View a markdown version of this page

Configurer le cluster Amazon EKS pour les AI/ML charges de travail à l'aide de Terraform - Amazon EKS

Aidez à améliorer cette page

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Pour contribuer à ce guide de l'utilisateur, cliquez sur le GitHub lien Modifier cette page qui se trouve dans le volet droit de chaque page.

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Configurer le cluster Amazon EKS pour les AI/ML charges de travail à l'aide de Terraform

Astuce

Inscrivez-vous aux prochains AI/ML ateliers Amazon EKS.

Cette section explique les étapes à suivre pour créer l'infrastructure requise pour exécuter des charges de travail de formation ou d'inférence sur Amazon EKS à l'aide de Terraform. Les étapes incluent la création d'un cluster EKS, de GPU-enabled nœuds avec EKS Auto Mode ou Karpenter, d'une pile de surveillance avec Prometheus et Grafana et du stockage Amazon S3 pour les pondérations des modèles.

Consultez la documentation relative au mode automatique EKS et à Karpenter pour plus d'informations sur la manière dont ces fonctionnalités provisionnent et dimensionnent automatiquement les instances EC2 dans les clusters EKS.

High-level architecture et flux de travail

High-level architecture affichant un <shared id=

Le schéma montre l'architecture AWS de haut niveau pour la configuration de cette section.

Conditions préalables

Important

Les ressources que vous créez dans ce didacticiel, notamment les clusters EKS, les instances GPU, les équilibreurs de charge des applications et Amazon Managed Service pour Prometheus, sont payantes. Supprimez les ressources lorsque vous avez terminé pour éviter des frais permanents.

Vérifiez les versions de vos outils :

terraform --version aws --version kubectl version --client jq --version

Étape 1 : Téléchargez et déployez le code Terraform

Cette procédure pas à pas utilise le code Terraform dans le référentiel d'échantillons AWS sample-eks-docs. GitHub Clonez le référentiel dans un répertoire de travail :

git clone git@github.com:aws-samples/sample-eks-docs.git cd sample-eks-docs/ai-ml/set-up-cluster

Le référentiel a la structure suivante dans le ai-ml/set-up-cluster/ répertoire dans lequel vous venez de changer :

set-up-cluster/
├── scripts/
│   └── cleanup.sh
└── terraform/
    ├── auto-mode/
    └── karpenter/

Le référentiel propose deux voies de déploiement. Choisissez-en une seule et utilisez-la tout au long du guide.

  • Mode automatique EKS (terraform/auto-mode/) : outre les principaux modules complémentaires de mise en réseau, de stockage et d'équilibrage de charge, le mode automatique EKS inclut et gère les fonctionnalités suivantes pour la formation et l'inférence des charges de travail : agent de surveillance des nœuds EKS, réparation automatique des nœuds, snapshotter SOCI pour une extraction rapide des conteneurs et préparation du GPU pour la configuration par défaut. NodeClass Le plug-in de périphérique NVIDIA est inclus dans l'AMI accélérée Bottlerocket qu'EKS Auto Mode utilise pour les nœuds. GPU-enabled

  • Self-managed Karpenter (terraform/karpenter/) — Sur un cluster EKS sans mode automatique EKS, le code Terraform installe et configure les composants requis pour les charges de travail de formation et d'inférence. Cela inclut des modules complémentaires réseau (VPC CNI, CoreDNS, kube-proxy), Karpenter, l'agent de surveillance des nœuds EKS, le plug-in de périphérique NVIDIA et le snapshotter SOCI pour une extraction rapide des conteneurs.

Important

Choisissez le mode automatique EKS ou Karpenter autogéré et utilisez-le tout au long du guide. Le basculement en cours de chaîne nécessite de détruire le cluster et de recommencer à zéro.

Options du cluster EKS : mode automatique EKS et Karpenter autogéré

Side-by-side comparaison des deux options de cluster : un cluster EKS Auto Mode avec un NodePool, et un cluster standard EKS avec Karpenter autogéré, CoreDNS, VPC CNI, un plug-in de périphérique NVIDIA, un agent EKS Pod Identity, un agent de surveillance des nœuds, kube-proxy, et NodeClass NodePool
Grafana est accessible au public via HTTP avec des informations d'identification par défaut

La Ingress valeur par défaut de Grafana ALB est0.0.0.0/0, ce qui expose Grafana var.my_cidr à l'Internet public via HTTP simple avec des informations d'identification d'administrateur par défaut. Les scanners automatisés détectent les équilibreurs de charge publics en quelques minutes. Vous devez restreindre l'accès en saisissant var.my_cidr votre propre adresse IP :

export MY_CIDR="$(curl -s https://checkip.amazonaws.com)/32" terraform apply -var "my_cidr=${MY_CIDR}"

Traitez la liste des adresses IP autorisées comme une garantie minimale, et non comme une garantie complète. Modifiez également le mot de passe administrateur Grafana par défaut après la première connexion. Pour une meilleure posture, changez le alb.ingress.kubernetes.io/scheme to internal (accessible uniquement depuis votre VPC ou un VPN connecté) et ajoutez un certificat TLS.

Déploiement du cluster

Accédez au répertoire correspondant au chemin que vous avez choisi, initialisez Terraform et appliquez :

Les deux variantes utilisent par défaut la us-east-2 région. Pour déployer dans une autre région, ajoutez -var "region=region-code" à la terraform apply commande de l'étape suivante la AWS région dans laquelle region-code vous souhaitez effectuer le déploiement.

Le code Terraform utilise toutes les zones de disponibilité disponibles dans la région cible, à l'exception de use1-az3usw1-az2, et cac1-az3 parce qu'Amazon EKS ne prend pas en charge le placement de plans de contrôle dans ces zones.

EKS Auto Mode
cd terraform/auto-mode terraform init terraform apply

L'exécution de cette commande prend quelques minutes.

Self-managed Karpenter
cd terraform/karpenter terraform init terraform apply

Cette commande prend environ 15 minutes. Il crée un cluster EKS avec un groupe de nœuds géré dédié à l'hébergement des modules complémentaires et du contrôleur Karpenter. Terraform installe Karpenter en activant la file d'attente d'interruptions ponctuelles et en activant les portes NodeRepair et StaticCapacity fonctionnalités. Il installe également le plug-in de périphérique NVIDIA, le AWS Load Balancer Controller et la pile de surveillance.

Passez en revue les sorties Terraform

Une fois l'application terminée, Terraform imprime les sorties suivantes (les valeurs varient en fonction de votre configuration) :

Apply complete! Resources: 74 added, 0 changed, 0 destroyed.

Outputs:

cluster_name         = "ai-eks-docs"
configure_kubectl    = "aws eks update-kubeconfig --region us-east-2 --name ai-eks-docs --alias ai-eks-docs"
configure_model_bucket = "export MODEL_BUCKET=ai-eks-docs-models-20250612abc1"
model_bucket         = "ai-eks-docs-models-20250612abc1"
node_iam_role_name   = "ai-eks-docs-eks-auto-20250612..."
region               = "us-east-2"

La configure_kubectl sortie est une commande prête à être exécutée qui kubectl pointe vers le cluster. La model_bucket sortie contient le nom du compartiment S3 pour les pondérations des modèles. La node_iam_role_name sortie indique le rôle IAM utilisé par les nœuds.

Configurer kubectl

kubectlPointez sur le nouveau cluster. La configure_kubectl sortie est une commande prête à être exécutée :

eval "$(terraform output -raw configure_kubectl)"

Vérifiez le cluster

EKS Auto Mode
kubectl get pods --all-namespaces

Sortie attendue :

NAMESPACE NAME READY STATUS RESTARTS AGE kube-system metrics-server-5db89f9ffd-h4mlr 1/1 Running 0 3m kube-system metrics-server-5db89f9ffd-nd748 1/1 Running 0 3m monitoring kube-prometheus-stack-grafana-ff9b5fd57-dh562 3/3 Running 0 3m monitoring kube-prometheus-stack-kube-state-metrics-5dcbfdf69b-wd6qn 1/1 Running 0 3m monitoring kube-prometheus-stack-operator-548c4f4485-m5wh2 1/1 Running 0 3m monitoring kube-prometheus-stack-prometheus-node-exporter-p2z7l 1/1 Running 0 3m monitoring prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 3m

En mode EKS Auto, le VPC CNI, kube-proxy et CoreDNS s'exécutent en tant que composants gérés et n'apparaissent pas sous forme de pods dans. kube-system

Self-managed Karpenter
kubectl get pods --all-namespaces

Les résultats attendus incluent Karpenter, CoreDNS, kube-proxy, aws-node (VPC CNI), l'agent EKS Pod Identity, l'agent de surveillance des nœuds EKS et le plug-in de périphérique NVIDIA :

NAMESPACE NAME READY STATUS RESTARTS AGE kube-system aws-node-bzdcz 2/2 Running 0 5m kube-system aws-node-vkbhb 2/2 Running 0 5m kube-system coredns-7dbb8998cf-9b9wk 1/1 Running 0 5m kube-system coredns-7dbb8998cf-pwtjd 1/1 Running 0 5m kube-system ebs-csi-controller-748f54b69-8h7jv 6/6 Running 0 5m kube-system ebs-csi-controller-748f54b69-v2mv8 6/6 Running 0 5m kube-system eks-node-monitoring-agent-5qw4l 1/1 Running 0 5m kube-system eks-node-monitoring-agent-7lrtm 1/1 Running 0 5m kube-system eks-pod-identity-agent-ddvlv 1/1 Running 0 5m kube-system eks-pod-identity-agent-q4g29 1/1 Running 0 5m kube-system karpenter-898ff78-cndbd 1/1 Running 0 5m kube-system karpenter-898ff78-hfbhn 1/1 Running 0 5m kube-system kube-proxy-gcfnh 1/1 Running 0 5m kube-system kube-proxy-tktcf 1/1 Running 0 5m kube-system metrics-server-5b789db597-cm9qd 1/1 Running 0 5m kube-system metrics-server-5b789db597-w57b6 1/1 Running 0 5m kube-system nvidia-device-plugin-node-feature-discovery-gc-66cb7f5dc-xvftc 1/1 Running 0 5m kube-system nvidia-device-plugin-node-feature-discovery-master-854d6b5hnqtp 1/1 Running 0 5m monitoring kube-prometheus-stack-grafana-6797bcb59f-2zlwg 3/3 Running 0 5m monitoring kube-prometheus-stack-kube-state-metrics-8446bd549c-q6gjc 1/1 Running 0 5m monitoring kube-prometheus-stack-operator-5f499b784-vf5xb 1/1 Running 0 5m monitoring kube-prometheus-stack-prometheus-node-exporter-4c6wq 1/1 Running 0 5m monitoring kube-prometheus-stack-prometheus-node-exporter-l5t25 1/1 Running 0 5m monitoring prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 5m

Vérifiez que le plug-in de l'appareil NVIDIA est installé. Aucun module de plug-in d'appareil n'apparaît tant qu'un GPU NodePool portant l'amiFamily=al2023étiquette correspondante n'est pas provisionné :

kubectl get daemonset nvidia-device-plugin -n kube-system

Sortie attendue :

NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE nvidia-device-plugin 0 0 0 0 0 amiFamily=al2023 5m

Étape 2 : Création d'un GPU dynamique NodePool

NodePools Les GPU sont optionnels. Par défaut, terraform apply crée le cluster et la pile de surveillance sans capacité GPU et sans facturation GPU. Pour provisionner des nœuds GPU, transmettez la nodepools variable avec un nom de stratégie.

Activez la spot-ondemand stratégie, qui provisionne des instances G-family GPU d'une génération supérieure à 4, en utilisant la capacité Spot On-Demand comme solution de repli :

terraform apply -var 'nodepools={"spot-ondemand"={}}'

Cette commande applique les NodeClass modèles NodePool et du nodepools/spot-ondemand/ répertoire. Les deux chemins utilisent la même NodePool API, mais leurs NodePool références diffèrent. NodeClass

EKS Auto Mode

Les NodePool références au gestionnaire default NodeClass, qui sélectionne déjà l'AMI accélérée Bottlerocket, les pilotes NVIDIA, le plug-in de périphérique NVIDIA et l'extraction parallèle SOCI. La spot-ondemand stratégie n' NodeClass est pas autonome dans cette voie.

Validez les éléments NodePool suivants :

kubectl get nodepools,nodeclasses

Sortie attendue. Les gpu-inf NodePool jointures sont intégrées general-purpose et system NodePools, toutes les trois, font référence à la gestion default NodeClass :

NAME NODECLASS NODES READY AGE nodepool.karpenter.sh/general-purpose default 0 True 12m nodepool.karpenter.sh/gpu-inf default 0 True 20s nodepool.karpenter.sh/system default 1 True 12m NAME ROLE READY AGE nodeclass.eks.amazonaws.com/default ai-eks-docs-eks-auto-... True 12m
Self-managed Karpenter

Terraform applique une coutume à gpu-inf EC2NodeClass côté du. NodePool Le code EC2NodeClass épingle l'alias AMI EKS-optimized AL2023, active SOCI via la porte des FastImagePull fonctionnalités et permet de déplacer le cache d'images conteneurisées instanceStorePolicy: RAID0 vers le NVMe local.

Validez le NodePool et EC2NodeClass :

kubectl get nodepools,ec2nodeclasses

Sortie attendue. La gpu-inf paire rejoint le general-purpose NodePool et EC2NodeClass que Terraform crée pour les charges de travail non GPU :

NAME NODECLASS NODES READY AGE nodepool.karpenter.sh/general-purpose general-purpose 1 True 14m nodepool.karpenter.sh/gpu-inf gpu-inf 0 True 25s NAME READY AGE ec2nodeclass.karpenter.k8s.aws/general-purpose True 14m ec2nodeclass.karpenter.k8s.aws/gpu-inf True 25s

Les deux chemins indiquent les 0 nœuds gpu-inf jusqu'à ce qu'une charge de travail du GPU soit planifiée. EKS Auto Mode et Karpenter ne lancent des nœuds que lorsque des pods en attente en ont besoin.

Étape 3 : Testez avec un échantillon de pod

Testez la NodePool configuration de votre GPU avec un nvidia-smi Pod :

cat << EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nvidia-smi labels: guide: ai-eks-docs spec: restartPolicy: OnFailure tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" containers: - name: nvidia-smi image: public.ecr.aws/amazonlinux/amazonlinux:2023-minimal command: ["nvidia-smi"] resources: limits: nvidia.com/gpu: 1 EOF

Vérifiez que le Pod est planifié et terminé correctement :

kubectl get pods nvidia-smi

Sortie attendue :

NAME         READY   STATUS      RESTARTS   AGE
nvidia-smi   0/1     Completed   0          67s

STATUS: CompletedCela signifie que la nvidia-smi commande a été exécutée et terminée. Consultez les journaux du Pod pour voir le GPU détecté par le nœud :

kubectl logs nvidia-smi

Sortie attendue :

+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.159.03             Driver Version: 580.159.03     CUDA Version: 13.0     |
+-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA L4                      On  |   00000000:31:00.0 Off |                    0 |
| N/A   41C    P8             13W /   72W |       0MiB /  23034MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

La sortie indique le modèle de GPU, la version du pilote, la version CUDA et la mémoire disponible. Dans cet exemple, Karpenter a provisionné une instance G6 dotée d'un GPU NVIDIA L4 avec 24 Go de mémoire. Le modèle de GPU et la mémoire varient en fonction du type d'instance sélectionné par Karpenter. Les instances G5 sont équipées de GPU NVIDIA A10G (24 Go), les instances G6 de GPU NVIDIA L4 (24 Go) et les instances G6e de GPU NVIDIA L40S (48 Go).

Pour comprendre comment Karpenter et le planificateur Kubernetes se sont coordonnés pour provisionner un nœud et placer le Pod, consultez les événements du cycle de vie du Pod :

kubectl describe pod nvidia-smi

Sortie attendue :

Events:
  Type     Reason            Age   From                   Message
  ----     ------            ----  ----                   -------
  Warning  FailedScheduling  75s   default-scheduler      0/2 nodes are available: 2 node(s) had untolerated taint(s).
  Normal   Nominated         74s   eks-auto-mode/compute  Pod should schedule on: nodeclaim/gpu-inf-z6q75
  Normal   Scheduled         35s   default-scheduler      Successfully assigned default/nvidia-smi to i-0eb897a8302551589
  Normal   Pulling           27s   kubelet                spec.containers{nvidia-smi}: Pulling image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal"
  Normal   Pulled            22s   kubelet                spec.containers{nvidia-smi}: Successfully pulled image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal" in 5.625s (5.626s including waiting). Image size: 37440620 bytes.
  Normal   Created           22s   kubelet                spec.containers{nvidia-smi}: Container created
  Normal   Started           21s   kubelet                spec.containers{nvidia-smi}: Container started

Ces événements indiquent la séquence de planification du Pod : le Pod échoue initialement à planifier car aucun nœud GPU n'existe (FailedScheduling), Karpenter en désigne un nouveau NodeClaim (Nominated), le planificateur attribue le Pod une fois que le nœud est prêt (Scheduled), puis l'image du conteneur est extraite et démarrée. Le mode EKS Auto dispose de l'extraction parallèle SOCI (Seekable OCI) installée et configurée par défaut sur les instances G, P et Trn, et le chemin Karpenter autogéré le configure explicitement via la porte des fonctionnalités. FastImagePull

Note

Sur un cluster Karpenter autogéré, l'Nominatedévénement s'affiche karpenter/compute au lieu de. eks-auto-mode/compute

A NodeClaim est une demande créée par Karpenter pour approvisionner un nœud spécifique. Il indique le type d'instance, le type de capacité, AZ, et indique si le nœud est prêt :

kubectl get nodeclaims

Sortie attendue :

NAME            TYPE        CAPACITY   ZONE         NODE                  READY   AGE
gpu-inf-z6q75   g6.xlarge   spot       us-east-2a   i-0eb897a8302551589   True    5m

Le type d'instance et l'AZ varient. Toute G-family instance dont la génération est supérieure à 4 est éligible.

Astuce

Si aucun nœud n'apparaît, vérifiez s'il y a des erreurs de capacité insuffisante :

kubectl get events | grep InsufficientCapacityError

Karpenter met en cache les offres non disponibles pendant 3 minutes. L'élargissement des types d'instances et des AZ autorisés dans votre instance NodePool augmente les chances d'obtenir de la capacité.

Note

Les instances Spot lancées par Karpenter n'apparaissent pas dans la console EC2 Spot Requests. Karpenter utilise l'CreateFleetAPI EC2 avec. type: instant Les instances apparaissent dans la console EC2 Instances avec un spot cycle de vie.

Étape 4 : Ajoutez de la capacité réservée au NodePool (facultatif)

Alors que le GPU NodePool de l'étape 2 provisionne le Spot ou On-Demand les instances de manière dynamique, certains cas d'utilisation nécessitent une capacité garantie. Vous pouvez créer une réservation On-Demand de capacité (ODCR) pour vous assurer que la capacité du GPU est disponible en cas de besoin.

Avec Terraform, une seule commande crée l'ODCR, une personnalisation NodeClass qui fait référence à la réservation par tag, et la met à jour NodePool pour l'inclure en reserved tant que type de capacité. Terraform étiquette l'ODCR avec nodepool=reserved-spot-ondemand et le NodeClass sélectionne par cette balise.

Avertissement

La commande suivante crée un ODCR qui facture immédiatement et continue à facturer jusqu'à ce que vous le détruisiez à l'aide du script de nettoyage terraform destroy ou du script de nettoyage, que des nœuds y soient exécutés ou non.

Utilisez les valeurs par défaut (g6e.4xlarge, 1 instance, premier cluster de A à Z) :

terraform apply -var 'nodepools={"reserved-spot-ondemand"={reservation={}}}'

Choisissez le type d'instance, le nombre et l'AZ :

terraform apply -var 'nodepools={"reserved-spot-ondemand"={reservation={instance_type="g6e.2xlarge",instance_count=1,az="us-east-2a"}}}'

L'reservationobjet prend en charge les champs suivants :

  • instance_type— Type d'instance GPU à réserver. Valeur par défaut : g6e.4xlarge.

  • instance_count— Le nombre d'instances à réserver. Valeur par défaut : 1.

  • az— La zone de disponibilité pour la réservation. Par défaut : "" (utilise le premier cluster AZ).

Important

Les reserved-spot-ondemand stratégies spot-ondemand et s'excluent mutuellement. Vous pouvez en activer au plus un dans la nodepools variable. Si vous l'avez déjà utilisée spot-ondemand à l'étape 2, la reserved-spot-ondemand commande la remplace car les deux gèrent la même chose gpu-inf NodePool.

Si vous obtenez une InsufficientInstanceCapacity erreur, la réservation ne peut pas être exécutée dans la zone Z spécifiée. Annulez l'opération Terraform (Ctrl+C), puis relancez-la avec une valeur différente : az

terraform apply -var 'nodepools={"reserved-spot-ondemand"={reservation={instance_type="g6e.4xlarge",az="us-east-2b"}}}'

Après l'application, Terraform met à jour les exigences NodePool pour inclure reservedspot, et on-demand dans les exigences de type de capacité. Karpenter considère reserved que c'est l'option la plus rentable et la lance en premier. Une fois la réservation complète, elle revient à Spot or On-Demand.

Sur le chemin du mode automatique EKS, Terraform crée une configuration personnalisée gpu-inf NodeClass (car le bundle default NodeClass est en lecture seule) qui fait référence à l'ODCR par balise. capacityReservationSelectorTerms Sur le chemin autogéré de Karpenter, Terraform réapplique le gpu-inf EC2NodeClass with capacityReservationSelectorTerms added et met à jour le to include. NodePool reserved

Vérifiez que l'ODCR a été créé :

aws ec2 describe-capacity-reservations \ --filters "Name=state,Values=active" "Name=tag:nodepool,Values=reserved-spot-ondemand" \ --query 'CapacityReservations[0].{Id:CapacityReservationId,State:State,InstanceType:InstanceType,AvailableCount:AvailableInstanceCount}' \ --output table \ --region $(terraform output -raw region)

Vérifiez les NodeClass références à l'ODCR :

EKS Auto Mode
kubectl get nodeclasses gpu-inf -o yaml | grep 'id: cr-.*'

Sortie attendue :

id: cr-xxxxxxxxxxxxxxxxx
Self-managed Karpenter
kubectl get ec2nodeclasses gpu-inf -o yaml | grep 'id: cr-.*'

Sortie attendue :

id: cr-xxxxxxxxxxxxxxxxx

Vérifiez NodePool qu'il est prêt :

kubectl get nodepools gpu-inf

Sortie attendue :

NAME      NODECLASS   NODES   READY   AGE
gpu-inf   gpu-inf     0       True    30s

Après avoir appliqué les modifications, vérifiez que Karpenter donne la priorité à la capacité réservée et revient à Spot ou. On-Demand Déployez un déploiement à 2 répliques qui nécessite 1 GPU par pod. L'ODCR est pour 1 instance (1 GPU), donc le premier Pod déclenche Karpenter pour qu'il lance un nœud réservé. Le second Pod ne peut pas tenir sur le nœud réservé et incite Karpenter à lancer un autre nœud depuis Spot ou On-Demand sa capacité.

cat << 'EOF' | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: gpu-overflow-test labels: guide: ai-eks-docs spec: replicas: 2 selector: matchLabels: app: gpu-overflow-test template: metadata: labels: app: gpu-overflow-test guide: ai-eks-docs spec: tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule containers: - name: nvidia-smi image: public.ecr.aws/amazonlinux/amazonlinux:2023-minimal command: ["sh", "-c", "nvidia-smi && sleep infinity"] resources: limits: nvidia.com/gpu: 1 EOF

Contrairement au pod de nvidia-smi test de l'étape 3 qui s'est exécuté et s'est terminé, ce déploiement permet aux pods de fonctionner (sleep infinity) afin qu'ils contiennent le GPU et empêchent la consolidation du nœud.

Vérifiez les Pods planifiés sur les différents nœuds :

kubectl get pods -l app=gpu-overflow-test -o wide

Sortie attendue :

NAME                                 READY   STATUS    RESTARTS   AGE     IP            NODE                  NOMINATED NODE   READINESS GATES
gpu-overflow-test-55d55ff5b9-dvg52   1/1     Running   0          4m42s   10.0.75.210   i-08741a36089ff2088   <none>           <none>
gpu-overflow-test-55d55ff5b9-hw4m9   1/1     Running   0          4m43s   10.0.82.49    i-0f50cdbacb2017202   <none>           <none>

Vérifiez NodeClaims les types de capacité :

kubectl get nodeclaims

Sortie attendue :

NAME            TYPE          CAPACITY   ZONE         NODE                  READY   AGE
gpu-inf-vw99m   g6e.4xlarge   reserved   us-east-2c   i-0f50cdbacb2017202   True    6m
gpu-inf-s65s6   g6.xlarge     spot       us-east-2b   i-08741a36089ff2088   True    5m59s

Le nœud réservé a été lancé en premier, suivi d'un Spot ou d'un On-Demand nœud une fois la réservation complète.

Nettoyez le déploiement des tests :

kubectl delete deployment gpu-overflow-test

Contrôle

Terraform a déjà provisionné la pile de surveillance complète lors terraform apply de l'étape 1. La pile comprend un espace de travail Amazon Managed Service for Prometheus (AMP), des politiques IAM et des associations d'identité de pod EKS pour l'écriture à distance de Prometheus et l'accès aux requêtes Grafana, le graphique Helm de la pile kube-prometheus (Prometheus, Grafana, kube-state-metrics, node-exporter) et l'exportateur NVIDIA DCGM pour les métriques GPU.

Cette section couvre la vérification des composants de surveillance déployés.

Vérifiez les modules de surveillance

Attendez que tous les modules de surveillance soient prêts :

kubectl wait --for=condition=Ready pod --all -n monitoring --timeout=300s kubectl get pods -n monitoring

Sortie attendue :

NAME                                                       READY   STATUS    RESTARTS   AGE
kube-prometheus-stack-grafana-7c58f54f77-rftrj             3/3     Running   0          5m
kube-prometheus-stack-kube-state-metrics-d68dcbc84-5smxq   1/1     Running   0          5m
kube-prometheus-stack-operator-5895df479f-ttm47            1/1     Running   0          5m
kube-prometheus-stack-prometheus-node-exporter-t9q7s       1/1     Running   0          5m
kube-prometheus-stack-prometheus-node-exporter-x6vfb       1/1     Running   0          5m
prometheus-kube-prometheus-stack-prometheus-0              2/2     Running   0          5m

Accédez à Grafana

Grafana est exposé via un équilibreur de charge d' AWS application (ALB) connecté à Internet, limité au CIDR que vous avez défini. var.my_cidr Imprimez l'URL de l'équilibreur de charge (attendez une minute ou deux pour que l'ALB soit provisionné) :

echo "http://$(kubectl get ingress kube-prometheus-stack-grafana -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')"

Ouvrez l'URL dans votre navigateur. Connectez-vous avec le nom d'utilisateur admin et le mot de passe à l'aide de la commande suivante :

kubectl --namespace monitoring get secrets kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 -d ; echo

Vérifiez le pipeline de métriques

Pour vérifier que le pipeline de métriques fonctionne de bout en bout :

  1. Accédez à Connexions > Sources de données et vérifiez qu'elle Amazon-Managed-Prometheus est répertoriée comme source de données par défaut.

    Validez la source de données AMP dans Grafana

    La page Grafana Connections s' Amazon-Managed-Prometheus affiche comme source de données par défaut
  2. Accédez à Drilldown > Metrics et recherchez la up métrique. Vous devriez voir les résultats des cibles de scrape de votre cluster.

    Validez la up métrique dans Grafana

    Page Grafana Drilldown Metrics affichant la métrique ascendante avec des barres d'état vertes indiquant les cibles de scrape actives

Si up les résultats s'affichent, le pipeline (cluster → Prometheus → AMP → Grafana) fonctionne.

Valider les métriques du GPU DCGM

L'exportateur DCGM DaemonSet s'exécute sur des nœuds GPU et indique l'utilisation du GPU, la mémoire, la température, la consommation électrique, la bande passante NVLink et les mesures d'activité des tenseurs.

Vérifiez l'exportateur DaemonSet DCGM :

kubectl get daemonset dcgm-exporter -n monitoring

Une fois qu'un nœud GPU est en cours d'exécution (à partir de l'étape 2 ou de l'étape 4), vous devriez voir apparaître un ou plusieurs pods prêts. Pour valider les métriques DCGM, accédez à Drilldown > Metrics in Grafana et recherchez. DCGM_

Validez les métriques DCGM dans Grafana

Page Grafana Drilldown Metrics filtrée par DCGM_ affichant les métriques GPU, notamment DCGM_FI_DEV_ECC_SBE_VOL_TOTAL, DCGM_FI_DEV_ENC_UTIL, DCGM_FI_DEV_DEV_FB_FREE et DCGM_FI_DEV_FB_USED

Pour afficher le tableau de bord, accédez à Tableaux de bord > Surveillance du GPU > Tableau de bord NVIDIA DCGM Exporter.

Tableau de bord de l'exportateur NVIDIA DCGM dans Grafana

Tableau de bord Grafana NVIDIA DCGM Exporter indiquant l'utilisation du GPU, la température moyenne du GPU, la mémoire mémoire du GPU utilisée et les panneaux de puissance totale du GPU

Le modèle pèse le godet S3

Terraform a déjà créé un compartiment Amazon S3 pour stocker les poids des modèles, un model-storage-sa ServiceAccount dans l'defaultespace de noms, une politique IAM limitée au compartiment et une association EKS Pod Identity qui les relie. Les modules de charge de travail qui définissent serviceAccountName: model-storage-sa peuvent lire et écrire dans le compartiment.

Vérifiez le compartiment

Récupérez le nom du compartiment à partir des sorties Terraform :

MODEL_BUCKET=$(terraform output -raw model_bucket) echo ${MODEL_BUCKET}

Vérifiez que le compartiment existe :

aws s3api head-bucket --bucket ${MODEL_BUCKET}

Sortie attendue :

{
    "BucketArn": "arn:aws:s3:::ai-eks-docs-models-20250612abc1",
    "BucketRegion": "us-east-2",
    "AccessPointAlias": false
}

Exécutez un pod unique avec l'image AWS CLI, en utilisant le model-storage-sa ServiceAccount, pour confirmer que EKS Pod Identity est câblé et que l'accès S3 fonctionne :

cat << EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: s3-test labels: guide: ai-eks-docs spec: serviceAccountName: model-storage-sa containers: - name: aws-cli image: public.ecr.aws/aws-cli/aws-cli:2.27.0 command: - sh - -c - | echo "=== Caller Identity ===" aws sts get-caller-identity echo "" echo "=== S3 Write Test ===" echo "pod identity works" | aws s3 cp - s3://${MODEL_BUCKET}/test.txt echo "" echo "=== S3 List Test ===" aws s3 ls s3://${MODEL_BUCKET}/ echo "" echo "=== S3 Delete Test ===" aws s3 rm s3://${MODEL_BUCKET}/test.txt restartPolicy: Never EOF

Attendez que le Pod soit terminé et vérifiez les journaux :

kubectl wait --for=jsonpath='{.status.phase}'=Succeeded pod/s3-test --timeout=300s kubectl logs s3-test

Sortie attendue :

=== Caller Identity ===
{
    "UserId": "AROA...:eks-ai-eks-docs-model-s-...",
    "Account": "123456789012",
    "Arn": "arn:aws:sts::123456789012:assumed-role/ai-eks-docs-models-.../eks-ai-eks-docs-..."
}

=== S3 Write Test ===
upload: - to s3://ai-eks-docs-models-20250612abc1/test.txt

=== S3 List Test ===
2026-07-15 12:00:00         19 test.txt

=== S3 Delete Test ===
delete: s3://ai-eks-docs-models-20250612abc1/test.txt

L'identité de l'appelant confirme que le Pod a assumé le rôle de stockage du modèle via EKS Pod Identity. Les commandes S3 confirment l'accès en lecture et en écriture.

Nettoyez le module de test :

kubectl delete pod s3-test

Étapes suivantes

Une fois votre cluster prêt, vous pouvez passer au modèle Load & Serve pour déployer un grand modèle de langage et interagir avec le point de terminaison d'inférence.

Nettoyage

Astuce

Si vous prévoyez de passer aux sections suivantes de ce guide, ignorez le nettoyage complet. Ne le lancez que lorsque vous avez terminé.

Supprimez les charges de travail de test afin qu'aucun pod ne contienne de nœuds GPU :

kubectl delete pod nvidia-smi --ignore-not-found kubectl delete deployment gpu-overflow-test --ignore-not-found

Si vous souhaitez uniquement libérer l'ODCR et revenir à Spot et à la On-Demand capacité, replacez la nodepools variable sur la spot-ondemand stratégie :

terraform apply -var 'nodepools={"spot-ondemand"={}}'

Cela réduit les exigences reserved de NodePool type de capacité et détruit l'ODCR, laissant le cluster, la pile de surveillance et le compartiment S3 en place.

Important

L'annulation d'une réservation ne met pas fin aux instances qui s'exécutent déjà sur celle-ci. Ces instances continuent de fonctionner à On-Demand des taux standard jusqu'à leur fermeture. Supprimez d'abord les charges de travail du GPU, comme indiqué ci-dessus, afin que le nœud réservé soit vidé avant que la réservation ne soit publiée.

Videz les Karpenter-managed nœuds avant de les détruire, afin qu'aucun cycle de vie des nœuds en vol ne bloque la destruction. Supprimez tous PodDisruptionBudgets ceux qui empêcheraient un drainage, puis supprimez les éléments NodeClaims suivants :

kubectl delete pdb -A --all --ignore-not-found kubectl delete nodeclaim --all --wait=true --timeout=900s

Détruisez ensuite tout ce que Terraform a créé, y compris le cluster EKS, le VPC, la pile de surveillance, le NodePools et NodeClasses, le compartiment du modèle S3 et tout ODCR :

terraform destroy
Avertissement

Le compartiment S3 est créé avec force_destroy = true les poids du modèle. Il terraform destroy supprime donc le compartiment ainsi que tous les poids des modèles que vous y avez chargés. Copiez d'abord tout ce que vous souhaitez conserver dans un autre emplacement.

Note

Le référentiel fournit également un scripts/cleanup.sh assistant qui exécute les étapes de vidange et de destruction ci-dessus, puis balaie tous les volumes EBS orphelins étiquetés avec le nom du cluster. Exécutez-le depuis le terraform/<mode>/ répertoire à partir duquel vous avez postulé et passez --auto-approve pour ignorer l'invite de confirmation de Terraform.

Vérifiez qu'il ne reste aucune réservation de capacité active pour le cluster :

aws ec2 describe-capacity-reservations \ --filters "Name=state,Values=active" "Name=tag:nodepool,Values=reserved-spot-ondemand" \ --query 'CapacityReservations[].CapacityReservationId' \ --output text

Un résultat vide signifie qu'aucune réservation n'est active et qu'aucun autre frais ne s'applique.