

 **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 mithilfe von CLIs einrichten
<a name="ml-cluster-setup-cli"></a>

**Tipp**  
 [Registrieren Sie sich ](https://events.eksworkshop.com/workshops/genai/) 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 CLI-Befehlen 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 ](https://docs.aws.amazon.com/eks/latest/userguide/automode.html) und automatisch skalieren, finden Sie in der Dokumentation [ für EKS Auto Mode und ](https://karpenter.sh/docs/) Karpenter.

 **High-level Architektur und Arbeitsablauf ** 

![High-level Architektur NodePool, die den EKS-Cluster mit Karpenter NodeClass und den Grafana- und Prometheus-Monitoring-Stack beim Schreiben in Amazon Managed Service für Prometheus, einen Amazon S3-Bucket für Modellgewichte und die nummerierten Workflow-Schritte zeigt](https://docs.aws.amazon.com/de_de/eks/latest/userguide/images/ml-cluster-setup-architecture.png)


Das Diagramm zeigt die AWS allgemeine Architektur für das Setup dieses Abschnitts. Die nummerierten Schritte auf der rechten Seite geben die Reihenfolge an, in der Sie die Konfiguration in den folgenden Schritten abschließen.

## Voraussetzungen
<a name="cluster-setup-cli-prerequisites"></a>

**Wichtig**  
Für die Ressourcen, die Sie in diesem Tutorial erstellen, einschließlich EKS-Cluster, GPU-Instances, Application Load Balancers und Amazon Managed Service for Prometheus, fallen Gebühren an. Löschen Sie Ressourcen, wenn Sie fertig sind, um laufende Gebühren zu vermeiden.
+  `kubectl`>= 1,36. Anweisungen zur Einrichtung finden Sie unter. [Richten Sie `kubectl und eksctl ein` ``](install-kubectl.md)
+  AWS CLI >= 2.27. Anweisungen zur Einrichtung finden Sie unter [ Installieren. ](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)
+ Helm >= 3.14. Anweisungen zur Einrichtung finden Sie unter Helm [ einrichten. ](helm.md)
+  `jq`. Anweisungen zur Einrichtung finden Sie unter [ Laden Sie jq ](https://jqlang.github.io/jq/download/) herunter.
+  `eksctl`>= 0,227,0. Anweisungen zur Einrichtung finden Sie in der Dokumentation unter [ Installation](https://eksctl.io/installation). `eksctl`

Überprüfen Sie Ihre `eksctl` Version:

```
eksctl version
```

Wenn Sie eine Version verwenden, die älter als 0.227.0 ist, folgen Sie der [ eksctl-Installationsanleitung, um auf die neueste Version ](https://eksctl.io/installation/) zu aktualisieren.

## Festlegen von Umgebungsvariablen
<a name="cluster-setup-cli-set-environment-variables"></a>

Achten Sie bei diesen Schritten darauf, dass der folgende Clustername und die folgende AWS Region konsistent sind. Eine Änderung kann dazu führen, dass nachfolgende Befehle auf den falschen EKS-Cluster abzielen.

```
export CLUSTER_NAME=ai-eks-docs
export AWS_REGION=us-east-2
```

Die Verwendung aller verfügbaren AZs verbessert die Fehlertoleranz und erhöht die Wahrscheinlichkeit, GPU-Kapazität zu erhalten:

```
export AZS=$(aws ec2 describe-availability-zones \
  --region ${AWS_REGION} \
  --query "AvailabilityZones[?ZoneId!='use1-az3' && ZoneId!='usw1-az2' && ZoneId!='cac1-az3'].ZoneName" \
  --output text | tr '\t' ',')
echo $AZS
```

**Wichtig**  
Die Availability Zones `use1-az3``usw1-az2`, und `cac1-az3` sind ausgeschlossen, da [ Amazon EKS die Platzierung der Steuerungsebene in diesen Zonen nicht unterstützt](https://repost.aws/knowledge-center/eks-cluster-creation-errors). Das Erstellen eines Clusters mit Subnetzen in einer dieser Zonen führt zu einem`UnsupportedAvailabilityZoneException`.

Erwartete Ausgabe:

```
us-east-2a,us-east-2b,us-east-2c
```

Die AZs in der Ausgabe variieren je nach Region. Dieses Beispiel zeigt die verfügbaren AZs für die `us-east-2` Region.

## Cluster und GPU erstellen NodePool
<a name="cluster-setup-cli-create-cluster-and-gpu-nodepool"></a>

Dieser Abschnitt enthält zwei Pfade zum Erstellen Ihres EKS-Clusters und Ihrer GPU-enabled EKS-Knoten, wie in der folgenden Abbildung dargestellt. Wählen Sie in der Anleitung nur eine Option aus.
+  **EKS-Automatikmodus ** — Zusätzlich zu den wichtigsten [ Netzwerk-, Speicher- und Load-Balancing-Add-Ons ](https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html#addon-consider-auto) 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](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 ** — Auf einem EKS-Cluster ohne EKS Auto Mode sind Sie für die Installation und Konfiguration der Komponenten verantwortlich, die für Trainings- und Inferenz-Workloads erforderlich sind. Dazu gehören Netzwerk-Add-Ons (VPC CNI, CoreDNS, Kube-Proxy), Karpenter, der EKS-Node-Monitoring-Agent, das NVIDIA-Geräte-Plugin und der SOCI-Snapshotter für schnelle Container-Pulls.

 **EKS-Cluster-Optionen: EKS Auto Mode 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](https://docs.aws.amazon.com/de_de/eks/latest/userguide/images/ml-cluster-setup-cli-cluster-options.png)


Wählen Sie in jedem der folgenden Schritte einen Pfad (EKS Auto Mode, Karpenter) und folgen Sie ihm durchgehend. Nachdem Sie die Schritte für den von Ihnen gewählten Pfad abgeschlossen haben, haben Sie einen EKS-Cluster mit einer GPU, die NodePool bereit ist, GPU-Workloads zu planen.

## Schritt 1: Cluster erstellen
<a name="cluster-setup-cli-create-cluster"></a>

Erstellen Sie zunächst Ihren EKS-Cluster und installieren Sie die Cluster-Komponenten, die für GPU-Workloads benötigt werden.

Im EKS-Automatikmodus wird mit einem einzigen `eksctl create cluster --enable-auto-mode` Befehl ein EKS-Cluster bereitgestellt, der für GPU-Workloads bereit ist.

Bei selbstverwaltetem Karpenter stellt der `eksctl create cluster` Befehl die wichtigsten Netzwerk-Add-Ons bereit. Anschließend sind zusätzliche Schritte erforderlich, um die automatische Knotenreparatur über ein Karpenter Feature Gate zu aktivieren, den EKS-Node-Monitoring-Agenten zu installieren und das NVIDIA-Geräte-Plug-In zu installieren.

------
#### [ EKS Auto Mode ]

 **Erstellen Sie einen EKS-Auto-Mode-Cluster ** 

```
eksctl create cluster \
  --name=$CLUSTER_NAME \
  --region=$AWS_REGION \
  --enable-auto-mode \
  --version=1.36 \
  --zones=$AZS
```

Die Ausführung dieses Befehls dauert einige Minuten. Nach Abschluss wird Ihre kubeconfig-Datei `eksctl` automatisch aktualisiert, damit sie mit dem neu bereitgestellten Cluster funktioniert. Stellen Sie sicher, dass der Cluster betriebsbereit ist:

```
kubectl get pods --all-namespaces
```

Erwartete Ausgabe:

```
NAMESPACE     NAME                              READY   STATUS    RESTARTS   AGE
kube-system   metrics-server-55cf976ddd-cz2mw   1/1     Running   0          3m
kube-system   metrics-server-55cf976ddd-wrjvv   1/1     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`

 **Erstellen Sie den Standard StorageClass ** 

GPU-Workloads benötigen häufig persistenten Speicher, um beispielsweise Modellgewichte zwischenzuspeichern, damit Kubernetes sie nicht bei jedem Pod-Neustart erneut herunterlädt. Der EKS-Automatikmodus beinhaltet eine integrierte Blockspeicherfunktion, sodass Sie den Amazon EBS-CSI-Treiber nicht installieren müssen. Erstellen Sie eine`StorageClass`, die auf den Auto Mode Provisioner verweist:

```
cat << EOF | kubectl apply -f -
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gp3
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.eks.amazonaws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
  type: gp3
  encrypted: "true"
EOF
```

Dieser Befehl erstellt einen `gp3` `StorageClass` und markiert ihn mit der `storageclass.kubernetes.io/is-default-class` Anmerkung als Cluster-Standard. Alles, `PersistentVolumeClaim` was weggelassen wird, `storageClassName` verwendet dies`StorageClass`. Die `volumeBindingMode: WaitForFirstConsumer` Einstellung verzögert die Volume-Erstellung, bis Kubernetes einen Pod plant, sodass das EBS-Volume in derselben Availability Zone wie der Pod landet.

------
#### [ Self-managed Karpenter ]

 **Authentifizieren Sie Helm beim öffentlichen ECR ** 

 `eksctl`ruft das Karpenter Helm-Diagramm aus Amazon Public ECR ab. Authentifizieren Sie sich, bevor Sie den Cluster erstellen, um einen 403-Fehler bei der Helm-Installation zu vermeiden:

```
aws ecr-public get-login-password --region us-east-1 \
  | helm registry login --username AWS --password-stdin public.ecr.aws
```

Public ECR ist ein globaler Dienst, der in gehostet wird. `us-east-1` Verwenden Sie es `--region us-east-1` hier, unabhängig davon, in welcher Region sich Ihr EKS-Cluster befindet.

Erwartete Ausgabe: `Login Succeeded` 

 **Erstellen Sie den EKS-Cluster mit Karpenter ** 

Speichern Sie Ihre Karpenter-Version in einer Umgebungsvariablen zur späteren Verwendung. Die neuesten Karpenter-Versionen finden Sie in den Karpenter-Versionen am[. ](https://github.com/aws/karpenter-provider-aws/releases) GitHub

```
export KARPENTER_VERSION=1.14.0
```

**Example Cluster-Konfiguration (YAML)**  

```
cat << EOF > /tmp/cluster-karpenter.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: ${CLUSTER_NAME}
  region: ${AWS_REGION}
  version: "1.36"
  tags:
    karpenter.sh/discovery: ${CLUSTER_NAME}

availabilityZones: [$(echo $AZS | sed 's/,/, /g')]

autoModeConfig:
  enabled: false

iam:
  withOIDC: true

karpenter:
  version: "${KARPENTER_VERSION}"
  withSpotInterruptionQueue: true

managedNodeGroups:
  - name: system
    instanceTypes: ["m6i.2xlarge", "m5.2xlarge", "m6a.2xlarge", "m5a.2xlarge", "m7i.2xlarge"]
    desiredCapacity: 2
    minSize: 2
    maxSize: 3
    labels:
      node-role: system
    tags:
      karpenter.sh/discovery: ${CLUSTER_NAME}

addons:
  - name: eks-pod-identity-agent
  - name: eks-node-monitoring-agent
  - name: aws-ebs-csi-driver
EOF
```

Die `system` verwaltete Knotengruppe listet mehrere Instanztypen derselben Größe (8 vCPU, 32 GiB) statt eines einzelnen Typs auf. Wenn ein Typ in einer Availability Zone vorübergehend nicht verfügbar ist, fällt die Auto Scaling-Gruppe der Knotengruppe auf einen anderen Typ zurück, wodurch `InsufficientInstanceCapacity` Startfehler vermieden werden. Bei einer On-Demand verwalteten Knotengruppe müssen alle aufgelisteten Instanztypen dieselbe vCPU und denselben Arbeitsspeicher haben, damit die Knotengröße einheitlich ist.

Erstellen Sie den Cluster mit der Konfigurationsdatei:

```
eksctl create cluster -f /tmp/cluster-karpenter.yaml
```

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. Bei der Installation von Karpenter ist die Spot-Unterbrechungswarteschlange aktiviert, sodass Spot-Unterbrechungen und Empfehlungen zur Neuverteilung verarbeitet werden können. Die `autoModeConfig.enabled: false` Einstellung macht deutlich, dass dieser Cluster den EKS-Automatikmodus nicht verwendet, sodass die in diesem Pfad installierten Karpenter-Komponenten für die Knotenverwaltung verantwortlich sind.

Auf dem Cluster werden außerdem der [ EKS Pod Identity Agent](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html), der [ EKS-Knotenüberwachungsagent ](https://docs.aws.amazon.com/eks/latest/userguide/node-health.html) und der Amazon EBS-CSI-Treiber als EKS-Add-Ons installiert. EKS Pod Identity wird später in der Anleitung verwendet. Der EKS-Knotenüberwachungsagent läuft auf jedem Knoten und liest Kernelprotokolle, um Knotenbedingungen wie`AcceleratedHardwareReady`, und festzulegen`KernelReady`, anhand derer die automatische Knotenreparatur von Karpenter entscheidet`NetworkingReady`, wann ein defekter Knoten ersetzt werden muss.

Stellen Sie sicher, dass der Cluster betriebsbereit ist:

```
kubectl get pods --all-namespaces
```

Zu den erwarteten Ausgaben gehören Karpenter, CoreDNS, Kube-Proxy, aws-node (VPC CNI), der EKS Pod Identity Agent und der EKS Node Monitoring Agent.

```
NAMESPACE     NAME                              READY   STATUS    RESTARTS   AGE
karpenter     karpenter-567547464c-s6vkx        1/1     Running   0          3m40s
karpenter     karpenter-567547464c-x7gmw        1/1     Running   0          3m40s
kube-system   aws-node-b6gf2                    2/2     Running   0          12m
kube-system   aws-node-lcphh                    2/2     Running   0          12m
kube-system   coredns-7d4dcbf4fb-ccvrr          1/1     Running   0          16m
kube-system   coredns-7d4dcbf4fb-qbhk2          1/1     Running   0          16m
kube-system   eks-node-monitoring-agent-h79vm   1/1     Running   0          9m45s
kube-system   eks-node-monitoring-agent-tf4dw   1/1     Running   0          9m45s
kube-system   eks-pod-identity-agent-5jbtc      1/1     Running   0          12m
kube-system   eks-pod-identity-agent-rwcrc      1/1     Running   0          12m
kube-system   kube-proxy-p4bmq                  1/1     Running   0          12m
kube-system   kube-proxy-v5nwr                  1/1     Running   0          12m
kube-system   metrics-server-5b966ff79c-hr58p   1/1     Running   0          9m22s
kube-system   metrics-server-5b966ff79c-szs2d   1/1     Running   0          9m22s
```

 **Aktivieren Sie die Karpenter Feature Gates ** 

Der EKS-Automatikmodus ermöglicht standardmäßig die automatische Knotenreparatur und die statische Kapazität. Bei selbstverwaltetem Karpenter müssen Sie das `NodeRepair` Feature-Gate und das `StaticCapacity` Gate für Static explizit aktivieren. Dadurch wird eine feste Anzahl von Knoten beibehalten NodePools, `spec.replicas` anstatt als Reaktion auf ausstehende Pods zu skalieren. Beide Gates sind Alpha und in Karpenter standardmäßig ausgeschaltet. Der folgende Befehl patcht den Einsatz von Karpenter, um beide Gates zu aktivieren. Die Aktualisierung der Bereitstellungsumgebung löst einen Rollout der Karpenter Pods aus:

```
kubectl set env deployment/karpenter -n karpenter \
  FEATURE_GATES=NodeRepair=true,StaticCapacity=true
```

Erwartete Ausgabe:

```
deployment.apps/karpenter env updated
```

Warten Sie, bis die Karpenter Pods eingeführt sind:

```
kubectl rollout status deployment/karpenter -n karpenter
```

 **Installieren Sie das NVIDIA-Geräte-Plugin ** 

Das EKS-optimized AL2023 AMI enthält das [ NVIDIA-Geräte-Plugin nicht ](https://github.com/NVIDIA/k8s-device-plugin) (im Gegensatz zum Bottlerocket-AMI, das von EKS Auto Mode verwendet wird). Installieren Sie es über Helm, um die GPU-Ressourcen mit Pods im Cluster nutzbar zu machen.

```
helm repo add nvdp https://nvidia.github.io/k8s-device-plugin
helm repo update
```

```
cat << 'EOF' > /tmp/nvdp-values.yaml
mofedEnabled: false
nodeSelector:
  amiFamily: al2023
gfd:
  enabled: true
nfd:
  worker:
    tolerations:
      - operator: "Exists"
EOF
```

```
helm install nvidia-device-plugin nvdp/nvidia-device-plugin \
  --namespace kube-system \
  -f /tmp/nvdp-values.yaml
```
+  `mofedEnabled: false`: deaktiviert die Prüfung auf Mellanox OFED (InfiniBand), die nicht verwendet wird AWS 
+  `nodeSelector.amiFamily: al2023`: erstreckt sich nur DaemonSet auf die beiden AL2023-Knoten (Bottlerocket hat das Plugin bereits eingebaut)
+  `gfd.enabled: true`: aktiviert GPU Feature Discovery-Labels (`nvidia.com/gpu.product`, usw.) `nvidia.com/gpu.memory`

Stellen Sie sicher, dass das NVIDIA-Geräte-Plugin installiert ist. Es wird erwartet, dass es keine Geräte-Plugin-Pods gibt, bis eine GPU NodePool mit dem passenden 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   2m5s
```

Erstellen Sie als Nächstes eine NodePool Allzweckversion. In der `system` verwalteten Knotengruppe werden die Add-Ons und Controller ausgeführt. Fügen Sie einen Allzweck-Karpenter hinzu, `NodePool` sodass Workloads, die keine GPUs sind, bei Bedarf skaliert werden können, ohne auf den Knoten zu landen. `system` Die GPU wird später in Schritt 2 `NodePool` erstellt. [Schritt 2: Dynamische GPU erstellen NodePool](#cluster-setup-cli-create-gpu-nodepool)

<a name="cluster-setup-cli-step1-karpenter-general-nodepool-yaml"></a> **General-purpose EC2NodeClass und NodePool YAML ** 

```
cat << EOF | kubectl apply -f -
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: general-purpose
spec:
  role: "eksctl-KarpenterNodeRole-${CLUSTER_NAME}"
  amiSelectorTerms:
    - alias: al2023@latest
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: ${CLUSTER_NAME}
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: ${CLUSTER_NAME}
  tags:
    karpenter.sh/discovery: ${CLUSTER_NAME}
---
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: general-purpose
spec:
  template:
    spec:
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: general-purpose
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["on-demand"]
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["c", "m", "r"]
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["4"]
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"]
  limits:
    cpu: 1000
    memory: 1000Gi
EOF
```

Dies NodePool hat keine Makel, sodass jeder Pod, der den GPU-Taint nicht toleriert, darauf planen kann.

 **Erstellen Sie den Standard StorageClass ** 

GPU-Workloads benötigen häufig persistenten Speicher, um beispielsweise Modellgewichte zwischenzuspeichern, damit Kubernetes sie nicht bei jedem Pod-Neustart erneut herunterlädt. Der Amazon EBS-CSI-Treiber wurde bereits zu Beginn dieses Schritts `addons:` blockweise in der Cluster-Konfiguration installiert. Sie müssen also nur Folgendes erstellen: `StorageClass`

```
cat << EOF | kubectl apply -f -
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gp3
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
  type: gp3
  encrypted: "true"
EOF
```

Dieser Befehl erstellt einen `gp3` `StorageClass` und markiert ihn mit der `storageclass.kubernetes.io/is-default-class` Anmerkung als Cluster-Standard. Alles, `PersistentVolumeClaim` was weggelassen wird, `storageClassName` verwendet dies`StorageClass`. Die `volumeBindingMode: WaitForFirstConsumer` Einstellung verzögert die Volume-Erstellung, bis Kubernetes einen Pod plant, sodass das EBS-Volume in derselben Availability Zone wie der Pod landet.

------

**Warnung**  
Sowohl für den EKS-Automodus als auch für den selbstverwalteten Karpenter-Pfad verhält sich die automatische Knotenreparatur für Knoten, die von bereitgestellt wurden, auf dieselbe Weise. NodePools Die automatische Knotenreparatur im EKS-Auto-Modus und in Karpenter ist eine Methode der * gewaltsamen * Unterbrechung, bei der die Anmerkungen und umgangen werden. PodDisruptionBudgets `karpenter.sh/do-not-disrupt` `terminationGracePeriod` Die automatische Knotenreparatur wartet 10 Minuten, bevor ein Knoten ersetzt wird, dessen `AcceleratedHardwareReady` Zustand auf auf gesetzt ist, `False` und 30 Minuten für andere Reparaturbedingungen. [https://docs.aws.amazon.com/eks/latest/userguide/node-repair.html](https://docs.aws.amazon.com/eks/latest/userguide/node-repair.html)

### Richten Sie den Lastenausgleich ein
<a name="cluster-setup-cli-loadbalancing"></a>

In späteren Schritten in diesem Handbuch wird Grafana (und in der Inferenz-Komplettlösung ein Modellendpunkt) über einen AWS Application Load Balancer (ALB) verfügbar gemacht. Richten Sie jetzt die Voraussetzungen für den Lastenausgleich ein, damit diese Abschnitte ohne weitere Einrichtung einen erstellen können. `Ingress`

Das ALB wird anhand von Ressourcen-Tags in Ihren VPC-Subnetzen platziert. AWS Öffentliche Subnetze, die für mit dem Internet verbundene Load Balancer verwendet werden, müssen mit `kubernetes.io/role/elb` = gekennzeichnet werden`1`, und private Subnetze, die für interne Load Balancer verwendet werden, müssen mit = gekennzeichnet sein. `kubernetes.io/role/internal-elb` `1` Da Sie diesen Cluster mit erstellt haben`eksctl`, sind diese Tags bereits in den erstellten Subnetzen vorhanden. `eksctl` Wenn Sie Ihre eigene VPC oder importierte Subnetze mitbringen, kennzeichnen Sie sie manuell. Details hierzu finden Sie unter [Kennzeichnung von Subnetzen für EKS Auto Mode](tag-subnets-auto.md).

#### Erstellen Sie den Load Balancer IngressClass
<a name="_create_the_load_balancer_ingressclass"></a>

Der Rest des Setups unterscheidet sich je nach Pfad. Der EKS-Automatikmodus enthält einen integrierten ALB-Controller, sodass Sie einen `IngressClass` selbst erstellen können. Self-managed Karpenter erfordert die Installation des Load AWS Balancer Controllers mit Helm, und das Helm-Diagramm erstellt den für Sie. `IngressClass`

------
#### [ EKS Auto Mode ]

Der EKS-Automatikmodus enthält einen integrierten ALB-Controller, sodass Sie keine zusätzlichen Komponenten installieren müssen. Erstellen Sie einen `IngressClass` Namen`alb`, der auf den integrierten Controller zeigt. Jede Klasse, die `Ingress` Sie später erstellen, verweist namentlich auf diese Klasse und legt ihr eigenes Schema und andere Optionen mithilfe von Anmerkungen fest.

```
cat << EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: alb
spec:
  controller: eks.amazonaws.com/alb
EOF
```

------
#### [ Self-managed Karpenter ]

Der Load AWS Balancer Controller ist kein EKS-managed Add-on und kann daher nicht wie der EBS-CSI-Treiber in den `eksctl` `addons:` Cluster-Konfigurationsblock eingefügt werden. Installieren Sie es mit Helm.

 **Laden Sie die IAM-Richtlinie herunter ** 

Der Controller benötigt IAM-Berechtigungen, um ALBs zu erstellen und zu verwalten. Laden Sie die offizielle IAM-Richtlinie im JSON-Format herunter:

```
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json
```

Erstellen Sie die IAM-Richtlinie:

```
aws iam create-policy \
  --policy-name AWSLoadBalancerControllerIAMPolicy \
  --policy-document file://iam_policy.json
```

 **Erstellen Sie die Pod Identity-Zuordnung ** 

Der Cluster installiert das `eks-pod-identity-agent` Add-on bereits in [ Schritt 1](#cluster-setup-cli-create-cluster), sodass EKS Pod Identity verfügbar ist. Erstellen Sie eine Pod Identity-Zuordnung, die die IAM-Richtlinie an das Dienstkonto des Controllers bindet:

```
eksctl create podidentityassociation \
  --cluster ${CLUSTER_NAME} \
  --region ${AWS_REGION} \
  --namespace kube-system \
  --service-account-name aws-load-balancer-controller \
  --permission-policy-arns arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):policy/AWSLoadBalancerControllerIAMPolicy
```

 **Mit Helm installieren ** 

Fügen Sie das Helm-Repository für EKS-Diagramme hinzu:

```
helm repo add eks https://aws.github.io/eks-charts
helm repo update
```

Suchen Sie nach der VPC-ID Ihres Clusters. Die Helm-Werte benötigen sie, damit der Controller Subnetze erkennen kann:

```
VPC_ID=$(aws eks describe-cluster \
  --name ${CLUSTER_NAME} \
  --region ${AWS_REGION} \
  --query 'cluster.resourcesVpcConfig.vpcId' \
  --output text)
```

Installieren Sie den Controller. Aufgrund der Toleranz `nodeSelector` und der Toleranz wird der Controller in der `system` verwalteten Knotengruppe neben der clusterkritischen Infrastruktur platziert, anstatt mit GPU- oder Karpenter-launched Allzweckknoten um die Kapazität zu konkurrieren:

```
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  --namespace kube-system \
  --version 3.4.2 \
  --set clusterName=${CLUSTER_NAME} \
  --set region=${AWS_REGION} \
  --set vpcId=${VPC_ID} \
  --set serviceAccount.create=true \
  --set serviceAccount.name=aws-load-balancer-controller \
  --set "nodeSelector.node-role=system" \
  --set "tolerations[0].key=CriticalAddonsOnly" \
  --set "tolerations[0].operator=Exists"
```

Stellen Sie sicher, dass der Controller läuft. Es sollte zwei verfügbare Replikate melden:

```
kubectl get deployment aws-load-balancer-controller -n kube-system
```

 **Überprüfen Sie das IngressClass ** 

Das Helm-Diagramm erstellt im `alb` Rahmen der Controller-Installation einen `IngressClass` Namen, der auf den selbstverwalteten Controller `ingress.k8s.aws/alb` verweist. Sie müssen es nicht manuell erstellen. Bestätigen Sie, dass es existiert:

```
kubectl get ingressclass alb
```

Erwartete Ausgabe:

```
NAME   CONTROLLER            PARAMETERS   AGE
alb    ingress.k8s.aws/alb   <none>       22s
```

------

Beide Pfade haben jetzt eine `alb``IngressClass`. Die Abschnitte Grafana und Inferenz verweisen auf das ALB-Schema, die Quell-IP-Zulassungsliste `ingressClassName: alb` und anderes Verhalten und legen diese durch Per-Annotationen fest. `Ingress`

## Schritt 2: Dynamische GPU erstellen NodePool
<a name="cluster-setup-cli-create-gpu-nodepool"></a>

Definieren Sie eine NodePool , die G-family GPU-Instances mit einer Generation von mehr als 4 und weniger als 7 dynamisch bereitstellt und Spot-Kapazität On-Demand als Fallback verwendet. Die Pfade EKS Auto Mode und Karpenter verwenden beide dieselbe NodePool API, mit dem einzigen Unterschied, dass NodeClass sie darauf verweist. Im EKS-Auto-Modus wählt das Paket `default` NodeClass bereits das richtige AMI aus und konfiguriert den SOCI-Parallel-Pull, sodass das das einzige Objekt NodePool ist, das Sie erstellen. Im selbstverwalteten Karpenter benötigen Sie außerdem ein benutzerdefiniertes System, `EC2NodeClass` das das AMI anheftet und SOCI optimiert.

**Wichtig**  
Für den G7 EC2-Instance-Typ ist die NVIDIA-Treiberversion 595 oder höher erforderlich. Die EKS-optimized beschleunigten AMIs enthalten derzeit die NVIDIA-Treiberversion 580, die G7-Instances nicht unterstützt. NodePool In diesem Schritt beschränkt sich die Instanzgenerierung auf weniger als 7, sodass Karpenter keine G7-Instance auswählt. Um G7-Instances mit Amazon EKS zu verwenden, müssen Sie ein benutzerdefiniertes AMI mit der NVIDIA-Treiberversion 595 erstellen. Weitere Informationen finden Sie unter [Verwenden Sie EKS-optimized beschleunigte AMIs für GPU-Instances](ml-eks-optimized-ami.md).

------
#### [ EKS Auto Mode ]

Im EKS-Auto-Modus wählt das Paket `default` NodeClass automatisch das Bottlerocket-AMI für GPU-Instances aus, das vorinstallierte NVIDIA-Treiber, das NVIDIA-Geräte-Plugin und SOCI-Parallel-Pull umfasst. Sie müssen nur eine anwenden, die auf Folgendes verweist: NodePool `default` NodeClass

```
cat << 'EOF' | kubectl apply -f -
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: gpu-inf
spec:
  template:
    metadata:
      labels:
        guide: ai-eks-docs
    spec:
      nodeClassRef:
        group: eks.amazonaws.com
        kind: NodeClass
        name: default
      taints:
        - key: nvidia.com/gpu
          effect: NoSchedule
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot", "on-demand"]
        - key: eks.amazonaws.com/instance-category
          operator: In
          values: ["g"]
        - key: eks.amazonaws.com/instance-generation
          operator: Gt
          values: ["4"]
        - key: eks.amazonaws.com/instance-generation
          operator: Lt
          values: ["7"]
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"]
  limits:
    cpu: 1000
    memory: 5000Gi
EOF
```

Dadurch NodePool werden G-family GPU-Instances mit einer Generation größer als 4 und weniger als 7 ([G5](https://aws.amazon.com/ec2/instance-types/g5/), [ G6e usw.) ](https://aws.amazon.com/ec2/instance-types/g6e/) bereitgestellt. EKS Auto Mode wählt einen Instanztyp innerhalb dieser Einschränkungen aus.

------
#### [ Self-managed Karpenter ]

Self-managed Karpenter enthält keine Standardeinstellung. NodeClass Sie erstellen zunächst eine`EC2NodeClass`, die den EKS-optimized NVIDIA AL2023 AMI-Alias anheftet, SOCI über das `FastImagePull` Feature Gate aktiviert und so konfiguriert, dass der Containerd-Image-Cache `instanceStorePolicy: RAID0` auf das lokale NVMe verschoben wird. Dann erstellen Sie den, der darauf verweist. NodePool 

 **Erstellen Sie den EC2NodeClass ** 

**Example**  

```
cat << EOF | kubectl apply -f -
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: gpu-inf
  labels:
    guide: ai-eks-docs
spec:
  role: "eksctl-KarpenterNodeRole-${CLUSTER_NAME}"
  amiSelectorTerms:
    - alias: al2023@latest
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: ${CLUSTER_NAME}
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: ${CLUSTER_NAME}
  tags:
    karpenter.sh/discovery: ${CLUSTER_NAME}
  instanceStorePolicy: RAID0
  userData: |
    apiVersion: node.eks.aws/v1alpha1
    kind: NodeConfig
    spec:
      featureGates:
        FastImagePull: true
EOF
```

 `instanceStorePolicy: RAID0`baut lokale NVMe-Festplatten zu einem RAID-0 Array zusammen. Der `al2023@latest` AMI-Alias wird in das AL2023 AMI aufgelöst. EKS-optimized Wenn Karpenter einen GPU-Instance-Typ startet, wählt es automatisch die beschleunigte Variante AL2023\_x86\_64\_NVIDIA aus, die den NVIDIA-Treiber vorinstalliert enthält.

Das `FastImagePull` Feature Gate ermöglicht den Parallel-Pull-Modus von SOCI Snapshotter, der Bildebenen gleichzeitig herunterlädt und entpackt. Dies entspricht dem EKS-Auto-Modus-Verhalten bei den Instance-Familien G, P und Trn.

Weitere SOCI-Tuning-Optionen (gleichzeitige Downloads pro Bild, Chunk-Größe usw.) finden Sie im Karpenter SOCI-Blueprint. [https://github.com/aws-samples/karpenter-blueprints/tree/main/blueprints/soci-snapshotter](https://github.com/aws-samples/karpenter-blueprints/tree/main/blueprints/soci-snapshotter)

 EC2NodeClassValidieren Sie:

```
kubectl get ec2nodeclass gpu-inf
```

Erwartete Ausgabe:`READY True`. Wenn`False`, führen Sie aus `kubectl describe ec2nodeclass gpu-inf` und überprüfen Sie die Bedingungen für fehlende Subnetz- oder Sicherheitsgruppen-Tags.

 **Erstellen Sie die GPU NodePool ** 

**Example**  

```
cat << EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: gpu-inf
spec:
  template:
    metadata:
      labels:
        guide: ai-eks-docs
        amiFamily: al2023
    spec:
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: gpu-inf
      taints:
        - key: nvidia.com/gpu
          effect: NoSchedule
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot", "on-demand"]
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["g"]
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["4"]
        - key: karpenter.k8s.aws/instance-generation
          operator: Lt
          values: ["7"]
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"]
  limits:
    cpu: 1000
    memory: 5000Gi
EOF
```

Das `amiFamily: al2023` Label auf der Knotenvorlage DaemonSet verwendet das NVIDIA-Geräte-Plugin, um diese Knoten auszuwählen. Karpenter wählt einen Instanztyp innerhalb dieser Einschränkungen aus. Der `nvidia.com/gpu:NoSchedule` Makel stellt sicher, dass nur GPU-eligible Pods auf diesen Knoten geplant sind.

------

Bestätigen Sie, NodePool dass das erstellt wurde:

```
kubectl get nodepool gpu-inf
```

Erwartete Ausgabe:

```
NAME      NODECLASS   NODES   READY   AGE
gpu-inf   default     0       True    8s
```

Auf dem selbstverwalteten Karpenter-Pfad wird in der Spalte NODECLASS anstelle von angezeigt. `gpu-inf` `default`

## Schritt 3: Testen Sie mit einem Beispiel-Pod
<a name="cluster-setup-cli-test-with-a-sample-pod"></a>

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:
  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
  restartPolicy: OnFailure
EOF
```

Vergewissern Sie sich, dass der Pod geplant ist und erfolgreich abgeschlossen wurde.

```
kubectl get pods
```

Erwartete Ausgabe:

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

Der STATUS: Abgeschlossen bedeutet, dass der Befehl nvidia-smi 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:35:00.0 Off |                    0 |
| N/A   42C    P8             16W /   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. 42C ist die aktuelle GPU-Temperatur und P8 ist ein Leerlaufzustand mit geringem Stromverbrauch, was zu erwarten ist, da kein Workload die GPU nutzt. 16 W/72 W zeigen den aktuellen Stromverbrauch im Vergleich zur maximalen Leistungskapazität an, und 0 MiB/23034 MiB zeigt den aktuell genutzten GPU-Speicher im Vergleich zum verfügbaren Gesamtspeicher an. Da auf dem Pod gerade nvidia-smi ausgeführt und beendet wurde, wird die GPU von keiner Workload beansprucht, sodass der Arbeitsspeicher auf 0 steht und die Stromversorgung im Leerlauf ist. Die NVIDIA-GPU-Treiberversion (580.159.03) stammt aus dem Bottlerocket-AMI, während die CUDA-Version (13.0) aus dem Container-Image stammt. 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-Instances 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 po nvidia-smi
```

Erwartete Ausgabe:

```
Events:
  Type     Reason                  Age   From                   Message
  ----     ------                  ----  ----                   -------
  Warning  FailedScheduling        60s   default-scheduler      0/2 nodes are available: 2 node(s) had untolerated taint(s). no new claims to deallocate, preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.
  Normal   Nominated               59s   eks-auto-mode/compute  Pod should schedule on: nodeclaim/gpu-inf-vxcnj
  Normal   Scheduled               24s   default-scheduler      Successfully assigned default/nvidia-smi to i-0fb17a09bc4203164
  Warning  FailedCreatePodSandBox  21s   kubelet                Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "7f85e25b220c8fb245187758dbbbc8efb3d40f3e49e13054404880daf4c3b2f0": plugin type="aws-cni" name="aws-cni" failed (add): add cmd: failed to setup network policy
  Normal   Pulling                  7s   kubelet                spec.containers{nvidia-smi}: Pulling image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal"
  Normal   Pulled                   5s   kubelet                spec.containers{nvidia-smi}: Successfully pulled image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal" in 1.237s (1.237s including waiting). Image size: 37442701 bytes.
  Normal   Created                  5s   kubelet                spec.containers{nvidia-smi}: Container created
  Normal   Started                  5s   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-Automatikmodus ist SOCI (Seekable OCI) Parallel Pull auf G-, P- und Trn-Instances sofort installiert und konfiguriert. Beachten Sie, dass das Container-Image aufgrund des SOCI-Parallel-Pulls in weniger als 2 Sekunden (1,237 s) aus dem ECR abgerufen wurde.

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 NodeClaim Ausgabe:

```
NAME            TYPE         CAPACITY   ZONE         NODE                  READY   AGE
gpu-inf-vxcnj   g6.4xlarge   spot       us-east-2c   i-0fb17a09bc4203164   True    51s
```

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

Die `FailedCreatePodSandBox` Warnung in `kubectl describe pod nvidia-smi` ist vorübergehend und wird erwartet. Das VPC-CNI wird asynchron initialisiert, nachdem der Knoten beigetreten ist, und das Kubelet versucht es automatisch erneut. Wenn der Pod aktiv bleibt, überprüfen Sie die Knotenereignisse mit. `ContainerCreating` `kubectl describe node <node-name>`

**Tipp**  
Wenn kein Knoten angezeigt wird, überprüfen Sie, ob Fehler bei unzureichender Kapazität vorliegen:  

```
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 mit. [`CreateFleet`](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateFleet.html) `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)
<a name="cluster-setup-cli-attach-odcr"></a>

Um die reservierte Kapazität zuerst mit Spot/On-Demand Fallback zu verwenden, erstellen Sie eine On-Demand Kapazitätsreservierung (ODCR) und fügen Sie sie Ihrer hinzu. Aktualisieren Sie dann die Dynamik NodePool aus Schritt 2 NodeClass, sodass auch Kapazität zugelassen `reserved` wird. Der Reservierungs-API-Aufruf ist für beide Pfade identisch. Der NodeClass Anhang unterscheidet sich, da EKS Auto Mode und selbstverwaltetes Karpenter unterschiedliche Typen verwenden. NodeClass 

**Warnung**  
Der folgende Befehl führt zu einer Gebühr für den reservierten Instance-Typ, bis Sie ihn mit kündigen. `aws ec2 cancel-capacity-reservation --capacity-reservation-id <id>`

Erstellen Sie die Kapazitätsreservierung:

```
CR_AZ="us-east-2a"
INSTANCE_TYPE="g6e.4xlarge"

aws ec2 create-capacity-reservation \
  --instance-type $INSTANCE_TYPE \
  --instance-platform Linux/UNIX \
  --availability-zone "$CR_AZ" \
  --instance-count 1 \
  --instance-match-criteria open \
  --end-date-type unlimited
```

Wenn Sie eine `InsufficientInstanceCapacity` Fehlermeldung erhalten, wechseln Sie `CR_AZ` zu einer anderen AZ und versuchen Sie es erneut.

Suchen Sie die Kapazitätsreservierungs-ID und speichern Sie sie in einer Shell-Variablen für die folgenden Schritte:

```
CAPACITY_RESERVATION_ID=$(aws ec2 describe-capacity-reservations \
  --filters "Name=state,Values=active" "Name=instance-type,Values=${INSTANCE_TYPE}" \
  --query 'CapacityReservations[0].CapacityReservationId' \
  --output text \
  --region ${AWS_REGION})
echo "Capacity reservation ID: ${CAPACITY_RESERVATION_ID}"
```

Wenden Sie dann die NodePool Änderungen NodeClass und für Ihren Pfad an:

------
#### [ EKS Auto Mode ]

Im EKS-Auto-Modus `default` NodeClass ist das Paket schreibgeschützt. Erstellen Sie also ein benutzerdefiniertes Objekt, NodeClass das auf die Reservierung verweist, aktualisieren Sie es, sodass es NodePool auf die zeigt, NodeClass und fügen Sie der Liste `reserved` Kapazität hinzu. `capacity-type`

**Example Benutzerdefiniertes YAML NodeClass**  

```
NODE_ROLE=$(kubectl get nodeclass default -o jsonpath='{.spec.role}')

cat << EOF | kubectl apply -f -
apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
  name: gpu-inf
  labels:
    guide: ai-eks-docs
spec:
  role: "$NODE_ROLE"
  subnetSelectorTerms:
    - tags:
        alpha.eksctl.io/cluster-name: "$CLUSTER_NAME"
        kubernetes.io/role/internal-elb: "1"
  securityGroupSelectorTerms:
    - tags:
        aws:eks:cluster-name: "$CLUSTER_NAME"
  capacityReservationSelectorTerms:
    - id: "$CAPACITY_RESERVATION_ID"
EOF
```

Das `kubernetes.io/role/internal-elb: "1"` Tag stellt sicher, dass Knoten nur in privaten Subnetzen gestartet werden.

Aktualisieren Sie das NodePool , um das zu verwenden, ODCR-backed NodeClass und fügen Sie Folgendes `reserved` als Kapazitätstyp hinzu:

**Example NodePool YAML wurde aktualisiert**  

```
cat << EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: gpu-inf
spec:
  template:
    metadata:
      labels:
        guide: ai-eks-docs
    spec:
      nodeClassRef:
        group: eks.amazonaws.com
        kind: NodeClass
        name: gpu-inf
      taints:
        - key: nvidia.com/gpu
          effect: NoSchedule
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot", "on-demand", "reserved"]
        - key: eks.amazonaws.com/instance-category
          operator: In
          values: ["g"]
        - key: eks.amazonaws.com/instance-generation
          operator: Gt
          values: ["4"]
        - key: eks.amazonaws.com/instance-generation
          operator: Lt
          values: ["7"]
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"]
  limits:
    cpu: 1000
    memory: 5000Gi
EOF
```

------
#### [ Self-managed Karpenter ]

Wenden Sie bei selbstverwaltetem Karpenter die in Schritt 2 `EC2NodeClass` erstellte Datei erneut mit hinzugefügt an. `capacityReservationSelectorTerms` Der Feldname und die Form entsprechen dem EKS-Auto-Modus, der `NodeClass` auf der anderen Registerkarte angezeigt wird.

**Example EC2NodeClass YAML wurde aktualisiert**  

```
cat << EOF | kubectl apply -f -
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: gpu-inf
  labels:
    guide: ai-eks-docs
spec:
  role: "eksctl-KarpenterNodeRole-${CLUSTER_NAME}"
  amiSelectorTerms:
    - alias: al2023@latest
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: ${CLUSTER_NAME}
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: ${CLUSTER_NAME}
  tags:
    karpenter.sh/discovery: ${CLUSTER_NAME}
  instanceStorePolicy: RAID0
  capacityReservationSelectorTerms:
    - id: "$CAPACITY_RESERVATION_ID"
  userData: |
    apiVersion: node.eks.aws/v1alpha1
    kind: NodeConfig
    spec:
      featureGates:
        FastImagePull: true
EOF
```

Die einzige Änderung gegenüber Schritt 2 ist das neue `capacityReservationSelectorTerms` Feld. Alle anderen Felder bleiben gleich.

Aktualisieren Sie das so NodePool , dass `reserved` es als Kapazitätstyp Folgendes enthält:

**Example NodePool YAML wurde aktualisiert**  

```
cat << EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: gpu-inf
spec:
  template:
    metadata:
      labels:
        guide: ai-eks-docs
        amiFamily: al2023
    spec:
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: gpu-inf
      taints:
        - key: nvidia.com/gpu
          effect: NoSchedule
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot", "on-demand", "reserved"]
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["g"]
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["4"]
        - key: karpenter.k8s.aws/instance-generation
          operator: Lt
          values: ["7"]
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"]
  limits:
    cpu: 1000
    memory: 5000Gi
EOF
```

------

Karpenter betrachtet es `reserved` als die kostengünstigste Option und bringt sie zuerst auf den Markt. Sobald die Reservierung vollständig ist, fällt sie auf Spot oder zurück. On-Demand

### Überprüfen Sie die reservierte Priorität und den Spot-Fallback
<a name="cluster-setup-cli-step4-validate"></a>

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, 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, sorgt dieses Deployment dafür, dass die Pods laufen (`sleep infinity`), sodass sie die GPU halten und den Knoten nicht freigeben.

Überprüfe, 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-59b97944fb-lq56c   1/1     Running   0          2m42s   192.168.186.240   i-057692590480155da   <none>           <none>
gpu-overflow-test-59b97944fb-z4zcx   1/1     Running   0          2m42s   192.168.130.64    i-0521ecd1849fa0578   <none>           <none>
```

Die beiden Pods werden ausgeführt, jeder auf einem anderen Knoten.

Markieren Sie das NodeClaims , um die Kapazitätstypen zu sehen:

```
kubectl get nodeclaims
```

Erwartete Ausgabe:

```
NAME            TYPE          CAPACITY    ZONE         NODE                  READY   AGE
gpu-inf-shg5w   g6e.xlarge    reserved    us-east-2a   i-0ea91fdeef65b8cb6   True    2m2s
gpu-inf-ssnqf   g6e.2xlarge   spot        us-east-2b   i-00ccf7ce65cf3f6ca   True    112s
```

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
<a name="cluster-setup-cli-monitoring"></a>

Installieren Sie einen Monitoring-Stack, der Cluster-, Knoten- und GPU-Metriken in Amazon Managed Service for Prometheus (AMP) erfasst, und visualisieren Sie sie mit Grafana. Das Kube-Prometheus-Stack-Helm-Diagramm setzt Prometheus ein, um Metriken zu scrapen und per Fernzugriff auf AMP zu schreiben, sowie ein selbstverwaltetes Grafana für Dashboards. Der NVIDIA DCGM Exporter fügt Metriken hinzu (Auslastung, Speicher, Temperatur, Leistung, NVLink, Tensoraktivität). GPU-specific 

Prometheus, Grafana und der Operator landen standardmäßig auf Nicht-GPU-Knoten, da GPU-Knoten den Fehler enthalten. `nvidia.com/gpu:NoSchedule` Node-exporter und der DCGM-Exporter laufen beide auf GPU-Knoten, sodass wir Host- und GPU-Metriken flottenweit auslesen können.

Wenn Sie ein neues Terminal geöffnet haben, legen Sie den Clusternamen und die Region fest:

```
export CLUSTER_NAME=ai-eks-docs
export AWS_REGION=us-east-2
```

### Erstelle den AMP Workspace
<a name="_create_the_amp_workspace"></a>

Erstelle einen AMP-Workspace zum Speichern von Metriken:

```
aws amp create-workspace \
  --alias "amp-ws-${CLUSTER_NAME}" \
  --region ${AWS_REGION}
```

Hol dir die Workspace-ID:

```
AMP_WORKSPACE_ID=$(aws amp list-workspaces \
  --alias "amp-ws-${CLUSTER_NAME}" \
  --query 'workspaces[0].workspaceId' \
  --output text \
  --region ${AWS_REGION})

echo "AMP Workspace ID: ${AMP_WORKSPACE_ID}"
```

Ruft den Remote-Write-Endpunkt ab:

```
AMP_ENDPOINT=$(aws amp describe-workspace \
  --workspace-id ${AMP_WORKSPACE_ID} \
  --query 'workspace.prometheusEndpoint' \
  --output text \
  --region ${AWS_REGION})

echo "AMP Endpoint: ${AMP_ENDPOINT}"
```

### Erstellen Sie eine IAM-Richtlinie und EKS Pod Identity-Zuordnungen
<a name="_create_iam_policy_and_eks_pod_identity_associations"></a>

Erstellen Sie eine IAM-Richtlinie, die es Prometheus ermöglicht, Metriken per Fernzugriff zu schreiben und Grafana sie abzufragen:

```
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

AMP_POLICY_ARN=$(aws iam create-policy \
  --policy-name "${CLUSTER_NAME}-amp-grafana-policy" \
  --policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Sid\": \"AllowAMPReadWrite\", \"Effect\": \"Allow\", \"Action\": [\"aps:ListWorkspaces\", \"aps:DescribeWorkspace\", \"aps:GetMetricMetadata\", \"aps:GetSeries\", \"aps:QueryMetrics\", \"aps:RemoteWrite\", \"aps:GetLabels\"], \"Resource\": \"arn:aws:aps:${AWS_REGION}:${ACCOUNT_ID}:workspace/*\"}, {\"Sid\": \"AllowCloudWatchMetrics\", \"Effect\": \"Allow\", \"Action\": [\"cloudwatch:DescribeAlarmsForMetric\", \"cloudwatch:ListMetrics\", \"cloudwatch:GetMetricData\", \"cloudwatch:GetMetricStatistics\"], \"Resource\": \"*\"}]}" \
  --query 'Policy.Arn' \
  --output text)

echo "AMP Policy ARN: ${AMP_POLICY_ARN}"
```

Erstellen Sie den Monitoring-Namespace und die Dienstkonten für Prometheus und Grafana:

```
kubectl create namespace monitoring
kubectl create serviceaccount amp-iamproxy-ingest-service-account -n monitoring
kubectl create serviceaccount grafana-sa -n monitoring
```

Erstellen Sie EKS Pod Identity Associations, um die Dienstkonten mit der IAM-Richtlinie zu verknüpfen:

```
eksctl create podidentityassociation \
  --cluster ${CLUSTER_NAME} \
  --namespace monitoring \
  --service-account-name amp-iamproxy-ingest-service-account \
  --role-name "${CLUSTER_NAME}-amp-ingest-role" \
  --permission-policy-arns ${AMP_POLICY_ARN} \
  --region ${AWS_REGION}

eksctl create podidentityassociation \
  --cluster ${CLUSTER_NAME} \
  --namespace monitoring \
  --service-account-name grafana-sa \
  --role-name "${CLUSTER_NAME}-grafana-role" \
  --permission-policy-arns ${AMP_POLICY_ARN} \
  --region ${AWS_REGION}
```

Stellen Sie sicher, dass beide EKS-Pod Identity-Zuordnungen erstellt wurden:

```
eksctl get podidentityassociation --cluster ${CLUSTER_NAME} --region ${AWS_REGION}
```

Die erwartete Ausgabe sollte beide `amp-iamproxy-ingest-service-account` und `grafana-sa` im `monitoring` Namespace enthalten.

### Installieren Sie kube-prometheus-stack
<a name="cluster-setup-cli-install-kube-prometheus"></a>

Füge das Helm-Repo hinzu:

```
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
```

In dieser Wertedatei fehlt ein NodeSelector für Prometheus, Grafana und den Operator: Der Makel der GPU-Knoten hält sie von GPU-Knoten fern, sodass sie standardmäßig im System oder Allzweckpool landen. `nvidia.com/gpu:NoSchedule` Node-exporter verwendet eine Platzhaltertoleranz, sodass es auf jedem Knoten — einschließlich GPU-Knoten — ausgeführt wird, um Metriken flottenweit zu erfassen.

In der Wertedatei wird auch eine Grafana-Datei konfiguriert, `Ingress` sodass das Diagramm eine mit dem Internet verbundene ALB für den Browserzugriff bereitstellt. Dabei wird der ALB verwendet, den Sie unter Load Balancing einrichten erstellt haben. `alb` `IngressClass` [Richten Sie den Lastenausgleich ein](#cluster-setup-cli-loadbalancing) Die `alb.ingress.kubernetes.io/inbound-cidrs` Anmerkung beschränkt den Load Balancer auf Ihre eigene IP-Adresse. Stellen Sie sie daher vor der Installation ein.

**Grafana ist über HTTP mit Standardanmeldeinformationen öffentlich zugänglich**  
Grafana enthält Standard-Administratoranmeldedaten und bietet vollen Administratorzugriff auf Ihre Überwachungsdaten. Ein mit dem Internet verbundener Load Balancer platziert diese Schnittstelle über Klartext-HTTP im öffentlichen Internet. Automatisierte Scanner erkennen öffentliche Load Balancer innerhalb von Minuten. Sie ** müssen den Zugriff anhand der `alb.ingress.kubernetes.io/inbound-cidrs` Anmerkung ** einschränken und die Quell-IP-Zulassungsliste als Mindestschutz und nicht als vollständigen Schutz behandeln. Ändern Sie auch das Standard-Grafana-Admin-Passwort. Verwenden Sie für eine stärkere Haltung ein ** internes ** Schema (das nur von Ihrer VPC oder einem verbundenen VPN aus erreichbar ist)`internal`, indem Sie das Schema auf setzen und ein TLS-Zertifikat hinzufügen.

Finden Sie Ihre öffentliche IP-Adresse und speichern Sie sie als `/32` CIDR. Die Wertedatei liest dies aus der `MY_CIDR` Umgebungsvariablen:

```
export MY_CIDR="$(curl -s https://checkip.amazonaws.com)/32"
echo $MY_CIDR
```

Das Ergebnis sieht so aus`203.0.113.4/32`. Wenn Ihr Netzwerk Adressen dynamisch zuweist, kann sich Ihre IP-Adresse im Laufe der Zeit ändern. Erwägen Sie daher, einen breiteren Bereich festzulegen, z. B. `203.0.113.0/24`

Erstellen Sie die Wertedatei:

**Example Kube-Prometheus-Stack-Wertedatei**  

```
cat << EOF > /tmp/kube-prometheus-values.yaml
alertmanager:
  enabled: false

prometheus-adapter:
  enabled: false

prometheus:
  serviceAccount:
    create: false
    name: amp-iamproxy-ingest-service-account
  prometheusSpec:
    serviceAccountName: amp-iamproxy-ingest-service-account
    enableRemoteWriteReceiver: true
    retention: 2h
    scrapeInterval: 30s
    evaluationInterval: 30s
    podMonitorSelectorNilUsesHelmValues: false
    serviceMonitorSelectorNilUsesHelmValues: false
    resources:
      requests:
        cpu: 500m
        memory: 1Gi
      limits:
        memory: 8Gi
    remoteWrite:
      - url: "${AMP_ENDPOINT}api/v1/remote_write"
        sigv4:
          region: "${AWS_REGION}"
        queueConfig:
          maxSamplesPerSend: 1000
          maxShards: 200
          capacity: 2500

prometheusOperator:
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      memory: 256Mi

kube-state-metrics:
  resources:
    requests:
      cpu: 50m
      memory: 128Mi
    limits:
      memory: 512Mi

grafana:
  enabled: true
  ingress:
    enabled: true
    ingressClassName: alb
    labels:
      guide: ai-eks-docs
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/inbound-cidrs: ${MY_CIDR}
      alb.ingress.kubernetes.io/load-balancer-name: grafana-ai-eks-docs
      alb.ingress.kubernetes.io/healthcheck-path: /api/health
  serviceAccount:
    create: false
    name: grafana-sa
  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      memory: 1Gi
  grafana.ini:
    auth.sigv4:
      enabled: true
  sidecar:
    datasources:
      defaultDatasourceEnabled: false
  plugins:
    - grafana-amazonprometheus-datasource
  additionalDataSources:
    - name: Amazon-Managed-Prometheus
      type: grafana-amazonprometheus-datasource
      access: proxy
      url: "${AMP_ENDPOINT}"
      isDefault: true
      jsonData:
        sigV4Auth: true
        defaultRegion: "${AWS_REGION}"
        sigV4Region: "${AWS_REGION}"
      editable: true
  dashboardProviders:
    dashboardproviders.yaml:
      apiVersion: 1
      providers:
        - name: default
          orgId: 1
          folder: 'GPU Monitoring'
          type: file
          disableDeletion: false
          editable: true
          options:
            path: /var/lib/grafana/dashboards/default
  dashboards:
    default:
      nvidia-dcgm:
        gnetId: 25261
        revision: 1
        datasource:
          - name: DS_PROMETHEUS
            value: Amazon-Managed-Prometheus
      vllm:
        gnetId: 25263
        revision: 1
        datasource:
          - name: DS_PROMETHEUS
            value: Amazon-Managed-Prometheus
      vllm-load-analysis:
        gnetId: 25494
        revision: 1
        datasource:
          - name: DS_PROMETHEUS
            value: Amazon-Managed-Prometheus

prometheus-node-exporter:
  resources:
    requests:
      cpu: 50m
      memory: 64Mi
    limits:
      memory: 128Mi
  tolerations:
    - operator: Exists
EOF
```

Überprüfen Sie, ob die Variablen korrekt gefüllt wurden:

```
grep -E "url:|region:" /tmp/kube-prometheus-values.yaml
```

Du solltest die vollständige AMP-Endpunkt-URL (beginnend mit`https://aps-workspaces…​`) und deine Region sehen. Wenn eine der Variablen leer ist, exportiere die Variablen erneut und erstelle die Datei neu.

Installieren Sie das Diagramm:

```
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  -f /tmp/kube-prometheus-values.yaml
```

Stellen Sie sicher, dass die Pods ausgeführt werden:

```
kubectl get pods -n monitoring
```

Erwartete Ausgabe:

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

Der Stack stellt die folgenden Komponenten bereit:
+  **Prometheus ** (StatefulSet): scrappt Metriken und schreibt sie per Fernzugriff auf AMP
+  **Grafana**: Dashboards und Visualisierungen, die mit der AMP-Datenquelle vorkonfiguriert sind
+  **kube-state-metrics**: generiert Metriken über den Zustand des Kubernetes-Objekts (Pod-Status, Ressource, Status) requests/limits NodeClaim 
+  **Node-Exporter ** (DaemonSet, einer pro Knoten): sammelt Metriken auf Host-Ebene (CPU, Speicher, Festplatte, Netzwerk)
+  **Operator**: verwaltet die benutzerdefinierten Ressourcen von Prometheus und Alertmanager

Alertmanager ist in diesem Setup deaktiviert.

### Greifen Sie auf Grafana zu
<a name="cluster-setup-cli-grafana-loadbalancer"></a>

Sie greifen über einen mit dem Internet verbundenen AWS Application Load Balancer (ALB) auf Grafana zu. Sie erstellen es nicht hier. Das Kube-Prometheus-Stack-Diagramm stellt es aus der `grafana.ingress` Konfiguration in der [ Wertedatei bereit und verwendet dabei das Formular Setup ](#cluster-setup-cli-install-kube-prometheus) Load Balancing. `alb` `IngressClass` [Richten Sie den Lastenausgleich ein](#cluster-setup-cli-loadbalancing) Das Grafana-Helm-Diagramm verfügt über eine integrierte `Ingress` Unterstützung, sodass kein separates Manifest erforderlich ist. Das ALB hat einen Namen`grafana-ai-eks-docs`, trägt das Label und ist auf die IP-Adresse beschränkt`guide: ai-eks-docs`, die Sie `MY_CIDR` bei der Installation eingegeben haben.

**Für die Grafana-ALB-Zielgruppe ist ein Gesundheitscheck-Pfad erforderlich**  
Die `alb.ingress.kubernetes.io/healthcheck-path` Anmerkung in der Wertedatei verweist die Zustandsprüfungen des Load Balancers auf den `/api/health` Grafana-Endpunkt, der zurückkehrt. `200` Ohne diese Option wird bei den ALB-Zustandsprüfungen standardmäßig die Standardeinstellung verwendet`/`, auf die Grafana mit einer `302` Weiterleitung antwortet`/login`, sodass die Zielgruppe den Endpunkt als fehlerhaft meldet.

Drucken Sie die Load Balancer-URL aus. Der Load Balancer wird asynchron erstellt. Warten Sie also ein oder zwei Minuten:

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

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](https://docs.aws.amazon.com/de_de/eks/latest/userguide/images/ml-cluster-setup-cli-prometheus-ds-validate.png)

1. 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](https://docs.aws.amazon.com/de_de/eks/latest/userguide/images/ml-cluster-setup-cli-prometheus-metrics-validate.png)

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

### Stellen Sie den DCGM-Exporter für GPU-Metriken bereit
<a name="_deploy_the_dcgm_exporter_for_gpu_metrics"></a>

Der Kube-Prometheus-Stack erfasst CPU- und Speichermetriken auf Knotenebene, aber keine GPU-Metriken. Der NVIDIA DCGM Exporter fügt GPU-Auslastung, Speichernutzung, Temperatur, Stromverbrauch, NVLink-Bandbreite und Tensoraktivität hinzu.

```
helm repo add gpu-helm-charts https://nvidia.github.io/dcgm-exporter/helm-charts
helm repo update
```

Stellen Sie den GPU-Knotenauswahlschlüssel für Ihren Pfad ein. EKS Auto Mode und selbstverwaltetes Karpenter verwenden unterschiedliche Labelschlüssel für den GPU-Hersteller.

------
#### [ EKS Auto Mode ]

```
GPU_NODE_SELECTOR_KEY="eks.amazonaws.com/instance-gpu-manufacturer"
```

------
#### [ Self-managed Karpenter ]

```
GPU_NODE_SELECTOR_KEY="karpenter.k8s.aws/instance-gpu-manufacturer"
```

------

Erstellen Sie die DCGM-Exportwertedatei:

**Example DCGM-Exporter-Wertedatei**  

```
cat << EOF > /tmp/dcgm-exporter-values.yaml
resources:
  requests:
    memory: "512Mi"
    cpu: "100m"
  limits:
    memory: "1Gi"
    cpu: "500m"

serviceMonitor:
  enabled: true
  additionalLabels:
    release: kube-prometheus-stack

nodeSelector:
  ${GPU_NODE_SELECTOR_KEY}: nvidia

tolerations:
  - key: "nvidia.com/gpu"
    operator: "Exists"
    effect: "NoSchedule"

customMetrics: |
  # Clocks
  DCGM_FI_DEV_SM_CLOCK,  gauge, SM clock frequency (in MHz).
  DCGM_FI_DEV_MEM_CLOCK, gauge, Memory clock frequency (in MHz).
  # Temperature
  DCGM_FI_DEV_MEMORY_TEMP, gauge, Memory temperature (in C).
  DCGM_FI_DEV_GPU_TEMP,    gauge, GPU temperature (in C).
  # Power
  DCGM_FI_DEV_POWER_USAGE,              gauge, Power draw (in W).
  DCGM_FI_DEV_TOTAL_ENERGY_CONSUMPTION, counter, Total energy consumption since boot (in mJ).
  # PCIe
  DCGM_FI_PROF_PCIE_TX_BYTES,  counter, Number of bytes transmitted through PCIe TX (in KB) via NVML.
  DCGM_FI_PROF_PCIE_RX_BYTES,  counter, Number of bytes received through PCIe RX (in KB) via NVML.
  DCGM_FI_DEV_PCIE_REPLAY_COUNTER, counter, Total number of PCIe retries.
  # Utilization (the sample period varies depending on the product)
  DCGM_FI_DEV_GPU_UTIL,      gauge, GPU utilization (in %).
  DCGM_FI_DEV_MEM_COPY_UTIL, gauge, Memory utilization (in %).
  DCGM_FI_DEV_ENC_UTIL,      gauge, Encoder utilization (in %).
  DCGM_FI_DEV_DEC_UTIL,      gauge, Decoder utilization (in %).
  # Errors and violations
  DCGM_FI_DEV_XID_ERRORS,            gauge, Value of the last XID error encountered.
  DCGM_EXP_XID_ERRORS_COUNT,         gauge, Value of count of XID errors encountered.
  DCGM_FI_DEV_POWER_VIOLATION,       counter, Throttling duration due to power constraints (in us).
  DCGM_FI_DEV_THERMAL_VIOLATION,     counter, Throttling duration due to thermal constraints (in us).
  DCGM_FI_DEV_SYNC_BOOST_VIOLATION,  counter, Throttling duration due to sync-boost constraints (in us).
  DCGM_FI_DEV_BOARD_LIMIT_VIOLATION, counter, Throttling duration due to board limit constraints (in us).
  DCGM_FI_DEV_LOW_UTIL_VIOLATION,    counter, Throttling duration due to low utilization (in us).
  DCGM_FI_DEV_RELIABILITY_VIOLATION, counter, Throttling duration due to reliability constraints (in us).
  # Memory usage
  DCGM_FI_DEV_FB_FREE, gauge, Framebuffer memory free (in MiB).
  DCGM_FI_DEV_FB_USED, gauge, Framebuffer memory used (in MiB).
  # Retired pages
  DCGM_FI_DEV_RETIRED_SBE,     counter, Total number of retired pages due to single-bit errors.
  DCGM_FI_DEV_RETIRED_DBE,     counter, Total number of retired pages due to double-bit errors.
  DCGM_FI_DEV_RETIRED_PENDING, counter, Total number of pages pending retirement.
  # NVLink
  DCGM_FI_DEV_NVLINK_BANDWIDTH_TOTAL, counter, Total number of NVLink bandwidth counters for all lanes.
  DCGM_FI_PROF_NVLINK_TX_BYTES,       counter, The rate of data transmitted over NVLink not including protocol headers in bytes per second.
  DCGM_FI_PROF_NVLINK_RX_BYTES,       counter, The rate of data received over NVLink not including protocol headers in bytes per second.
  # DCP metrics
  DCGM_FI_PROF_GR_ENGINE_ACTIVE,   gauge, Ratio of time the graphics engine is active (in %).
  DCGM_FI_PROF_SM_ACTIVE,          gauge, The ratio of cycles an SM has at least 1 warp assigned (in %).
  DCGM_FI_PROF_SM_OCCUPANCY,       gauge, The ratio of number of warps resident on an SM (in %).
  DCGM_FI_PROF_PIPE_TENSOR_ACTIVE, gauge, Ratio of cycles the tensor (HMMA) pipe is active (in %).
  DCGM_FI_PROF_DRAM_ACTIVE,        gauge, Ratio of cycles the device memory interface is active sending or receiving data (in %).
  DCGM_FI_DEV_CLOCK_THROTTLE_REASONS, gauge, Current clock throttle reasons (bitmask of DCGM_CLOCKS_THROTTLE_REASON_*).
  DCGM_FI_DEV_GPU_NVLINK_ERRORS,      gauge, Identifies a GPU NVLink error type returned by DCGM_FI_DEV_GPU_NVLINK_ERRORS.
  ## NVLink
  DCGM_FI_DEV_NVLINK_BANDWIDTH_L0, counter, The number of bytes of active NVLink rx or tx data including both header and payload.
  ## Remapped rows
  DCGM_FI_DEV_UNCORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for uncorrectable errors.
  DCGM_FI_DEV_CORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for correctable errors.
  DCGM_FI_DEV_ROW_REMAP_FAILURE, gauge, whether remapping of rows has failed.
  ## Profiling metrics
  DCGM_FI_PROF_PIPE_FP64_ACTIVE, gauge, Ratio of cycles the fp64 pipes are active (in %).
  DCGM_FI_PROF_PIPE_FP32_ACTIVE, gauge, Ratio of cycles the fp32 pipes are active (in %).
  DCGM_FI_PROF_PIPE_FP16_ACTIVE, gauge, Ratio of cycles the fp16 pipes are active (in %).
  # ECC
  DCGM_FI_DEV_ECC_SBE_VOL_TOTAL, counter, Total number of single-bit volatile ECC errors.
  DCGM_FI_DEV_ECC_DBE_VOL_TOTAL, counter, Total number of double-bit volatile ECC errors.
EOF
```

Das `customMetrics` Feld überschreibt den Standard-Metriksatz des DCGM-Exporters durch einen erweiterten Metriksatz, der NVLink-Bandbreite, Tensoraktivität, PCIe-Durchsatz, ECC-Fehler und thermische Drosselung umfasst. Bei Inferenz-Workloads helfen Ihnen diese dabei, zu verstehen, ob die GPU-Recheneinheiten voll ausgelastet sind, ob die GPU aufgrund niedriger Batchgrößen zwischen Anfragen im Leerlauf ist, ob die Datenübertragung zwischen CPU und GPU ein Engpass ist, ob thermische Drosselung Latenzspitzen verursacht und wie viel GPU-Speicher für größere Batches noch verfügbar ist.

Installieren Sie den DCGM-Exporter:

```
helm install dcgm-exporter gpu-helm-charts/dcgm-exporter \
  --namespace monitoring \
  -f /tmp/dcgm-exporter-values.yaml
```

`tolerations`Dadurch kann der Exporter auf den GPU-tainted Knoten ausgeführt werden, die Sie in Schritt 2 bereitgestellt haben. Das `serviceMonitor` mit dem `release: kube-prometheus-stack` Etikett stellt sicher, dass Prometheus es automatisch erkennt und löscht.

Überprüfen Sie den DCGM-Exporter: DaemonSet

```
kubectl get daemonset dcgm-exporter -n monitoring
```

Sobald ein GPU-Knoten läuft, sollten Sie einen fertigen Pod 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](https://docs.aws.amazon.com/de_de/eks/latest/userguide/images/ml-cluster-setup-cli-dcgm-metrics-validate.png)


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](https://docs.aws.amazon.com/de_de/eks/latest/userguide/images/ml-cluster-setup-cli-dcgm-dashboard.png)


## Das Modell wiegt den S3-Eimer
<a name="cluster-setup-cli-model-bucket"></a>

Erstellen Sie einen Amazon S3-Bucket zum Speichern von Modellgewichten und konfigurieren Sie eine EKS Pod Identity Association, damit Workload-Pods darauf lesen und schreiben können.

Wenn Sie ein neues Terminal geöffnet haben, legen Sie den Clusternamen und die Region fest:

```
export CLUSTER_NAME=ai-eks-docs
export AWS_REGION=us-east-2
```

### Erstellen Sie den S3-Bucket
<a name="_create_the_s3_bucket"></a>

Erstellen Sie den Bucket mit einem zufälligen Suffix, um Namenskollisionen zu vermeiden:

```
BUCKET_SUFFIX=$(head -c 4 /dev/urandom | od -An -tx1 | tr -d ' \n')
MODEL_BUCKET="${CLUSTER_NAME}-models-${BUCKET_SUFFIX}"

aws s3 mb s3://${MODEL_BUCKET} --region ${AWS_REGION}
```

Bei S3-Buckets, die nach Januar 2023 erstellt wurden, sind die serverseitige Verschlüsselung (AES256) und die Sperrung des öffentlichen Zugriffs standardmäßig aktiviert.

### Konfigurieren Sie EKS Pod Identity für den S3-Zugriff
<a name="_configure_eks_pod_identity_for_s3_access"></a>

Erstellen Sie `model-storage-sa` ServiceAccount im `default` Namespace eine IAM-Richtlinie für den Modell-Bucket und eine EKS Pod Identity Association, die sie verknüpft. Diese Workload-Pods `serviceAccountName: model-storage-sa` werden in der Lage sein, den Bucket zu lesen und in ihn zu schreiben.

```
kubectl create serviceaccount model-storage-sa
```

Erstellen Sie die IAM-Richtlinie:

```
POLICY_ARN=$(aws iam create-policy \
  --policy-name "${CLUSTER_NAME}-model-storage-policy" \
  --policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Action\": [\"s3:GetObject\", \"s3:PutObject\", \"s3:ListBucket\", \"s3:DeleteObject\"], \"Resource\": [\"arn:aws:s3:::${MODEL_BUCKET}\", \"arn:aws:s3:::${MODEL_BUCKET}/*\"]}]}" \
  --query 'Policy.Arn' \
  --output text)

echo "Policy ARN: ${POLICY_ARN}"
```

**Anmerkung**  
Diese Richtlinie gewährt `s3:DeleteObject` und `s3:PutObject` für den Validierungsschritt. Bei Inferenz-Pods für die Produktion, die nur Modellgewichte lesen, entfernen `s3:PutObject` und befolgen Sie `s3:DeleteObject` Least-Privilege-Befehle.

Erstellen Sie die EKS Pod Identity Association. `eksctl`erstellt die IAM-Rolle mit der richtigen Vertrauensrichtlinie und verknüpft sie mit: ServiceAccount

```
eksctl create podidentityassociation \
  --cluster ${CLUSTER_NAME} \
  --namespace default \
  --service-account-name model-storage-sa \
  --role-name "${CLUSTER_NAME}-model-storage-role" \
  --permission-policy-arns ${POLICY_ARN} \
  --region ${AWS_REGION}
```

Überprüfen Sie die Zuordnung:

```
eksctl get podidentityassociation --cluster ${CLUSTER_NAME} --region ${AWS_REGION}
```

Die Ausgabe sollte die `model-storage-sa` Assoziation im `default` Namespace enthalten.

#### Validieren Sie den S3-Zugriff von einem Pod aus
<a name="cluster-setup-cli-s3-validate"></a>

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-model-storage-role/eks-ai-eks-docs-model-s-..."
}

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

=== S3 List Test ===
2026-05-04 12:00:00         19 test.txt

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

Die Identität des Anrufers bestätigt, dass der Pod die `${CLUSTER_NAME}-model-storage-role` Rolle über EKS Pod Identity übernommen hat. Die S3-Befehle bestätigen den Lese- und Schreibzugriff.

Bereinigen Sie den Test-Pod:

```
kubectl delete pod s3-test
```

## Nächste Schritte
<a name="cluster-setup-cli-next-steps"></a>

Wenn Ihr Cluster bereit ist, können Sie mit [ Load & Serve Model fortfahren](ml-inference-load-serve-model.md), um ein umfangreiches Sprachmodell bereitzustellen und mit dem Inferenzendpunkt zu interagieren.

## Bereinigen
<a name="cluster-setup-cli-cleanup"></a>

**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.

```
export CLUSTER_NAME=ai-eks-docs
export AWS_REGION=us-east-2
```

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

### Stornieren Sie die Kapazitätsreservierung
<a name="cluster-setup-cli-cleanup-cancel-reservation"></a>

Wenn Sie ein ODCR erstellt haben, stornieren Sie es zuerst. Schlagen Sie die Reservierungs-ID nach:

```
INSTANCE_TYPE="g6e.4xlarge"
CAPACITY_RESERVATION_ID=$(aws ec2 describe-capacity-reservations \
  --filters "Name=state,Values=active" "Name=instance-type,Values=${INSTANCE_TYPE}" \
  --query 'CapacityReservations[0].CapacityReservationId' \
  --output text \
  --region ${AWS_REGION})
echo "Capacity reservation ID: ${CAPACITY_RESERVATION_ID}"
```

Stornieren Sie die Reservierung:

```
aws ec2 cancel-capacity-reservation --capacity-reservation-id ${CAPACITY_RESERVATION_ID}
```

**Wichtig**  
Durch das Stornieren einer Reservierung werden laufende Instances nicht beendet. Sie gelten weiterhin zu On-Demand Standardtarifen, bis sie beendet werden. Löschen Sie zuerst die Bereitstellung, um den reservierten Knoten zu entleeren, bevor Sie den Vorgang abbrechen.

### Bereinigen Sie die Überwachung
<a name="cluster-setup-cli-cleanup-monitoring"></a>

Schlagen Sie den ARN der IAM-Richtlinie nach:

```
AMP_POLICY_ARN=$(aws iam list-policies \
  --scope Local \
  --query "Policies[?PolicyName=='${CLUSTER_NAME}-amp-grafana-policy'].Arn" \
  --output text)
echo "AMP Policy ARN: ${AMP_POLICY_ARN}"
```

Schlage die AMP-Workspace-ID nach:

```
AMP_WORKSPACE_ID=$(aws amp list-workspaces \
  --alias "amp-ws-${CLUSTER_NAME}" \
  --query 'workspaces[0].workspaceId' \
  --output text \
  --region ${AWS_REGION})
echo "AMP Workspace ID: ${AMP_WORKSPACE_ID}"
```

Deinstalliere das Helm-Release des DCGM-Exporters:

```
helm uninstall dcgm-exporter -n monitoring
```

Deinstallieren Sie die Helm-Version von Kube-Prometheus-Stack:

```
helm uninstall kube-prometheus-stack -n monitoring
```

Löschen Sie die EKS Pod Identity-Zuordnung für das Prometheus-Ingest-Dienstkonto:

```
eksctl delete podidentityassociation \
  --cluster ${CLUSTER_NAME} \
  --namespace monitoring \
  --service-account-name amp-iamproxy-ingest-service-account \
  --region ${AWS_REGION}
```

Löschen Sie die EKS Pod Identity-Verknüpfung für das Grafana-Dienstkonto:

```
eksctl delete podidentityassociation \
  --cluster ${CLUSTER_NAME} \
  --namespace monitoring \
  --service-account-name grafana-sa \
  --region ${AWS_REGION}
```

Löschen Sie die von Prometheus und Grafana verwendete IAM-Richtlinie:

```
aws iam delete-policy --policy-arn ${AMP_POLICY_ARN}
```

Löschen Sie den AMP-Workspace:

```
aws amp delete-workspace --workspace-id ${AMP_WORKSPACE_ID} --region ${AWS_REGION}
```

Löschen Sie den Monitoring-Namespace:

```
kubectl delete namespace monitoring
```

### Säubern Sie den S3-Bucket mit den Gewichten des Modells
<a name="cluster-setup-cli-cleanup-model-bucket"></a>

Schlagen Sie den Namen des Modell-Buckets nach:

```
MODEL_BUCKET=$(aws s3api list-buckets \
  --query "Buckets[?starts_with(Name, '${CLUSTER_NAME}-models-')].Name | [0]" \
  --output text)
echo "Model bucket: ${MODEL_BUCKET}"
```

Schlagen Sie den ARN der IAM-Richtlinie nach:

```
POLICY_ARN=$(aws iam list-policies \
  --scope Local \
  --query "Policies[?PolicyName=='${CLUSTER_NAME}-model-storage-policy'].Arn" \
  --output text)
echo "Policy ARN: ${POLICY_ARN}"
```

Löschen Sie den S3-Modell-Bucket und alle seine Objekte:

```
aws s3 rb s3://${MODEL_BUCKET} --force
```

Löschen Sie die EKS Pod Identity-Zuordnung:

```
eksctl delete podidentityassociation \
  --cluster ${CLUSTER_NAME} \
  --namespace default \
  --service-account-name model-storage-sa \
  --region ${AWS_REGION}
```

Löschen Sie die IAM-Richtlinie:

```
aws iam delete-policy --policy-arn ${POLICY_ARN}
```

Löschen Sie die Kubernetes ServiceAccount:

```
kubectl delete serviceaccount model-storage-sa
```

### Löschen Sie die verbleibenden Ressourcen und den Cluster
<a name="cluster-setup-cli-cleanup-delete-resources"></a>

```
kubectl delete nodepool gpu-inf --ignore-not-found
kubectl delete nodeclass gpu-inf --ignore-not-found
kubectl delete ec2nodeclass gpu-inf --ignore-not-found
eksctl delete cluster --name=$CLUSTER_NAME --region=$AWS_REGION
```