

 **Bantu meningkatkan halaman ini ** 

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Untuk berkontribusi pada panduan pengguna ini, pilih GitHub ** tautan ** Edit halaman ini di yang terletak di panel kanan setiap halaman.

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Menyiapkan cluster Amazon EKS untuk AI/ML beban kerja menggunakan Terraform
<a name="ml-cluster-setup-tf"></a>

**Tip**  
 [Daftar ](https://events.eksworkshop.com/workshops/genai/) untuk AI/ML lokakarya Amazon EKS mendatang.

Bagian ini memandu Anda melalui langkah-langkah untuk membuat infrastruktur yang diperlukan untuk menjalankan beban kerja pelatihan atau inferensi di Amazon EKS dengan menggunakan Terraform. Langkah-langkahnya termasuk membuat cluster EKS, GPU-enabled node dengan EKS Auto Mode atau Karpenter, tumpukan pemantauan dengan Prometheus dan Grafana, dan penyimpanan Amazon S3 untuk bobot model.

Lihat dokumentasi untuk Mode Otom [ atis EKS ](https://docs.aws.amazon.com/eks/latest/userguide/automode.html) dan [ Karpenter ](https://karpenter.sh/docs/) untuk informasi selengkapnya tentang bagaimana fitur tersebut menyediakan dan menskalakan instans EC2 secara otomatis di cluster EKS.

 **High-level arsitektur dan alur kerja ** 

![High-level arsitektur yang menunjukkan <shared id=](http://docs.aws.amazon.com/id_id/eks/latest/userguide/images/ml-cluster-setup-tf-architecture.png)


Diagram menunjukkan arsitektur AWS tingkat tinggi untuk pengaturan bagian ini.

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

**penting**  
Sumber daya yang Anda buat dalam tutorial ini, termasuk cluster EKS, instans GPU, Penyeimbang Beban Aplikasi, dan Amazon Managed Service untuk Prometheus, dikenakan biaya. Hapus sumber daya setelah selesai untuk menghindari biaya yang sedang berlangsung.
+ Terraform> = 1.15.0. Untuk petunjuk penyiapan, lihat Meng [ instal Terraform](https://developer.hashicorp.com/terraform/install).
+  `kubectl`>= 1,36. Untuk petunjuk penyiapan, lihat[Siapkan `kubectl dan eksctl` ``](install-kubectl.md).
+  AWS CLI > = 2,27. Untuk petunjuk penyiapan, lihat [ Menginstal](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html).
+  `jq`. Untuk petunjuk penyiapan, lihat [ Unduh jq](https://jqlang.github.io/jq/download/).

Verifikasi versi alat Anda:

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

## Langkah 1: Unduh dan terapkan kode Terraform
<a name="cluster-setup-tf-deploy"></a>

Panduan ini menggunakan kode Terraform di repositori [ Samples sample-eks-docs ](https://github.com/aws-samples/sample-eks-docs) AWS . GitHub Kloning repositori ke direktori kerja:

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

Repositori memiliki struktur berikut di bawah `ai-ml/set-up-cluster/` direktori yang baru saja Anda ubah menjadi:

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

Repositori menyediakan dua jalur penerapan. Pilih hanya satu dan gunakan di seluruh panduan.
+  **EKS Auto Mode ** (`terraform/auto-mode/`) - Selain add-on [https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html#addon-consider-auto](https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html#addon-consider-auto) jaringan inti, penyimpanan, dan penyeimbangan beban, Mode Otomatis EKS menyertakan dan mengelola kemampuan berikut untuk beban kerja pelatihan dan inferensi: agen pemantauan simpul EKS, perbaikan node otomatis, [ snapshotter ](https://github.com/awslabs/soci-snapshotter) SOCI untuk penarikan kontainer cepat, dan kesiapan GPU untuk default. NodeClass Plugin perangkat NVIDIA disertakan dalam AMI akselerasi Bottlerocket yang digunakan oleh Mode Otomatis EKS untuk node. GPU-enabled 
+  **Self-managed Karpenter ** (`terraform/karpenter/`) - Pada cluster EKS tanpa Mode Otomatis EKS, kode Terraform menginstal dan mengonfigurasi komponen yang diperlukan untuk beban kerja pelatihan dan inferensi. Ini termasuk add-on jaringan (VPC CNI, CoreDNS, kube-proxy), Karpenter, agen pemantauan simpul EKS, plugin perangkat NVIDIA, dan snapshotter SOCI untuk penarikan kontainer yang cepat.

**penting**  
Pilih Mode Otomatis EKS atau Karpenter yang dikelola sendiri dan gunakan di seluruh panduan. Mengalihkan mid-stream membutuhkan penghancuran cluster dan memulai dari awal.

 **Opsi cluster EKS: Mode Otomatis EKS dan Karpenter yang dikelola sendiri ** 

![Side-by-side perbandingan dua opsi cluster: cluster Mode Otomatis EKS dengan NodePool, dan cluster standar EKS dengan Karpenter yang dikelola sendiri, CoreDNS, VPC CNI, plugin perangkat NVIDIA, agen Identity Pod EKS, Agen Pemantauan Node, kube-proxy, dan a dan NodeClass NodePool](http://docs.aws.amazon.com/id_id/eks/latest/userguide/images/ml-cluster-setup-cli-cluster-options.png)


**Grafana dapat diakses publik melalui HTTP dengan kredenSIAL default**  
Grafana ALB `Ingress` default `var.my_cidr` ke`0.0.0.0/0`, yang mengekspos Grafana ke internet publik melalui HTTP biasa dengan kredenSIAL admin default. Pemindai otomatis menemukan penyeimbang beban publik dalam hitungan menit. Anda ** harus ** membatasi akses dengan mengganti `var.my_cidr` dengan alamat IP Anda sendiri:  

```
export MY_CIDR="$(curl -s https://checkip.amazonaws.com)/32"
terraform apply -var "my_cidr=${MY_CIDR}"
```
Perlakukan allowlisting sumber IP sebagai perlindungan minimum, bukan yang lengkap. Juga ubah kata sandi admin Grafana default setelah login pertama. Untuk postur yang lebih kuat, ubah `alb.ingress.kubernetes.io/scheme` ke `internal` (hanya dapat dijangkau dari dalam VPC Anda atau VPN yang terhubung) dan tambahkan sertifikat TLS.

### Menyebarkan cluster
<a name="_deploy_the_cluster"></a>

Ubah ke direktori untuk jalur yang Anda pilih, inisialisasi Terraform, dan terapkan:

Kedua varian default ke `us-east-2` wilayah. Untuk menerapkan di wilayah yang berbeda, tambahkan `-var "region={{region-code}}"` ke `terraform apply` perintah pada langkah berikut, di {{region-code}} mana Wil AWS ayah yang ingin Anda terapkan.

Kode Terraform menggunakan semua Zona Ketersediaan yang tersedia di wilayah target, tidak termasuk, `use1-az3``usw1-az2`, dan `cac1-az3` karena [ Amazon EKS tidak mendukung penempatan pesawat kontrol di zona tersebut. ](https://repost.aws/knowledge-center/eks-cluster-creation-errors)

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

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

Perintah ini membutuhkan waktu beberapa menit untuk diselesaikan.

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

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

Perintah ini memakan waktu sekitar 15 menit. Ini menciptakan cluster EKS dengan grup node terkelola yang didedikasikan untuk hosting add-on dan pengontrol Karpenter. Terraform menginstal Karpenter dengan antrean interupsi Spot diaktifkan dan gerbang `StaticCapacity` fitur `NodeRepair` dan diaktifkan. Ini juga menginstal plugin perangkat NVIDIA, Load Balancer Controller, dan tumpukan pemantauan. AWS 

------

### Tinjau keluaran Terraform
<a name="_review_the_terraform_outputs"></a>

Ketika aplikasi selesai, Terraform mencetak output berikut (nilainya bervariasi berdasarkan konfigurasi Anda):

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

`configure_kubectl`Outputnya adalah perintah siap dijalankan yang `kubectl` menunjuk ke cluster. `model_bucket`Output berisi nama bucket S3 untuk bobot model. `node_iam_role_name`Output menunjukkan peran IAM yang digunakan node.

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

`kubectl`Arahkan ke cluster baru. `configure_kubectl`Outputnya adalah perintah siap dijalankan:

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

### Verifikasi cluster
<a name="_verify_the_cluster"></a>

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

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

Keluaran yang diharapkan

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

Dalam Mode Otomatis EKS, VPC CNI, kube-proxy, dan CoreDNS berjalan sebagai komponen terkelola dan tidak muncul sebagai pod di. `kube-system`

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

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

Output yang diharapkan termasuk Karpenter, CoreDNS, kube-proxy, aws-node (VPC CNI), Agen Identity Pod EKS, agen pemantauan simpul EKS, dan plugin perangkat 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
```

Verifikasi plugin perangkat NVIDIA diinstal. Nol plugin perangkat Pod muncul hingga GPU NodePool dengan `amiFamily=al2023` label yang cocok disediakan:

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

Keluaran yang diharapkan

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

------

## Langkah 2: Buat GPU dinamis NodePool
<a name="cluster-setup-tf-create-gpu-nodepool"></a>

GPU NodePools adalah opt-in. Secara default, membuat `terraform apply` cluster dan tumpukan pemantauan tanpa kapasitas GPU dan tanpa penagihan GPU. Untuk menyediakan node GPU, berikan `nodepools` variabel dengan nama strategi.

Aktif `spot-ondemand` kan strategi, yang menyediakan instans G-family GPU dengan generasi lebih besar dari 4, menggunakan kapasitas Spot dengan On-Demand sebagai fallback:

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

Perintah ini menerapkan NodeClass template NodePool dan dari `nodepools/spot-ondemand/` direktori. Kedua jalur menggunakan NodePool API yang sama, tetapi mereka berbeda NodeClass dalam NodePool referensi.

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

 NodePool Referensi yang dikelola `default` NodeClass, yang sudah memilih AMI yang dipercepat Bottlerocket, driver NVIDIA, plugin perangkat NVIDIA, dan tarikan paralel SOCI. `spot-ondemand`Strategi tidak ada NodeClass artinya di jalur ini.

Validasi NodePool:

```
kubectl get nodepools,nodeclasses
```

Keluaran yang diharapkan Bergabung `gpu-inf` NodePool dengan built-in `general-purpose` dan `system` NodePools, dan ketiganya mereferensikan yang dikelola `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 menerapkan kebiasaan di `gpu-inf` `EC2NodeClass` samping. NodePool Men `EC2NodeClass` jepit alias AMI EKS-optimized AL2023, memungkinkan SOCI melalui gerbang `FastImagePull` fitur, dan mengatur untuk memindahkan cache gambar containerd `instanceStorePolicy: RAID0` ke NVMe lokal.

Validasi NodePool dan EC2NodeClass:

```
kubectl get nodepools,ec2nodeclasses
```

Keluaran yang diharapkan `gpu-inf`Pasangan bergabung dengan `general-purpose` NodePool dan EC2NodeClass yang dibuat Terraform untuk beban kerja non-GPU:

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

NAME                                             READY   AGE
ec2nodeclass.karpenter.k8s.aws/general-purpose   True    14m
ec2nodeclass.karpenter.k8s.aws/gpu-inf           True    25s
```

------

Kedua jalur menunjukkan `0` node `gpu-inf` hingga beban kerja GPU dijadwalkan. Mode Otomatis EKS dan Karpenter hanya meluncurkan node ketika Pod yang tertunda membutuhkannya.

## Langkah 3: Uji dengan Pod sampel
<a name="cluster-setup-tf-test-with-a-sample-pod"></a>

Uji NodePool pengaturan GPU Anda dengan `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
```

Verifikasi Pod telah dijadwalkan dan berhasil diselesaikan:

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

Keluaran yang diharapkan

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

`STATUS: Completed`Artinya `nvidia-smi` perintah berjalan dan keluar. Periksa log Pod untuk melihat GPU yang terdeteksi oleh node:

```
kubectl logs nvidia-smi
```

Keluaran yang diharapkan

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

Output menunjukkan model GPU, versi driver, versi CUDA, dan memori yang tersedia. Dalam contoh ini, Karpenter menyediakan instance G6 yang memiliki GPU NVIDIA L4 dengan memori 24 GB. Model GPU dan memori bervariasi tergantung pada jenis instance yang dipilih Karpenter. Instans G5 memiliki GPU NVIDIA A10G (24 GB), instans G6 memiliki GPU NVIDIA L4 (24 GB), dan instans G6e memiliki GPU NVIDIA L40S (48 GB).

Untuk memahami bagaimana Karpenter dan penjadwal Kubernetes berkoordinasi untuk menyediakan node dan menempatkan Pod, periksa peristiwa siklus hidup Pod:

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

Keluaran yang diharapkan

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

Peristiwa ini menunjukkan urutan penjadwalan Pod: Pod awalnya gagal menjadwalkan karena tidak ada node GPU (`FailedScheduling`), Karpenter menominasikan new NodeClaim (`Nominated`), penjadwal menetapkan Pod setelah node siap (`Scheduled`), dan kemudian image container ditarik dan dimulai. Mode Otomatis EKS memiliki tarik paralel SOCI (Seekable OCI) yang diinstal dan dikonfigurasi secara default pada instance G, P, dan Trn, dan jalur Karpenter yang dikelola sendiri mengonfigurasinya secara eksplisit melalui gerbang fitur. `FastImagePull`

**catatan**  
Pada cluster Karpenter yang dikelola sendiri, `Nominated` acara `karpenter/compute` ditampilkan sebagai pengganti. `eks-auto-mode/compute`

A NodeClaim adalah permintaan yang dibuat Karpenter untuk menyediakan node tertentu. Ini menunjukkan jenis instance, tipe kapasitas, AZ, dan apakah node siap:

```
kubectl get nodeclaims
```

Keluaran yang diharapkan

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

Jenis instance dan AZ bervariasi. Inst G-family ans apa pun dengan generasi lebih dari 4 memenuhi syarat.

**Tip**  
Jika tidak ada node yang muncul, periksa Kesalahan Kapasitas Tidak Mencukupi:  

```
kubectl get events | grep InsufficientCapacityError
```
Karpenter menyimpan penawaran yang tidak tersedia selama 3 menit. Memperluas jenis instans dan AZ yang diizinkan di Anda NodePool meningkatkan kemungkinan kapasitas pendaratan.

**catatan**  
Instans spot yang diluncurkan oleh Karpenter tidak muncul di konsol Permintaan Spot EC2. Karpenter menggunakan API EC2 dengan [`CreateFleet`](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateFleet.html). `type: instant` Instans muncul di konsol Instans EC2 dengan `spot` siklus hidup.

## Langkah 4: Tambahkan kapasitas cadangan ke NodePool (opsional)
<a name="cluster-setup-tf-attach-odcr"></a>

Sementara GPU NodePool dari Langkah 2 menyediakan Spot atau On-Demand instance secara dinamis, beberapa kasus penggunaan memerlukan kapasitas yang dijamin. Anda dapat membuat Reservasi On-Demand Kapasitas (ODCR) untuk memastikan kapasitas GPU tersedia bila diperlukan.

Dengan Terraform, satu perintah membuat ODCR, kustom NodeClass yang mereferensikan reservasi berdasarkan tag, dan memperbarui NodePool untuk disertakan `reserved` sebagai tipe kapasitas. Terraform menandai ODCR dengan `nodepool=reserved-spot-ondemand` dan memilihnya dengan NodeClass tag itu.

**Awas**  
Perintah berikut membuat ODCR yang menagih segera dan melanjutkan penagihan sampai Anda menghancurkannya dengan `terraform destroy` atau skrip pembersihan, terlepas dari apakah node berjalan di atasnya atau tidak.

Gunakan default (`g6e.4xlarge`, 1 instance, cluster pertama AZ):

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

Pilih jenis instance, hitungan, dan AZ:

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

Ob `reservation` jek mendukung bidang berikut:
+  `instance_type`— Jenis instance GPU yang akan dipesan. Default: `g6e.4xlarge`.
+  `instance_count`— Jumlah contoh yang harus dipesan. Default: `1`.
+  `az`— Zona Ketersediaan untuk reservasi. Default: `""` (menggunakan cluster pertama AZ).

**penting**  
Strategi `spot-ondemand` dan `reserved-spot-ondemand` saling eksklusif. Anda dapat mengaktifkan paling banyak satu dalam `nodepools` variabel. Jika sebelumnya Anda menggunakan `spot-ondemand` pada Langkah 2, `reserved-spot-ondemand` perintah menggantikannya karena keduanya mengelola hal yang sama `gpu-inf` NodePool.

Jika Anda mendapatkan `InsufficientInstanceCapacity` kesalahan, reservasi tidak dapat dipenuhi di AZ yang ditentukan. Batalkan operasi Terraform (Ctrl\+C), lalu jalankan kembali dengan nilai yang berbeda: `az`

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

Setelah mendaftar, Terraform memperbarui NodePool untuk menyertakan`reserved`,`spot`, dan `on-demand` dalam persyaratan tipe kapasitas. Karpenter memperlakukan `reserved` sebagai opsi yang paling hemat biaya dan meluncurkannya terlebih dahulu. Setelah reservasi penuh, reservasi akan kembali ke Spot atau On-Demand.

Pada jalur Mode Otomatis EKS, Terraform membuat kustom `gpu-inf` NodeClass (karena yang dibundel `default` NodeClass adalah read-only) yang mereferensikan ODCR berdasarkan tag melalui. `capacityReservationSelectorTerms` Pada jalur Karpenter yang dikelola sendiri, Terraform menerapkan kembali `gpu-inf` EC2NodeClass dengan `capacityReservationSelectorTerms` menambahkan dan memperbarui untuk disertakan. NodePool `reserved`

Verifikasi ODCR telah dibuat:

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

Verifikasi NodeClass referensi ODCR:

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

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

Keluaran yang diharapkan

```
        id: cr-xxxxxxxxxxxxxxxxx
```

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

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

Keluaran yang diharapkan

```
        id: cr-xxxxxxxxxxxxxxxxx
```

------

Verifikasi NodePool sudah siap:

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

Keluaran yang diharapkan

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

### Verifikasi bahwa kapasitas cadangan digunakan terlebih dahulu, dengan fallback Spot
<a name="cluster-setup-tf-step4-validate"></a>

Setelah menerapkan perubahan, validasi bahwa Karpenter memprioritaskan kapasitas yang dicadangkan dan kembali ke Spot atau. On-Demand Terapkan Deployment 2-replika yang meminta 1 GPU per Pod. ODCR adalah untuk 1 instance (1 GPU), jadi Pod pertama memicu Karpenter untuk meluncurkan node cadangan. Pod kedua tidak dapat muat pada node yang dicadangkan dan memicu Karpenter untuk meluncurkan node lain dari Spot atau On-Demand kapasitas.

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

Berbeda `nvidia-smi` dengan Pod uji dari Langkah 3 yang berjalan dan keluar, Deployment ini membuat Pod tetap berjalan (`sleep infinity`) sehingga mereka menahan GPU dan mencegah node dikonsolidasikan.

Verifikasi Pod yang dijadwalkan pada node yang berbeda:

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

Keluaran yang diharapkan

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

Periksa NodeClaims untuk melihat jenis kapasitas:

```
kubectl get nodeclaims
```

Keluaran yang diharapkan

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

Node cadangan diluncurkan terlebih dahulu, diikuti oleh Spot atau On-Demand node setelah reservasi penuh.

Bersihkan penyebaran pengujian:

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

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

Terraform sudah menyediakan tumpukan pemantauan penuh selama `terraform apply` di Langkah 1. Tumpukan tersebut mencakup ruang kerja Amazon Managed Service for Prometheus (AMP), kebijakan IAM dan Asosiasi Identitas Pod EKS untuk akses kueri penulisan jarak jauh dan Grafana Prometheus, bagan Helm kube-prometheus-stack (Prometheus, Grafana, kube-state-metrics, node-eksportir), dan Eksportir NVIDIA DCGM untuk metrik GPU.

Bagian ini mencakup verifikasi komponen pemantauan yang digunakan.

### Verifikasi pod pemantauan
<a name="_verify_monitoring_pods"></a>

Tunggu hingga semua pod pemantauan siap:

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

Keluaran yang diharapkan

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

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

Grafana diekspos melalui Application Load Balancer (ALB) yang menghadap ke internet AWS , terbatas pada CIDR yang Anda tetapkan. `var.my_cidr` Cetak URL penyeimbang beban (izinkan satu atau dua menit untuk penyediaan ALB):

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

Buka URL di browser Anda. Masuk dengan nama pengguna `admin` dan kata sandi dari perintah berikut:

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

### Verifikasi pipeline metrik
<a name="_verify_the_metrics_pipeline"></a>

Untuk memverifikasi pipeline metrik bekerja dari ujung ke ujung:

1. Arahkan ** ke Koneksi> Sumber data ** dan konfirmasi ** Amazon-Managed-Prometheus ** terdaftar sebagai sumber data default.

    **Validasi sumber data AMP di Grafana **   
![Halaman Koneksi Grafana ditampilkan Amazon-Managed-Prometheus terdaftar sebagai sumber data default](http://docs.aws.amazon.com/id_id/eks/latest/userguide/images/ml-cluster-setup-cli-prometheus-ds-validate.png)

1. Arahkan ke ** Drilldown > Metrics ** dan cari metrik. `up` Anda akan melihat hasil dari target gores cluster Anda.

    **Validasi `up` metrik di Grafana **   
![Halaman Grafana Drilldown Metrics menampilkan metrik atas dengan bilah status hijau yang menunjukkan target pengikisan aktif](http://docs.aws.amazon.com/id_id/eks/latest/userguide/images/ml-cluster-setup-cli-prometheus-metrics-validate.png)

Jika `up` menunjukkan hasil, pipeline (cluster → Prometheus → AMP → Grafana) berfungsi.

### Validasi metrik GPU DCGM
<a name="_validate_dcgm_gpu_metrics"></a>

Eksportir DCGM DaemonSet berjalan pada node GPU dan melaporkan pemanfaatan GPU, memori, suhu, daya tarik, bandwidth NVLink, dan metrik aktivitas tensor.

Verifikasi eksportir DCGM: DaemonSet

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

Setelah node GPU berjalan (dari Langkah 2 atau Langkah 4), Anda akan melihat satu atau lebih Pod siap. Untuk memvalidasi metrik DCGM, navigasikan ke ** Drilldown > Metrics ** di Grafana dan cari. `DCGM_`

 **Validasi metrik DCGM di Grafana ** 

![Halaman Grafana Drilldown Metrics difilter oleh DCGM_ menampilkan metrik GPU termasuk DCGM_FI_DEV_ECC_SBE_VOL_TOTAL, DCGM_FI_DEV_ENC_UTIL, DCGM_FI_DEV_FB_FREE, dan DCGM_FI_DEV_FB_USED](http://docs.aws.amazon.com/id_id/eks/latest/userguide/images/ml-cluster-setup-cli-dcgm-metrics-validate.png)


Untuk melihat dasbor, navigasikan ke ** Dasbor> Pemantauan GPU> Dasbor Eksportir NVIDIA DCGM. **

 **Dasbor Eksportir NVIDIA DCGM di Grafana ** 

![Dasbor Eksportir NVIDIA DCGM Grafana menunjukkan Pemanfaatan GPU, Suhu Rata-rata GPU, Mem Framebuffer GPU Digunakan, dan panel Total Daya GPU](http://docs.aws.amazon.com/id_id/eks/latest/userguide/images/ml-cluster-setup-cli-dcgm-dashboard.png)


## Model bobot ember S3
<a name="cluster-setup-tf-model-bucket"></a>

Terraform sudah membuat bucket Amazon S3 untuk menyimpan bobot model, a `model-storage-sa` ServiceAccount di `default` namespace, kebijakan IAM yang dicakup ke bucket, dan EKS Pod Identity Association yang menautkannya. Pod beban kerja yang diatur `serviceAccountName: model-storage-sa` dapat membaca dari dan menulis ke bucket.

### Verifikasi ember
<a name="_verify_the_bucket"></a>

Ambil nama bucket dari output Terraform:

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

Verifikasi bucket ada:

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

Keluaran yang diharapkan

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

#### Memvalidasi akses S3 dari Pod
<a name="cluster-setup-tf-s3-validate"></a>

Jalankan Pod satu kali dengan gambar AWS CLI, menggunakan `model-storage-sa` ServiceAccount, untuk mengonfirmasi EKS Pod Identity terhubung dan akses S3 berfungsi:

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

Tunggu hingga Pod selesai dan periksa log:

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

Keluaran yang diharapkan

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

Identitas pemanggil mengonfirmasi bahwa Pod mengambil peran penyimpanan model melalui EKS Pod Identity. Perintah S3 mengkonfirmasi akses baca dan tulis.

Bersihkan Pod uji:

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

## Langkah selanjutnya
<a name="cluster-setup-tf-next-steps"></a>

Dengan cluster Anda siap, Anda dapat melanjutkan ke [ Load & Serve Model ](ml-inference-load-serve-model.md) untuk menerapkan model bahasa besar dan berinteraksi dengan titik akhir inferensi.

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

**Tip**  
Jika Anda berencana untuk melanjutkan dengan bagian selanjutnya dari panduan ini, lewati pembersihan penuh. Jalankan hanya ketika Anda selesai.

Hapus beban kerja pengujian sehingga tidak ada Pod yang menahan node GPU:

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

### Batalkan Reservasi Kapasitas tanpa menghancurkan cluster
<a name="cluster-setup-tf-cleanup-cancel-reservation"></a>

Jika Anda hanya ingin melepaskan ODCR dan kembali ke Spot dan On-Demand kapasitas, alihkan `nodepools` variabel kembali ke `spot-ondemand` strategi:

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

Ini turun `reserved` dari persyaratan NodePool tipe kapasitas dan menghancurkan ODCR, dan meninggalkan cluster, tumpukan pemantauan, dan bucket S3 di tempatnya.

**penting**  
Membatalkan reservasi tidak menghentikan instans yang sudah berjalan di dalamnya. Instans tersebut terus berjalan pada On-Demand tarif standar sampai dihentikan. Hapus beban kerja GPU terlebih dahulu, seperti yang ditunjukkan di atas, sehingga node yang dicadangkan habis sebelum reservasi dilepaskan.

### Hancurkan cluster dan semua Terraform-managed sumber daya
<a name="cluster-setup-tf-cleanup-destroy"></a>

Kuras Karpenter-managed node sebelum menghancurkan, sehingga tidak ada siklus hidup node dalam penerbangan yang menghalangi penghancuran. Hapus semua PodDisruptionBudgets yang akan mencegah pembuangan, lalu hapus NodeClaims:

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

Kemudian hancurkan semua yang dibuat Terraform, termasuk cluster EKS, VPC, tumpukan pemantauan, NodePools dan, bucket model S3 NodeClasses, dan ODCR apa pun:

```
terraform destroy
```

**Awas**  
Bucket S3 dengan bobot model dibuat`force_destroy = true`, jadi hapus `terraform destroy` bucket beserta bobot model apa pun yang Anda unggah ke dalamnya. Salin apa pun yang ingin Anda simpan ke lokasi lain terlebih dahulu.

**catatan**  
Repositori juga mengirimkan bantuan yang `scripts/cleanup.sh` menjalankan langkah pembuangan dan penghancuran di atas dan kemudian menyapu volume EBS yatim piatu yang ditandai dengan nama cluster. Jalankan dari dalam `terraform/<mode>/` direktori tempat Anda mendaftar, dan lewati `--auto-approve` untuk melewati prompt konfirmasi Terraform.

### Verifikasi reservasi hilang
<a name="cluster-setup-tf-cleanup-verify"></a>

Konfirmasikan tidak ada Reservasi Kapasitas aktif yang tersisa untuk cluster:

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

Hasil kosong berarti tidak ada reservasi yang aktif dan tidak ada biaya tambahan yang dikenakan.