View a markdown version of this page

Amazon EKS-Cluster für AI/ML Workloads mit Terraform einrichten - Amazon EKS

Unterstützung für die Verbesserung dieser Seite beitragen

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Um zu diesem Benutzerhandbuch beizutragen, wählen Sie den GitHub Link Diese Seite bearbeiten unter, der sich im rechten Bereich jeder Seite befindet.

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Amazon EKS-Cluster für AI/ML Workloads mit Terraform einrichten

Tipp

Registrieren Sie sich für bevorstehende Amazon EKS-Workshops. AI/ML

Dieser Abschnitt führt Sie durch die Schritte zur Erstellung der Infrastruktur, die für die Ausführung von Schulungs- oder Inferenz-Workloads auf Amazon EKS mithilfe von Terraform erforderlich ist. Zu den Schritten gehören das Erstellen eines EKS-Clusters, GPU-enabled Knoten mit EKS Auto Mode oder Karpenter, ein Monitoring-Stack mit Prometheus und Grafana sowie Amazon S3-Speicher für Modellgewichte.

Weitere Informationen dazu, wie diese Funktionen EC2-Instances in EKS-Clustern bereitstellen und automatisch skalieren, finden Sie in der Dokumentation für EKS Auto Mode und Karpenter.

High-level Architektur und Arbeitsablauf

High-level Architektur, die eine <shared id= zeigt

Das Diagramm zeigt die AWS allgemeine Architektur für das Setup dieses Abschnitts.

Voraussetzungen

Wichtig

Für die Ressourcen, die Sie in diesem Tutorial erstellen, einschließlich EKS-Cluster, GPU-Instances, Application Load Balancers und Amazon Managed Service für Prometheus, fallen Gebühren an. Löschen Sie Ressourcen, wenn Sie fertig sind, um laufende Gebühren zu vermeiden.

Überprüfen Sie Ihre Toolversionen:

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

Schritt 1: Laden Sie den Terraform-Code herunter und stellen Sie ihn bereit

In dieser exemplarischen Vorgehensweise wird der Terraform-Code im Beispiel-Repository sample-eks-docs verwendet. https://github.com/aws-samples/sample-eks-docs AWS GitHub Klonen Sie das Repository in ein Arbeitsverzeichnis:

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

Das Projektarchiv hat die folgende Struktur unter dem ai-ml/set-up-cluster/ Verzeichnis, in das Sie gerade gewechselt haben:

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

Das Repository bietet zwei Bereitstellungspfade. Wählen Sie nur einen aus und verwenden Sie ihn im gesamten Handbuch.

  • EKS-Automatikmodus (terraform/auto-mode/) — Zusätzlich zu den wichtigsten Netzwerk-, Speicher- und Load-Balancing-Add-Ons umfasst und verwaltet EKS Auto Mode die folgenden Funktionen für Trainings- und Inferenz-Workloads: EKS-Node-Monitoring-Agent, automatische Node-Reparatur, https://github.com/awslabs/soci-snapshotter SOCI-Snapshotter für schnelle Container-Pulls und GPU-Bereitschaft für die Standardeinstellung. NodeClass Das NVIDIA-Geräte-Plugin ist im Bottlerocket-beschleunigten AMI enthalten, das EKS Auto Mode für Knoten verwendet. GPU-enabled

  • Self-managed Karpenter (terraform/karpenter/) — Auf einem EKS-Cluster ohne EKS-Auto-Modus installiert und konfiguriert der Terraform-Code die Komponenten, die für Trainings- und Inferenz-Workloads erforderlich sind. Dazu gehören Netzwerk-Add-Ons (VPC CNI, CoreDNS, Kube-Proxy), Karpenter, der EKS-Knotenüberwachungsagent, das NVIDIA-Geräte-Plugin und der SOCI-Snapshotter für schnelle Container-Pulls.

Wichtig

Wählen Sie entweder den EKS-Automodus oder den selbstverwalteten Karpenter aus und verwenden Sie ihn im gesamten Handbuch. Um mitten im Stream zu wechseln, muss der Cluster zerstört und von vorne begonnen werden.

EKS-Cluster-Optionen: EKS-Automatikmodus und selbstverwaltetes Karpenter

Side-by-side Vergleich der beiden Cluster-Optionen: ein EKS-Auto-Mode-Cluster mit einem und ein EKS-Standardcluster mit selbstverwaltetem Karpenter NodePool, CoreDNS, VPC CNI, NVIDIA-Geräte-Plugin, EKS Pod Identity Agent, Node Monitoring Agent, Kube-Proxy und a und NodeClass NodePool
Grafana ist öffentlich über HTTP mit Standardanmeldeinformationen zugänglich

Die Grafana ALB Ingress ist standardmäßig var.my_cidr auf eingestellt0.0.0.0/0, wodurch Grafana über einfaches HTTP mit Standard-Administratoranmeldedaten dem öffentlichen Internet zugänglich gemacht wird. Automatisierte Scanner erkennen öffentliche Load Balancer innerhalb von Minuten. Sie müssen den Zugriff einschränken, indem Sie var.my_cidr mit Ihrer eigenen IP-Adresse überschreiben:

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

Behandeln Sie die Quell-IP-Allowlisting als Mindestschutz, nicht als vollständigen Schutz. Ändern Sie auch das Standard-Grafana-Admin-Passwort nach der ersten Anmeldung. Für eine stärkere Haltung ändern Sie das alb.ingress.kubernetes.io/scheme auf internal (nur von Ihrer VPC oder einem verbundenen VPN aus erreichbar) und fügen Sie ein TLS-Zertifikat hinzu.

Bereitstellen des Clusters

Wechseln Sie in das Verzeichnis für den von Ihnen gewählten Pfad, initialisieren Sie Terraform und wenden Sie Folgendes an:

Beide Varianten verwenden standardmäßig die Region. us-east-2 Um in einer anderen Region bereitzustellen, fügen Sie -var "region=region-code" dem terraform apply Befehl im folgenden Schritt hinzu, in region-code welcher AWS Region Sie die Bereitstellung durchführen möchten.

Der Terraform-Code verwendet alle verfügbaren Availability Zones in der Zielregion, mit Ausnahme von use1-az3usw1-az2, und cac1-az3 weil Amazon EKS die Platzierung von Kontrollebenen in diesen Zonen nicht unterstützt.

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

Die Ausführung dieses Befehls dauert einige Minuten.

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

Dieser Befehl dauert etwa 15 Minuten. Es erstellt einen EKS-Cluster mit einer verwalteten Knotengruppe, die dem Hosten von Add-Ons und dem Karpenter Controller gewidmet ist. Terraform installiert Karpenter, wobei die Spot-Unterbrechungswarteschlange aktiviert ist und die Feature-Gates aktiviert sind. NodeRepair StaticCapacity Es installiert auch das NVIDIA-Geräte-Plugin, den Load AWS Balancer Controller und den Monitoring-Stack.

Überprüfen Sie die Terraform-Ausgaben

Wenn der Antrag abgeschlossen ist, druckt Terraform die folgenden Ausgaben aus (die Werte variieren je nach Ihrer Konfiguration):

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"

Die configure_kubectl Ausgabe ist ein ausführbarer Befehl, der auf den Cluster verweistkubectl. Die model_bucket Ausgabe enthält den S3-Bucket-Namen für Modellgewichte. Die node_iam_role_name Ausgabe zeigt die IAM-Rolle, die Knoten verwenden.

Konfigurieren Sie kubectl

Zeigen kubectl Sie auf den neuen Cluster. Die configure_kubectl Ausgabe ist ein sofort ausführbarer Befehl:

eval "$(terraform output -raw configure_kubectl)"

Überprüfen Sie den Cluster

EKS Auto Mode
kubectl get pods --all-namespaces

Erwartete Ausgabe:

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

Im EKS-Automatikmodus werden VPC-CNI, Kube-Proxy und CoreDNS als verwaltete Komponenten ausgeführt und erscheinen nicht als Pods in. kube-system

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

Zu den erwarteten Ausgaben gehören Karpenter, CoreDNS, Kube-Proxy, aws-node (VPC CNI), der EKS Pod Identity Agent, der EKS Node Monitoring Agent und das NVIDIA-Geräte-Plugin:

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

Stellen Sie sicher, dass das NVIDIA-Geräte-Plugin installiert ist. Es werden keine Geräte-Plug-In-Pods angezeigt, bis eine GPU NodePool mit dem passenden amiFamily=al2023 Label bereitgestellt wird:

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

Erwartete Ausgabe:

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

Schritt 2: Dynamische GPU erstellen NodePool

GPU NodePools sind optional. terraform applyErstellt standardmäßig den Cluster und den Monitoring-Stack ohne GPU-Kapazität und ohne GPU-Abrechnung. Um GPU-Knoten bereitzustellen, übergeben Sie die nodepools Variable mit einem Strategienamen.

Aktivieren Sie die spot-ondemand Strategie, die G-family GPU-Instances mit einer Generation von mehr als 4 bereitstellt, und verwenden Sie Spot-Kapazität mit On-Demand als Fallback:

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

Mit diesem Befehl werden die NodeClass Vorlagen NodePool und aus dem nodepools/spot-ondemand/ Verzeichnis angewendet. Beide Pfade verwenden dieselbe NodePool API, unterscheiden sich jedoch in NodeClass den NodePool Referenzen.

EKS Auto Mode

Die NodePool Referenzen sind das Managed default NodeClass, das bereits das Bottlerocket Accelerated AMI, die NVIDIA-Treiber, das NVIDIA-Geräte-Plugin und SOCI Parallel Pull auswählt. Die spot-ondemand Strategie eignet sich nicht NodeClass von selbst für diesen Weg.

Bestätigen Sie NodePool:

kubectl get nodepools,nodeclasses

Erwartete Ausgabe. Das gpu-inf NodePool verknüpft das integrierte general-purpose und system NodePools, und alle drei verweisen auf das verwaltete 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 wendet gpu-inf EC2NodeClass neben dem einen benutzerdefinierten Wert an. NodePool Der EC2NodeClass pinnt den EKS-optimized AL2023 AMI-Alias, aktiviert SOCI über das FastImagePull Feature Gate und legt fest, dass der enthaltene Image-Cache instanceStorePolicy: RAID0 auf das lokale NVMe verschoben wird.

Validieren Sie das und: NodePool EC2NodeClass

kubectl get nodepools,ec2nodeclasses

Erwartete Ausgabe. Das gpu-inf Paar schließt sich dem an general-purpose NodePool und EC2NodeClass , das Terraform für Nicht-GPU-Workloads erstellt:

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

Beide Pfade zeigen 0 Knoten an, gpu-inf bis ein GPU-Workload geplant ist. EKS Auto Mode und Karpenter starten Knoten nur, wenn ausstehende Pods sie benötigen.

Schritt 3: Testen Sie mit einem Beispiel-Pod

Testen Sie Ihr NodePool GPU-Setup mit einem 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

Stellen Sie sicher, dass der Pod geplant und erfolgreich abgeschlossen ist:

kubectl get pods nvidia-smi

Erwartete Ausgabe:

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

Das STATUS: Completed bedeutet, dass der nvidia-smi Befehl ausgeführt und beendet wurde. Sehen Sie in den Pod-Protokollen nach, welche GPU vom Knoten erkannt wurde:

kubectl logs nvidia-smi

Erwartete Ausgabe:

+-----------------------------------------------------------------------------------------+
| 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 |
+-----------------------------------------+------------------------+----------------------+

Die Ausgabe zeigt das GPU-Modell, die Treiberversion, die CUDA-Version und den verfügbaren Speicher. In diesem Beispiel hat Karpenter eine G6-Instanz bereitgestellt, die über eine NVIDIA L4-GPU mit 24 GB Arbeitsspeicher verfügt. Das GPU-Modell und der Arbeitsspeicher variieren je nach dem Instanztyp, den Karpenter auswählt. G5-Instances haben NVIDIA A10G-GPUs (24 GB), G6-Instances haben NVIDIA L4-GPUs (24 GB) und G6e-Instanzen haben NVIDIA L40S-GPUs (48 GB).

Um zu verstehen, wie Karpenter und der Kubernetes-Scheduler die Bereitstellung eines Knotens und die Platzierung des Pods koordiniert haben, schauen Sie sich die Lebenszyklus-Ereignisse des Pods an:

kubectl describe pod nvidia-smi

Erwartete Ausgabe:

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

Diese Ereignisse zeigen die Reihenfolge der Pod-Planung: Der Pod kann zunächst nicht geplant werden, weil keine GPU-Knoten vorhanden sind (FailedScheduling), Karpenter nominiert einen neuen NodeClaim (Nominated), der Scheduler weist den Pod zu, sobald der Knoten bereit ist (Scheduled), und dann wird das Container-Image abgerufen und gestartet. Im EKS-Auto-Modus ist SOCI (Seekable OCI) Parallel-Pull standardmäßig auf G-, P- und Trn-Instances installiert und konfiguriert, und der selbstverwaltete Karpenter-Pfad konfiguriert ihn explizit über das FastImagePull Feature Gate.

Anmerkung

Auf einem selbstverwalteten Karpenter-Cluster wird das Ereignis anstelle von angezeigt. Nominated karpenter/compute eks-auto-mode/compute

A NodeClaim ist eine Anfrage, die Karpenter erstellt, um einen bestimmten Knoten bereitzustellen. Es zeigt den Instanztyp, den Kapazitätstyp, AZ und ob der Knoten bereit ist:

kubectl get nodeclaims

Erwartete Ausgabe:

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

Der Instanztyp und AZ variieren. Jede G-family Instance mit einer Generation von mehr als 4 ist berechtigt.

Tipp

Wenn kein Knoten angezeigt wird, suchen Sie nach Fehlern bei unzureichender Kapazität:

kubectl get events | grep InsufficientCapacityError

Karpenter speichert nicht verfügbare Angebote 3 Minuten lang im Cache. Wenn Sie die zulässigen Instance-Typen und AZs in Ihrem System erweitern, NodePool erhöhen Sie die Wahrscheinlichkeit, dass Ihnen Kapazitäten zur Verfügung stehen.

Anmerkung

Spot-Instances, die von Karpenter gestartet wurden, werden nicht in der EC2 Spot Requests Console angezeigt. Karpenter verwendet die EC2-API CreateFleet mit. type: instant Die Instances werden in der EC2-Instanzen-Konsole mit einem Lebenszyklus angezeigt. spot

Schritt 4: Fügen Sie reservierte Kapazität zur hinzu NodePool (optional)

Während die GPU NodePool aus Schritt 2 Spot oder On-Demand Instances dynamisch bereitstellt, ist in einigen Anwendungsfällen eine garantierte Kapazität erforderlich. Sie können eine On-Demand Kapazitätsreservierung (ODCR) erstellen, um sicherzustellen, dass die GPU-Kapazität bei Bedarf verfügbar ist.

Bei Terraform erstellt ein einziger Befehl den ODCR, einen benutzerdefinierten NodeClass Wert, der die Reservierung anhand von Tags referenziert, und aktualisiert ihn, sodass er reserved als NodePool Kapazitätstyp aufgenommen wird. Terraform taggt das ODCR mit nodepool=reserved-spot-ondemand und wählt es dann anhand dieses Tags aus NodeClass .

Warnung

Mit dem folgenden Befehl wird ein ODCR erstellt, das sofort fakturiert wird, und setzt die Abrechnung fort, bis Sie es mit terraform destroy oder dem Bereinigungsskript löschen, unabhängig davon, ob Knoten darauf laufen oder nicht.

Verwenden Sie Standardwerte (g6e.4xlarge, 1 Instanz, erster Cluster AZ):

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

Wählen Sie den Instanztyp, die Anzahl und die AZ aus:

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

Das reservation Objekt unterstützt die folgenden Felder:

  • instance_type— Der zu reservierende GPU-Instanztyp. Standard: g6e.4xlarge.

  • instance_count— Die Anzahl der zu reservierenden Instanzen. Standard: 1.

  • az— Die Availability Zone für die Reservierung. Standard: "" (verwendet den ersten Cluster AZ).

Wichtig

Die reserved-spot-ondemand Strategien spot-ondemand und schließen sich gegenseitig aus. Sie können höchstens eine in der nodepools Variablen aktivieren. Wenn Sie ihn zuvor spot-ondemand in Schritt 2 verwendet haben, wird er durch den reserved-spot-ondemand Befehl ersetzt, da beide dasselbe verwalten gpu-inf NodePool.

Wenn Sie eine InsufficientInstanceCapacity Fehlermeldung erhalten, kann die Reservierung in der angegebenen AZ nicht erfüllt werden. Brechen Sie den Terraform-Vorgang ab (Strg+C) und führen Sie ihn erneut mit einem anderen Wert aus: az

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

Nach der Anwendung aktualisiert Terraform die Anforderungen, um den Kapazitätstyp NodePool einzubeziehenreserved, und in den Kapazitätstyp spot einzubeziehen. on-demand Karpenter betrachtet es als die kostengünstigste Option reserved und bringt sie als erstes auf den Markt. Sobald die Reservierung vollständig ist, fällt sie auf Spot oder zurück. On-Demand

Auf dem EKS-Automodus-Pfad erstellt Terraform ein benutzerdefiniertes Objekt gpu-inf NodeClass (da das Paket schreibgeschützt default NodeClass ist), das das ODCR per Tag-through referenziert. capacityReservationSelectorTerms Auf dem selbstverwalteten Karpenter-Pfad wendet Terraform das mit hinzugefügtem Element erneut an und aktualisiert es auf Include. gpu-inf EC2NodeClass capacityReservationSelectorTerms NodePool reserved

Stellen Sie sicher, dass das ODCR erstellt wurde:

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)

Überprüfen Sie, ob die NodeClass ODCR referenziert wird:

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

Erwartete Ausgabe:

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

Erwartete Ausgabe:

id: cr-xxxxxxxxxxxxxxxxx

Stellen Sie sicher, NodePool dass der bereit ist:

kubectl get nodepools gpu-inf

Erwartete Ausgabe:

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

Nachdem Sie die Änderungen übernommen haben, überprüfen Sie, ob Karpenter der reservierten Kapazität Priorität einräumt und auf Spot oder zurückgreift. On-Demand Stellen Sie eine Bereitstellung mit 2 Replikaten bereit, die 1 GPU pro Pod anfordert. Der ODCR gilt für eine Instance (1 GPU), sodass der erste Pod Karpenter veranlasst, einen reservierten Knoten zu starten. Der zweite Pod passt nicht auf den reservierten Knoten und veranlasst Karpenter, einen weiteren Knoten von Spot oder Kapazität aus zu starten. On-Demand

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

Im Gegensatz zum nvidia-smi Test-Pod aus Schritt 3, der ausgeführt und beendet wurde, hält dieses Deployment die Pods am Laufen (sleep infinity), sodass sie die GPU enthalten und verhindern, dass der Knoten konsolidiert wird.

Überprüfen Sie, ob die Pods auf verschiedenen Knoten geplant sind:

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

Erwartete Ausgabe:

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>

Überprüfen Sie das NodeClaims , um die Kapazitätstypen zu sehen:

kubectl get nodeclaims

Erwartete Ausgabe:

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

Der reservierte Knoten wurde zuerst gestartet, gefolgt von einem Spot oder On-Demand Knoten, sobald die Reservierung vollständig war.

Bereinigen Sie die Testbereitstellung:

kubectl delete deployment gpu-overflow-test

Überwachen

Terraform hat bereits in Schritt 1 den gesamten Monitoring-Stack bereitgestelltterraform apply. Der Stack umfasst einen Amazon Managed Service for Prometheus (AMP) -Workspace, IAM-Richtlinien und EKS-Pod Identity Associations für Prometheus-Fernschreib- und Grafana-Abfragezugriff, das Kube-Prometheus-Stack-Helm-Diagramm (Prometheus, Grafana, kube-state-metrics, node-exporter) und den NVIDIA DCGM Exporter für GPU-Metriken.

In diesem Abschnitt wird die Überprüfung der eingesetzten Überwachungskomponenten behandelt.

Überprüfen Sie die Monitoring-Pods

Warten Sie, bis alle Monitoring-Pods bereit sind:

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

Erwartete Ausgabe:

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

Greifen Sie auf Grafana zu

Grafana wird über einen mit dem Internet verbundenen AWS Application Load Balancer (ALB) verfügbar gemacht, der auf den von Ihnen eingestellten CIDR beschränkt ist. var.my_cidr Drucken Sie die Load Balancer-URL aus (warten Sie ein oder zwei Minuten, bis der ALB die Bereitstellung abgeschlossen hat):

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

Öffnen Sie die URL in Ihrem Browser. Loggen Sie sich mit dem Benutzernamen admin und dem Passwort aus dem folgenden Befehl ein:

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

Überprüfen Sie die Metrik-Pipeline

Gehen Sie wie folgt vor, um zu überprüfen, ob die Metrik-Pipeline durchgängig funktioniert:

  1. Navigieren Sie zu Verbindungen > Datenquellen und bestätigen Sie, dass dies als Standarddatenquelle aufgeführt Amazon-Managed-Prometheus ist.

    Validieren Sie die AMP-Datenquelle in Grafana

    Die Seite „Grafana-Verbindungen“ wird als Amazon-Managed-Prometheus Standarddatenquelle aufgeführt
  2. Navigieren Sie zu Drilldown > Metriken und suchen Sie nach der Metrik. up Sie sollten Ergebnisse aus den Scrape-Zielen Ihres Clusters sehen.

    Validieren Sie die up Metrik in Grafana

    Seite mit Grafana-Drilldown-Metriken, auf der die Aufwärtsmetrik mit grünen Statusleisten angezeigt wird, die auf aktive Scrape-Ziele hinweisen

Wenn Ergebnisse up angezeigt werden, funktioniert die Pipeline (Cluster → Prometheus → AMP → Grafana).

Validieren Sie DCGM-GPU-Metriken

Der DCGM-Exporter DaemonSet wird auf GPU-Knoten ausgeführt und meldet GPU-Auslastung, Speicher, Temperatur, Stromverbrauch, NVLink-Bandbreite und Tensor-Aktivitätsmetriken.

Überprüfen Sie den DCGM-Exporter: DaemonSet

kubectl get daemonset dcgm-exporter -n monitoring

Sobald ein GPU-Knoten läuft (ab Schritt 2 oder Schritt 4), sollten Sie einen oder mehrere bereite Pods sehen. Um DCGM-Metriken zu validieren, navigieren Sie in Grafana zu Drilldown > Metriken und suchen Sie nach. DCGM_

Validieren Sie die DCGM-Metriken in Grafana

Die nach DCGM_ gefilterte Seite mit Grafana-Drilldown-Metriken zeigt GPU-Metriken wie DCGM_FI_DEV_ECC_SBE_VOL_TOTAL, DCGM_FI_DEV_ENC_UTIL, DCGM_FI_DEV_FB_FREE und DCGM_FI_DEV_FB_USED

Um das Dashboard anzuzeigen, navigieren Sie zu Dashboards > GPU-Überwachung > NVIDIA DCGM Exporter-Dashboard.

Das NVIDIA DCGM Exporter-Dashboard in Grafana

Das Grafana NVIDIA DCGM Exporter-Dashboard zeigt die Panels GPU-Auslastung, GPU Avg Temp, GPU-Framebuffer Mem Used und GPU Power Total

Das Modell wiegt den S3-Eimer

Terraform hat bereits einen Amazon S3-Bucket zum Speichern von Modellgewichten erstellt, einen model-storage-sa ServiceAccount im default Namespace, eine IAM-Richtlinie für den Bucket und eine EKS Pod Identity Association, die sie verknüpft. Workload-Pods, die festgelegt sind, serviceAccountName: model-storage-sa können aus dem Bucket lesen und in den Bucket schreiben.

Überprüfen Sie den Bucket

Rufen Sie den Bucket-Namen aus den Terraform-Ausgaben ab:

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

Stellen Sie sicher, dass der Bucket existiert:

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

Erwartete Ausgabe:

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

Führen Sie einen einmaligen Pod mit dem AWS CLI-Image aus und verwenden Sie dabei den, um zu bestätigen model-storage-sa ServiceAccount, dass EKS Pod Identity verkabelt ist und der S3-Zugriff funktioniert:

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

Warten Sie, bis der Pod fertig ist, und überprüfen Sie die Protokolle:

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

Erwartete Ausgabe:

=== 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

Die Identität des Anrufers bestätigt, dass der Pod über EKS Pod Identity die Rolle des Modellspeichers übernommen hat. Die S3-Befehle bestätigen den Lese- und Schreibzugriff.

Bereinigen Sie den Test-Pod:

kubectl delete pod s3-test

Nächste Schritte

Wenn Ihr Cluster bereit ist, können Sie mit Load & Serve Model fortfahren, um ein umfangreiches Sprachmodell bereitzustellen und mit dem Inferenzendpunkt zu interagieren.

Bereinigen

Tipp

Wenn Sie mit den nächsten Abschnitten dieses Handbuchs fortfahren möchten, überspringen Sie die vollständige Bereinigung. Führen Sie es erst aus, wenn Sie fertig sind.

Löschen Sie die Test-Workloads, sodass keine Pods GPU-Knoten enthalten:

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

Wenn Sie nur den ODCR veröffentlichen und auf Spot und On-Demand Kapazität zurückgreifen möchten, stellen Sie die nodepools Variable wieder auf die spot-ondemand Strategie um:

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

Dadurch fallen die Anforderungen reserved an den NodePool Kapazitätstyp weg und das ODCR wird zerstört. Der Cluster, der Monitoring-Stack und der S3-Bucket bleiben unverändert.

Wichtig

Durch das Stornieren einer Reservierung werden Instances, die bereits auf dieser Reservierung ausgeführt werden, nicht beendet. Diese Instances laufen zu On-Demand Standardtarifen weiter, bis sie beendet werden. Löschen Sie zuerst die GPU-Workloads, wie oben gezeigt, damit der reservierte Knoten leer wird, bevor die Reservierung freigegeben wird.

Entleeren Sie die Karpenter-managed Knoten, bevor Sie sie zerstören, sodass kein laufender Knotenlebenszyklus die Zerstörung blockiert. Löschen Sie alle PodDisruptionBudgets Elemente, die einen Drain verhindern würden, und löschen Sie dann: NodeClaims

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

Zerstören Sie dann alles, was Terraform erstellt hat, einschließlich des EKS-Clusters, der VPC, des Monitoring-Stacks, des NodePools und NodeClasses, des S3-Modell-Buckets und aller ODCR:

terraform destroy
Warnung

Das Modellgewicht, mit dem der S3-Bucket erstellt wurdeforce_destroy = true, terraform destroy löscht also den Bucket zusammen mit allen Modellgewichten, die Sie darauf hochgeladen haben. Kopieren Sie zuerst alles, was Sie behalten möchten, an einen anderen Ort.

Anmerkung

Das Repository enthält auch ein scripts/cleanup.sh Hilfsprogramm, das die oben genannten Schritte Drain und Destroy ausführt und dann alle verwaisten EBS-Volumes, die mit dem Clusternamen markiert sind, entfernt. Führen Sie es in dem terraform/<mode>/ Verzeichnis aus, aus dem Sie sich beworben haben, und geben Sie den Befehl ein, um die --auto-approve Terraform-Bestätigungsaufforderung zu überspringen.

Vergewissern Sie sich, dass für den Cluster keine aktive Kapazitätsreservierung mehr vorhanden ist:

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

Ein leeres Ergebnis bedeutet, dass keine Reservierung aktiv ist und keine weiteren Gebühren anfallen.