

 **Contribuisci a migliorare questa pagina** 

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Per contribuire a questa guida per l'utente, scegli il GitHub ** link ** Modifica questa pagina su che si trova nel riquadro destro di ogni pagina.

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Configura il cluster Amazon EKS per i AI/ML carichi di lavoro utilizzando Terraform
<a name="ml-cluster-setup-tf"></a>

**Suggerimento**  
 [Registrati per ](https://events.eksworkshop.com/workshops/genai/) i prossimi workshop Amazon EKS. AI/ML 

Questa sezione illustra i passaggi per creare l'infrastruttura necessaria per eseguire carichi di lavoro di formazione o inferenza su Amazon EKS utilizzando Terraform. I passaggi includono la creazione di un cluster EKS, GPU-enabled nodi con EKS Auto Mode o Karpenter, uno stack di monitoraggio con Prometheus e Grafana e lo storage Amazon S3 per i pesi dei modelli.

Consulta la documentazione per [ EKS Auto Mode ](https://docs.aws.amazon.com/eks/latest/userguide/automode.html) e [ Karpenter ](https://karpenter.sh/docs/) per ulteriori informazioni su come queste funzionalità forniscono e scalano automaticamente le istanze EC2 nei cluster EKS.

 **High-level architettura e flusso di lavoro ** 

![High-level architettura che mostra un <shared id=](http://docs.aws.amazon.com/it_it/eks/latest/userguide/images/ml-cluster-setup-tf-architecture.png)


Il diagramma mostra l'architettura AWS di alto livello per la configurazione di questa sezione.

## Prerequisiti
<a name="cluster-setup-tf-prerequisites"></a>

**Importante**  
Le risorse create in questo tutorial, tra cui cluster EKS, istanze GPU, Application Load Balancer e Amazon Managed Service for Prometheus, sono a pagamento. Elimina le risorse quando hai finito per evitare addebiti continui.
+ Terraform >= 1.15.0. Per le istruzioni di configurazione, vedi Installazione di Terraform. [https://developer.hashicorp.com/terraform/install](https://developer.hashicorp.com/terraform/install)
+  `kubectl`>= 1.36. Per le istruzioni di configurazione, vedere. [Configura `` kubectl ed eksctl ``](install-kubectl.md)
+  AWS CLI >= 2.27. Per le istruzioni di configurazione, vedere Installazione. [https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)
+  `jq`. Per le istruzioni di configurazione, consulta [ Download jq](https://jqlang.github.io/jq/download/).

Verifica le versioni dei tuoi strumenti:

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

## Passaggio 1: scarica e distribuisci il codice Terraform
<a name="cluster-setup-tf-deploy"></a>

Questa procedura dettagliata utilizza il codice Terraform nel repository sample-eks-docs Samples[. ](https://github.com/aws-samples/sample-eks-docs) AWS GitHub Clona il repository in una directory di lavoro:

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

Il repository ha la seguente struttura `ai-ml/set-up-cluster/` nella directory in cui hai appena cambiato:

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

Il repository fornisce due percorsi di distribuzione. Scegline solo uno e utilizzalo in tutta la guida.
+  **EKS Auto Mode ** (`terraform/auto-mode/`) — Oltre ai principali componenti aggiuntivi di [ rete, storage e bilanciamento del carico](https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html#addon-consider-auto), EKS Auto Mode include e gestisce le seguenti funzionalità per l'addestramento e l'inferenza dei carichi di lavoro: agente di monitoraggio dei nodi EKS, riparazione automatica dei nodi, [ snapshotter ](https://github.com/awslabs/soci-snapshotter) SOCI per una rapida estrazione dei container e predisposizione della GPU per l'impostazione predefinita. NodeClass Il plug-in per dispositivi NVIDIA è incluso nell'AMI accelerata Bottlerocket che EKS Auto Mode utilizza per i nodi. GPU-enabled 
+  **Self-managed Karpenter ** (`terraform/karpenter/`) — Su un cluster EKS senza EKS Auto Mode, il codice Terraform installa e configura i componenti necessari per i carichi di lavoro di addestramento e inferenza. Ciò include componenti aggiuntivi di rete (VPC CNI, CoreDNS, kube-proxy), Karpenter, l'agente di monitoraggio dei nodi EKS, il plug-in per dispositivi NVIDIA e lo snapshotter SOCI per richiamare rapidamente i container.

**Importante**  
Scegli EKS Auto Mode o Karpenter autogestito e usalo in tutta la guida. Il passaggio a metà flusso richiede la distruzione del cluster e il riavvio da capo.

 **Opzioni del cluster EKS: EKS Auto Mode e Karpenter autogestito ** 

![Side-by-side confronto delle due opzioni di cluster: un cluster EKS Auto Mode con un e un cluster standard EKS con Karpenter NodePool, CoreDNS, VPC CNI autogestiti, plug-in per dispositivi NVIDIA, agente EKS Pod Identity, Node Monitoring Agent, kube-proxy e un e NodeClass NodePool](http://docs.aws.amazon.com/it_it/eks/latest/userguide/images/ml-cluster-setup-cli-cluster-options.png)


**Grafana è accessibile pubblicamente tramite HTTP con credenziali predefinite**  
L'`Ingress`impostazione predefinita di Grafana ALB è`0.0.0.0/0`, che espone Grafana `var.my_cidr` alla rete Internet pubblica tramite un semplice HTTP con credenziali di amministratore predefinite. Gli scanner automatici scoprono i sistemi di bilanciamento del carico pubblici in pochi minuti. È ** necessario ** limitare l'accesso sovrascrivendo il proprio `var.my_cidr` indirizzo IP:  

```
export MY_CIDR="$(curl -s https://checkip.amazonaws.com)/32"
terraform apply -var "my_cidr=${MY_CIDR}"
```
Considera l'elenco degli indirizzi IP di origine come una protezione minima, non completa. Cambia anche la password amministratore predefinita di Grafana dopo il primo accesso. Per una postura più sicura, modifica l'`alb.ingress.kubernetes.io/scheme`impostazione `internal` (raggiungibile solo dall'interno del tuo VPC o da una VPN connessa) e aggiungi un certificato TLS.

### Distribuzione del cluster
<a name="_deploy_the_cluster"></a>

Entra nella directory del percorso scelto, inizializza Terraform e applica:

Entrambe le varianti utilizzano per impostazione predefinita la regione. `us-east-2` Per eseguire la distribuzione in una regione diversa, aggiungi `-var "region={{region-code}}"` al `terraform apply` comando nel passaggio successivo, {{region-code}} dov'è la AWS regione in cui desideri eseguire la distribuzione.

Il codice Terraform utilizza tutte le zone di disponibilità disponibili nella regione di destinazione `use1-az3``usw1-az2`, escluse e `cac1-az3` perché [ Amazon EKS non supporta il posizionamento dei piani di controllo in quelle zone. ](https://repost.aws/knowledge-center/eks-cluster-creation-errors)

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

```
cd terraform/auto-mode
terraform init
terraform apply
```

Il completamento di questo comando richiede alcuni minuti.

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

```
cd terraform/karpenter
terraform init
terraform apply
```

Questo comando richiede circa 15 minuti. Crea un cluster EKS con un gruppo di nodi gestiti dedicato all'hosting di componenti aggiuntivi e il controller Karpenter. Terraform installa Karpenter con la coda di interruzione Spot abilitata e i gate delle funzionalità e attivati. `NodeRepair` `StaticCapacity` Installa anche il plug-in del dispositivo NVIDIA, il Load Balancer Controller e lo AWS stack di monitoraggio.

------

### Esamina gli output di Terraform
<a name="_review_the_terraform_outputs"></a>

Al termine dell'applicazione, Terraform stampa i seguenti output (i valori variano in base alla configurazione):

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

L'`configure_kubectl`output è un comando pronto per l'esecuzione che punta al cluster. `kubectl` L'`model_bucket`output contiene il nome del bucket S3 per i pesi del modello. L'`node_iam_role_name`output mostra il ruolo IAM utilizzato dai nodi.

### Configura kubectl
<a name="_configure_kubectl"></a>

Indicate il `kubectl` nuovo cluster. L'`configure_kubectl`output è un comando pronto per l'esecuzione:

```
eval "$(terraform output -raw configure_kubectl)"
```

### Verifica il cluster
<a name="_verify_the_cluster"></a>

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

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

Output previsto:

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

In EKS Auto Mode, VPC CNI, kube-proxy e CoreDNS vengono eseguiti come componenti gestiti e non vengono visualizzati come pod in. `kube-system`

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

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

L'output previsto include Karpenter, CoreDNS, kube-proxy, aws-node (VPC CNI), EKS Pod Identity Agent, l'agente di monitoraggio dei nodi EKS e il plug-in per i dispositivi NVIDIA:

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

Verifica che il plug-in del dispositivo NVIDIA sia installato. Zero Device Plugin Pod viene visualizzato finché non viene fornita una GPU NodePool con l'`amiFamily=al2023`etichetta corrispondente:

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

Output previsto:

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

------

## Passaggio 2: crea una GPU dinamica NodePool
<a name="cluster-setup-tf-create-gpu-nodepool"></a>

Le GPU NodePools sono attivate. Per impostazione predefinita, `terraform apply` crea il cluster e lo stack di monitoraggio senza capacità GPU e senza fatturazione GPU. Per eseguire il provisioning dei nodi GPU, passate la `nodepools` variabile con un nome di strategia.

Attivate la `spot-ondemand` strategia, che prevede il provisioning di istanze G-family GPU con una generazione superiore a 4, utilizzando la capacità Spot con On-Demand come riserva:

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

Questo comando applica i NodeClass modelli NodePool e contenuti nella directory. `nodepools/spot-ondemand/` Entrambi i percorsi utilizzano la stessa NodePool API, ma differiscono NodeClass nei NodePool riferimenti.

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

Fanno NodePool riferimento a managed `default` NodeClass, che già seleziona l'AMI accelerata Bottlerocket, i driver NVIDIA, il plug-in del dispositivo NVIDIA e il pull parallelo SOCI. La `spot-ondemand` strategia non si prefigge di per sé questa strada. NodeClass 

Convalida: NodePool

```
kubectl get nodepools,nodeclasses
```

Output previsto. I `gpu-inf` NodePool join incorporati e tutti `general-purpose` e `system` NodePools tre fanno riferimento al gestore: `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 applica una personalizzazione `gpu-inf` `EC2NodeClass` insieme a. NodePool Inserisce `EC2NodeClass` l'alias AMI EKS-optimized AL2023, abilita SOCI attraverso il `FastImagePull` feature gate e imposta lo spostamento della cache delle immagini contenuta `instanceStorePolicy: RAID0` su NVMe locali.

Convalida la e: NodePool EC2NodeClass

```
kubectl get nodepools,ec2nodeclasses
```

Output previsto. La `gpu-inf` coppia si unisce alla band creata da Terraform per carichi di lavoro non GPU: `general-purpose` NodePool EC2NodeClass 

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

------

Entrambi i percorsi mostrano i `0` nodi `gpu-inf` fino alla pianificazione del carico di lavoro della GPU. EKS Auto Mode e Karpenter avviano i nodi solo quando i Pod in sospeso li richiedono.

## Fase 3: Esegui il test con un Pod di esempio
<a name="cluster-setup-tf-test-with-a-sample-pod"></a>

Verifica la NodePool configurazione della GPU con un `nvidia-smi` Pod:

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

Verifica che il Pod sia pianificato e completato correttamente:

```
kubectl get pods nvidia-smi
```

Output previsto:

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

Indica `STATUS: Completed` che il `nvidia-smi` comando è stato eseguito ed è terminato. Controlla i log del Pod per vedere la GPU rilevata dal nodo:

```
kubectl logs nvidia-smi
```

Output previsto:

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

L'output mostra il modello della GPU, la versione del driver, la versione CUDA e la memoria disponibile. In questo esempio, Karpenter ha effettuato il provisioning di un'istanza G6 con una GPU NVIDIA L4 con 24 GB di memoria. Il modello e la memoria della GPU variano a seconda del tipo di istanza selezionato da Karpenter. Le istanze G5 hanno GPU NVIDIA A10G (24 GB), le istanze G6 hanno GPU NVIDIA L4 (24 GB) e le istanze G6e hanno GPU NVIDIA L40S (48 GB).

Per capire come Karpenter e lo scheduler Kubernetes si sono coordinati per fornire un nodo e posizionare il Pod, controlla gli eventi del ciclo di vita del Pod:

```
kubectl describe pod nvidia-smi
```

Output previsto:

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

Questi eventi mostrano la sequenza di pianificazione del Pod: il Pod inizialmente non riesce a pianificare perché non esistono nodi GPU (`FailedScheduling`), Karpenter ne nomina un nuovo (), lo scheduler assegna il Pod una volta che il nodo è pronto NodeClaim (`Nominated`), quindi l'immagine del contenitore viene estratta e avviata. `Scheduled` EKS Auto Mode ha il pull parallelo SOCI (Seekable OCI) installato e configurato di default sulle istanze G, P e Trn e il percorso Karpenter autogestito lo configura esplicitamente tramite il `FastImagePull` feature gate.

**Nota**  
In un cluster Karpenter autogestito, l'evento viene visualizzato al posto di. `Nominated` `karpenter/compute` `eks-auto-mode/compute`

A NodeClaim è una richiesta creata da Karpenter per eseguire il provisioning di un nodo specifico. Mostra il tipo di istanza, il tipo di capacità, l'AZ e se il nodo è pronto:

```
kubectl get nodeclaims
```

Output previsto:

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

Il tipo di istanza e l'AZ variano. Qualsiasi G-family istanza con una generazione superiore a 4 è idonea.

**Suggerimento**  
Se non viene visualizzato alcun nodo, verifica la presenza di errori di capacità insufficiente:  

```
kubectl get events | grep InsufficientCapacityError
```
Karpenter memorizza nella cache le offerte non disponibili per 3 minuti. L'ampliamento dei tipi di istanze e degli AZ consentiti NodePool aumenta le possibilità di atterraggio.

**Nota**  
Le istanze Spot lanciate da Karpenter non vengono visualizzate nella console Spot Requests di EC2. Karpenter utilizza l'API EC2 [`CreateFleet`](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateFleet.html) con. `type: instant` Le istanze vengono visualizzate nella console EC2 Instances con un ciclo di vita. `spot`

## Fase 4: Aggiungere capacità riservata a (opzionale) NodePool
<a name="cluster-setup-tf-attach-odcr"></a>

Sebbene la GPU della Fase 2 NodePool esegua il provisioning di Spot o On-Demand delle istanze in modo dinamico, alcuni casi d'uso richiedono una capacità garantita. Puoi creare un On-Demand Capacity Reservation (ODCR) per assicurarti che la capacità della GPU sia disponibile quando necessario.

Con Terraform, un singolo comando crea l'ODCR, una personalizzazione NodeClass che fa riferimento alla prenotazione per tag e lo aggiorna NodePool per includerlo `reserved` come tipo di capacità. Terraform contrassegna l'ODCR con `nodepool=reserved-spot-ondemand` e poi lo NodeClass seleziona in base a quel tag.

**avvertimento**  
Il comando seguente crea un ODCR che viene fatturato immediatamente e continua a fatturare finché non viene distrutto con `terraform destroy` o con lo script di pulizia, indipendentemente dal fatto che i nodi siano in esecuzione o meno.

Usa i valori predefiniti (`g6e.4xlarge`, 1 istanza, primo cluster AZ):

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

Scegli il tipo di istanza, il numero e la AZ:

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

L'`reservation`oggetto supporta i seguenti campi:
+  `instance_type`— Il tipo di istanza GPU da prenotare. Default: `g6e.4xlarge`.
+  `instance_count`— Il numero di istanze da prenotare. Default: `1`.
+  `az`— La zona di disponibilità per la prenotazione. Predefinito: `""` (utilizza il primo cluster AZ).

**Importante**  
Le `reserved-spot-ondemand` strategie `spot-ondemand` e si escludono a vicenda. Puoi abilitarne al massimo una nella `nodepools` variabile. Se in precedenza lo si utilizzava `spot-ondemand` nel passaggio 2, il `reserved-spot-ondemand` comando lo sostituisce perché entrambi gestiscono la stessa cosa `gpu-inf` NodePool.

Se si `InsufficientInstanceCapacity` verifica un errore, la prenotazione non può essere soddisfatta nell'AZ specificato. Annulla l'operazione Terraform (Ctrl\+C), quindi eseguila nuovamente con un valore diverso: `az`

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

Dopo l'applicazione, Terraform li aggiorna NodePool per includere`reserved`, e nei requisiti relativi al tipo di `spot` capacità. `on-demand` Karpenter considera l'opzione più conveniente e `reserved` la lancia per prima. Una volta completata, la prenotazione torna a Spot o. On-Demand

Nel percorso EKS Auto Mode, Terraform crea un codice personalizzato `gpu-inf` NodeClass (perché il pacchetto `default` NodeClass è di sola lettura) che fa riferimento all'ODCR tramite tag. `capacityReservationSelectorTerms` Sul percorso Karpenter autogestito, Terraform riapplica le impostazioni aggiunte e le aggiorna per includere. `gpu-inf` EC2NodeClass `capacityReservationSelectorTerms` NodePool `reserved`

Verifica che l'ODCR sia stato creato:

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

Verifica i NodeClass riferimenti all'ODCR:

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

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

Output previsto:

```
        id: cr-xxxxxxxxxxxxxxxxx
```

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

```
kubectl get ec2nodeclasses gpu-inf -o yaml | grep 'id: cr-.*'
```

Output previsto:

```
        id: cr-xxxxxxxxxxxxxxxxx
```

------

Verifica che NodePool sia pronto:

```
kubectl get nodepools gpu-inf
```

Output previsto:

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

### Verifica che la capacità riservata venga utilizzata per prima, con il fallback di Spot
<a name="cluster-setup-tf-step4-validate"></a>

Dopo aver applicato le modifiche, verifica che Karpenter dia la priorità alla capacità riservata e ritorni a Spot o. On-Demand Implementa una distribuzione con 2 repliche che richiede 1 GPU per pod. L'ODCR è per 1 istanza (1 GPU), quindi il primo Pod attiva Karpenter per avviare un nodo riservato. Il secondo Pod non può essere inserito nel nodo riservato e fa sì che Karpenter avvii un altro nodo da Spot o Capacity. 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
```

A differenza del Pod di `nvidia-smi` test di Step 3, che è stato eseguito e chiuso, questo Deployment mantiene i Pod in funzione (`sleep infinity`) in modo da trattenere la GPU e impedire il consolidamento del nodo.

Verifica i Pod pianificati su diversi nodi:

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

Output previsto:

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

Controlla NodeClaims per vedere i tipi di capacità:

```
kubectl get nodeclaims
```

Output previsto:

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

Il nodo riservato viene avviato per primo, seguito da uno Spot o da un On-Demand nodo una volta completata la prenotazione.

Pulisci la distribuzione di prova:

```
kubectl delete deployment gpu-overflow-test
```

## Monitoraggio
<a name="cluster-setup-tf-monitoring"></a>

Terraform ha già fornito l'intero stack di monitoraggio durante la fase 1`terraform apply`. Lo stack include uno spazio di lavoro Amazon Managed Service for Prometheus (AMP), policy IAM e EKS Pod Identity Associations per l'accesso alla scrittura remota e alle query Grafana di Prometheus, il grafico Helm kube-prometheus-stack (Prometheus, Grafana, kube-state-metrics, node-exporter) e NVIDIA DCGM Exporter per le metriche GPU.

Questa sezione riguarda la verifica dei componenti di monitoraggio implementati.

### Verifica i pod di monitoraggio
<a name="_verify_monitoring_pods"></a>

Attendi che tutti i pod di monitoraggio siano pronti:

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

Output previsto:

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

### Accedi a Grafana
<a name="cluster-setup-tf-grafana"></a>

Grafana è esposta tramite un AWS Application Load Balancer (ALB) connesso a Internet, limitato al CIDR impostato. `var.my_cidr` Stampa l'URL del load balancer (attendi uno o due minuti per il provisioning dell'ALB):

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

Apri l'URL nel tuo browser. Accedi con nome utente `admin` e password con il seguente comando:

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

### Verifica la pipeline delle metriche
<a name="_verify_the_metrics_pipeline"></a>

Per verificare che la pipeline delle metriche funzioni integralmente:

1. Vai a ** Connessioni > Origini dati ** e conferma che ** Amazon-Managed-Prometheus ** sia elencato come origine dati predefinita.

    **Convalida l'origine dati AMP in Grafana **   
![La pagina Grafana Connections viene visualizzata come origine dati Amazon-Managed-Prometheus predefinita](http://docs.aws.amazon.com/it_it/eks/latest/userguide/images/ml-cluster-setup-cli-prometheus-ds-validate.png)

1. Vai a ** Drilldown > Metriche ** e cerca la metrica. `up` Dovresti vedere i risultati degli obiettivi di scrape del tuo cluster.

    **Convalida la `up` metrica in Grafana **   
![Pagina Grafana Drilldown Metrics che mostra la metrica up con barre di stato verdi che indicano gli obiettivi di scrape attivi](http://docs.aws.amazon.com/it_it/eks/latest/userguide/images/ml-cluster-setup-cli-prometheus-metrics-validate.png)

Se `up` vengono visualizzati i risultati, la pipeline (cluster → Prometheus → AMP → Grafana) funziona.

### Convalida le metriche della GPU DCGM
<a name="_validate_dcgm_gpu_metrics"></a>

Il DCGM Exporter DaemonSet funziona su nodi GPU e riporta le metriche relative all'utilizzo della GPU, alla memoria, alla temperatura, al consumo energetico, alla larghezza di banda NVLink e all'attività tensoriale.

Verifica l'esportatore DCGM: DaemonSet

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

Una volta che un nodo GPU è in esecuzione (dal passaggio 2 o dal passaggio 4), dovresti vedere uno o più pod pronti. Per convalidare le metriche DCGM, accedi a ** Drilldown > Metrics in Grafana e cerca. ** `DCGM_`

 **Convalida le metriche DCGM in Grafana ** 

![Pagina Grafana Drilldown Metrics filtrata da DCGM_ che mostra le metriche GPU tra cui DCGM_FI_DEV_ECC_SBE_VOL_TOTAL, DCGM_FI_DEV_ENC_UTIL, DCGM_FI_DEV_DEV_FB_FREE e DCGM_FI_DEV_FB_USED](http://docs.aws.amazon.com/it_it/eks/latest/userguide/images/ml-cluster-setup-cli-dcgm-metrics-validate.png)


Per visualizzare la dashboard, vai su ** Dashboard > Monitoraggio GPU > NVIDIA DCGM Exporter Dashboard**.

 **Dashboard di NVIDIA DCGM Exporter a Grafana ** 

![Grafana NVIDIA DCGM Exporter Dashboard che mostra l'utilizzo della GPU, la temperatura media della GPU, il framebuffer della GPU Mem usato e i pannelli GPU Power Total](http://docs.aws.amazon.com/it_it/eks/latest/userguide/images/ml-cluster-setup-cli-dcgm-dashboard.png)


## Il modello pesa un secchio S3
<a name="cluster-setup-tf-model-bucket"></a>

Terraform ha già creato un bucket Amazon S3 per memorizzare i pesi dei modelli, uno `model-storage-sa` ServiceAccount nel `default` namespace, una policy IAM con ambito per il bucket e un'EKS Pod Identity Association che li collega. I Workload Pod impostati possono leggere e scrivere nel bucket. `serviceAccountName: model-storage-sa`

### Verifica il bucket
<a name="_verify_the_bucket"></a>

Recupera il nome del bucket dagli output di Terraform:

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

Verifica che il bucket esista:

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

Output previsto:

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

#### Convalida l'accesso a S3 da un Pod
<a name="cluster-setup-tf-s3-validate"></a>

Esegui un Pod singolo con l'immagine AWS CLI, utilizzando `model-storage-sa` ServiceAccount, per confermare che EKS Pod Identity sia cablato e che l'accesso S3 funzioni:

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

Attendi il completamento del Pod e controlla i log:

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

Output previsto:

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

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

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

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

L'identità del chiamante conferma che il Pod ha assunto il ruolo di archiviazione del modello tramite EKS Pod Identity. I comandi S3 confermano l'accesso in lettura e scrittura.

Pulisci il pod di prova:

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

## Fasi successive
<a name="cluster-setup-tf-next-steps"></a>

Con il cluster pronto, puoi passare a [ Load & Serve Model ](ml-inference-load-serve-model.md) per implementare un modello linguistico di grandi dimensioni e interagire con l'endpoint di inferenza.

## Pulizia
<a name="cluster-setup-tf-cleanup"></a>

**Suggerimento**  
Se intendi continuare con le sezioni successive di questa guida, salta la pulizia completa. Eseguila solo quando hai finito.

Elimina i carichi di lavoro di test in modo che nessun Pod contenga nodi GPU:

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

### Annulla la prenotazione della capacità senza distruggere il cluster
<a name="cluster-setup-tf-cleanup-cancel-reservation"></a>

Se desideri solo rilasciare l'ODCR e tornare a Spot e On-Demand capacity, riporta la `nodepools` variabile alla `spot-ondemand` strategia:

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

Questo riduce `reserved` i requisiti relativi al NodePool tipo di capacità, distrugge l'ODCR e lascia il cluster, lo stack di monitoraggio e il bucket S3 al loro posto.

**Importante**  
L'annullamento di una prenotazione non comporta la chiusura delle istanze già in esecuzione su di essa. Tali istanze continuano a funzionare alle On-Demand tariffe standard fino alla loro chiusura. Elimina prima i carichi di lavoro della GPU, come mostrato sopra, in modo che il nodo riservato si esaurisca prima del rilascio della prenotazione.

### Distruggi il cluster e tutte le risorse Terraform-managed
<a name="cluster-setup-tf-cleanup-destroy"></a>

Svuota i Karpenter-managed nodi prima di distruggerli, in modo che nessun ciclo di vita in corso blocchi la distruzione. Elimina quelli PodDisruptionBudgets che potrebbero impedire un drenaggio, quindi elimina: NodeClaims

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

Quindi distruggi tutto ciò che Terraform ha creato, incluso il cluster EKS, il VPC, lo stack di monitoraggio, l' NodePools and NodeClasses, il bucket del modello S3 e qualsiasi ODCR:

```
terraform destroy
```

**avvertimento**  
Il bucket S3 è stato creato con i pesi del modello`force_destroy = true`, quindi `terraform destroy` elimina il bucket insieme a tutti i pesi del modello che hai caricato su di esso. Copia prima tutto ciò che desideri conservare in un'altra posizione.

**Nota**  
Il repository fornisce anche un `scripts/cleanup.sh` helper che esegue i passaggi di drenaggio e distruzione precedenti e quindi analizza tutti i volumi EBS orfani contrassegnati con il nome del cluster. Eseguilo dall'interno della `terraform/<mode>/` directory da cui hai fatto la domanda e passa a saltare la richiesta di conferma `--auto-approve` di Terraform.

### Verifica che la prenotazione sia finita
<a name="cluster-setup-tf-cleanup-verify"></a>

Conferma che non rimanga alcuna prenotazione di capacità attiva per il cluster:

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

Un risultato vuoto significa che nessuna prenotazione è attiva e non si applicano ulteriori costi.