View a markdown version of this page

Siapkan klaster Amazon EKS untuk AI/ML beban kerja menggunakan CLI - Amazon EKS

Bantu tingkatkan 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 Edit halaman ini pada GitHub tautan 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.

Siapkan klaster Amazon EKS untuk AI/ML beban kerja menggunakan CLI

Tip

Daftar 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 melalui perintah CLI. Langkah-langkahnya termasuk membuat cluster EKS, GPU-enabled node dengan Mode Otomatis EKS atau Karpenter, tumpukan pemantauan dengan Prometheus dan Grafana, dan penyimpanan Amazon S3 untuk bobot model.

Lihat dokumentasi untuk Mode Otomatis EKS dan Karpenter untuk informasi selengkapnya tentang bagaimana fitur tersebut menyediakan dan menskalakan instans EC2 secara otomatis di kluster EKS.

High-level arsitektur dan alur kerja

High-level arsitektur yang menampilkan klaster EKS dengan Karpenter NodeClass dan NodePool, penulisan tumpukan pemantauan Grafana dan Prometheus ke Amazon Managed Service for Prometheus, bucket Amazon S3 untuk bobot model, dan langkah alur kerja bernomor

Diagram menunjukkan arsitektur AWS tingkat tinggi untuk pengaturan bagian ini. Langkah-langkah bernomor di sebelah kanan menunjukkan urutan di mana Anda menyelesaikan konfigurasi pada langkah-langkah di bawah ini.

Prasyarat

  • kubectl>= 1,35. Untuk petunjuk penyiapan, lihatSiapkan kubectl dan eksctl.

  • AWS CLI >= 2.27. Untuk petunjuk penyiapan, lihat Menginstal.

  • Helm >= 3.14. Untuk petunjuk penyiapan, lihat Setup Helm.

  • jq. Untuk petunjuk penyiapan, lihat Unduh jq.

  • eksctl>= 0.227.0. Untuk petunjuk penyiapan, lihat Instalasi dalam eksctl dokumentasi.

Verifikasi eksctl versi Anda:

eksctl version

Jika Anda menggunakan versi yang lebih lama dari 0.227.0, ikuti panduan instalasi eksctl untuk meningkatkan ke rilis terbaru.

Tetapkan variabel lingkungan

Jaga agar nama klaster dan AWS Wilayah berikut tetap konsisten di seluruh langkah ini. Mengubahnya dapat menyebabkan perintah berikutnya menargetkan cluster EKS yang salah.

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

Menggunakan semua AZ yang tersedia meningkatkan toleransi kesalahan dan meningkatkan peluang mendapatkan kapasitas GPU:

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
penting

Availability Zones use1-az3usw1-az2,, dan cac1-az3 dikecualikan karena Amazon EKS tidak mendukung penempatan pesawat kontrol di zona tersebut. Membuat cluster dengan subnet di salah satu zona ini menghasilkan fileUnsupportedAvailabilityZoneException.

Keluaran yang diharapkan

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

AZ dalam output akan bervariasi per wilayah. Contoh ini menunjukkan AZ yang tersedia untuk us-east-2 wilayah.

Buat cluster dan GPU NodePool

Bagian ini menyediakan dua jalur untuk membuat kluster dan GPU-enabled node EKS Anda, yang ditunjukkan pada diagram berikut. Pilih hanya satu opsi di seluruh panduan.

  • Mode Otomatis EKS — Selain add-on 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 SOCI untuk penarikan kontainer cepat, dan kesiapan GPU untuk default. NodeClass Plugin perangkat NVIDIA termasuk dalam AMI yang dipercepat Bottlerocket yang digunakan Mode Otomatis EKS untuk node. GPU-enabled

  • Self-managed Karpenter — Pada cluster EKS tanpa Mode Otomatis EKS, Anda bertanggung jawab untuk 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 node EKS, plugin perangkat NVIDIA, dan snapshotter SOCI untuk penarikan kontainer cepat.

Opsi kluster EKS: Mode Otomatis EKS dan Karpenter yang dikelola sendiri

Side-by-side perbandingan dua opsi cluster: cluster Mode Otomatis EKS dengan NodePool, dan kluster standar EKS dengan Karpenter yang dikelola sendiri, CoreDNS, VPC CNI, plugin perangkat NVIDIA, agen Identitas Pod EKS, Agen Pemantauan Node, kube-proxy, dan a dan NodeClass NodePool

Di setiap langkah berikut, pilih jalur (Mode Otomatis EKS, Karpenter) dan ikuti seluruhnya. Setelah menyelesaikan langkah-langkah untuk jalur yang Anda pilih, Anda akan memiliki cluster EKS dengan GPU yang NodePool siap menjadwalkan beban kerja GPU.

Langkah 1: Buat klaster

Mulailah dengan membuat kluster EKS Anda dan menginstal komponen cluster yang diperlukan untuk beban kerja GPU.

Dengan Mode Otomatis EKS, satu eksctl create cluster --enable-auto-mode perintah menyediakan kluster EKS yang siap untuk beban kerja GPU.

Dengan Karpenter yang dikelola sendiri, eksctl create cluster perintah tersebut menyediakan add-on jaringan inti, kemudian langkah-langkah tambahan diperlukan untuk mengaktifkan perbaikan node otomatis melalui gerbang fitur Karpenter, menginstal agen pemantauan node EKS, dan menginstal plugin perangkat NVIDIA.

EKS Auto Mode

Buat kluster Mode Otomatis EKS

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

Perintah ini membutuhkan waktu beberapa menit untuk menyelesaikannya. Setelah selesai, eksctl secara otomatis memperbarui file kubeconfig Anda agar berfungsi dengan cluster yang baru disediakan. Verifikasi bahwa cluster beroperasi:

kubectl get pods --all-namespaces

Keluaran yang diharapkan

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

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

Self-managed Karpenter

Otentikasi Helm ke ECR publik

eksctlmenarik bagan Karpenter Helm dari Amazon Public ECR. Otentikasi sebelum membuat cluster untuk menghindari kesalahan 403 pada langkah instalasi Helm:

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

ECR publik adalah layanan global yang diselenggarakan dius-east-1. Gunakan --region us-east-1 di sini terlepas dari wilayah mana cluster EKS Anda berada.

Output yang diharapkan: Login Succeeded

Buat cluster EKS dengan Karpenter

Simpan versi Karpenter Anda dalam variabel lingkungan untuk digunakan nanti. Untuk versi Karpenter terbaru, lihat rilis Karpenter di. GitHub

export KARPENTER_VERSION=1.12.0
cat << EOF > /tmp/cluster-karpenter.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ${CLUSTER_NAME} region: ${AWS_REGION} version: "1.35" 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 instanceType: m6i.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 EOF eksctl create cluster -f /tmp/cluster-karpenter.yaml

Perintah ini memakan waktu sekitar 15 menit. Ini menciptakan cluster EKS dengan grup node terkelola yang didedikasikan untuk hosting add-on dan pengontrol Karpenter. Karpenter dipasang dengan antrean interupsi Spot diaktifkan sehingga dapat menangani gangguan Spot dan rekomendasi penyeimbangan kembali. autoModeConfig.enabled: falsePengaturan membuatnya eksplisit bahwa cluster ini tidak menggunakan Mode Otomatis EKS, sehingga komponen Karpenter yang dipasang di jalur ini bertanggung jawab untuk manajemen node.

Cluster ini juga mendapatkan Agen Identitas Pod EKS dan agen pemantauan node EKS diinstal sebagai add-on EKS. EKS Pod Identity digunakan nanti dalam panduan. Agen pemantauan node EKS berjalan pada setiap node dan membaca log kernel untuk mengatur kondisi node sepertiAcceleratedHardwareReady,, dan KernelReadyNetworkingReady, yang digunakan perbaikan node otomatis Karpenter untuk memutuskan kapan harus mengganti node yang tidak sehat.

Verifikasi bahwa cluster beroperasi:

kubectl get pods --all-namespaces

Output yang diharapkan meliputi Karpenter, CoreDNS, kube-proxy, aws-node (VPC CNI), Agen Identitas Pod EKS, dan agen pemantauan node EKS.

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

Aktifkan perbaikan node otomatis

Mode Otomatis EKS memungkinkan perbaikan node otomatis secara default. Pada Karpenter yang dikelola sendiri, perbaikan node otomatis terjaga keamanannya di belakang gerbang NodeRepair=true fitur dan harus diaktifkan secara eksplisit. Perintah berikut menambal penyebaran Karpenter untuk menambahkan gerbang fitur. NodeRepair=true Memperbarui env penerapan memicu peluncuran pod Karpenter:

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

Keluaran yang diharapkan

deployment.apps/karpenter env updated

Tunggu pod Karpenter diluncurkan:

kubectl rollout status deployment/karpenter -n karpenter

Instal plugin perangkat NVIDIA

EKS-optimized AL2023 AMI tidak menyertakan plugin perangkat NVIDIA (tidak seperti AMI Bottlerocket yang digunakan oleh Mode Otomatis EKS). Instal melalui Helm untuk membuat resource GPU dapat digunakan dengan Pod di cluster.

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: menonaktifkan cek untuk Mellanox OFED (InfiniBand), yang tidak menggunakan AWS

  • nodeSelector.amiFamily: al2023: mencakup node DaemonSet ke AL2023 saja (Bottlerocket sudah memiliki plugin bawaan)

  • gfd.enabled: true: mengaktifkan label Penemuan Fitur GPU (nvidia.com/gpu.product,nvidia.com/gpu.memory, dll.)

Verifikasi plugin perangkat NVIDIA diinstal. Harapannya adalah tidak ada Pod plugin perangkat hingga GPU NodePool dengan 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 2m5s
Awas

Untuk Mode Otomatis EKS dan jalur Karpenter yang dikelola sendiri, perbaikan node otomatis berperilaku dengan cara yang sama untuk node yang disediakan oleh. NodePools Perbaikan node otomatis di EKS Auto Mode dan Karpenter adalah metode gangguan kuat yang memintas PodDisruptionBudgets, anotasi, dan. karpenter.sh/do-not-disrupt terminationGracePeriod Perbaikan node otomatis menunggu 10 menit sebelum mengganti node dengan AcceleratedHardwareReady kondisi yang disetel ke False dan 30 menit untuk kondisi perbaikan lainnya.

Langkah 2: Buat GPU dinamis NodePool

Tentukan instans GPU NodePool yang secara dinamis G-family menyediakan instans GPU dengan generasi lebih besar dari 4, menggunakan kapasitas Spot On-Demand sebagai fallback. Jalur Mode Otomatis EKS dan Karpenter keduanya menggunakan NodePool API yang sama dengan satu-satunya perbedaan adalah yang NodeClass ditunjuknya. Dalam Mode Otomatis EKS, bundel default NodeClass sudah memilih AMI yang tepat dan mengonfigurasi tarikan paralel SOCI, jadi satu-satunya objek NodePool yang Anda buat. Di Karpenter yang dikelola sendiri, Anda juga memerlukan kustom EC2NodeClass yang menyematkan AMI dan menyetel SOCI.

EKS Auto Mode

Dalam Mode Otomatis EKS, bundel default NodeClass secara otomatis memilih AMI Bottlerocket untuk instance GPU, yang mencakup driver NVIDIA yang sudah diinstal sebelumnya, plugin perangkat NVIDIA, dan tarik paralel SOCI. Anda hanya perlu menerapkan a NodePool yang mereferensikan 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: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF

Ini menyediakan NodePool instans G-family GPU dengan generasi lebih besar dari 4 (G5, G6e, G7e, dll.). nvidia.com/gpu:NoScheduleTaint memastikan hanya GPU-eligible Pod yang dijadwalkan pada node ini.

Self-managed Karpenter

Self-managed Karpenter tidak menyertakan default. NodeClass Pertama-tama Anda membuat EC2NodeClass yang menyematkan alias AMI EKS-optimized NVIDIA AL2023, mengaktifkan SOCI FastImagePull melalui gerbang fitur, dan instanceStorePolicy: RAID0 mengonfigurasi untuk memindahkan cache gambar containerd ke NVMe lokal. Kemudian Anda membuat referensi NodePool itu.

Buat EC2NodeClass

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: | MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="BOUNDARY" --BOUNDARY Content-Type: application/node.eks.aws --- apiVersion: node.eks.aws/v1alpha1 kind: NodeConfig spec: featureGates: FastImagePull: true containerd: config: | [plugins."io.containerd.snapshotter.v1.soci"] [plugins."io.containerd.snapshotter.v1.soci".blob] max_concurrent_downloads_per_image = 20 concurrent_download_chunk_size = "16mb" max_concurrent_unpacks_per_image = 12 discard_unpacked_layers = true --BOUNDARY-- EOF

instanceStorePolicy: RAID0merakit disk NVMe lokal menjadi array. RAID-0 Alias al2023@latest AMI menyelesaikan AMI AL2023 EKS-optimized . Ketika Karpenter meluncurkan jenis instans GPU, secara otomatis memilih varian akselerasi AL2023_X86_64_NVIDIA, yang mencakup driver NVIDIA yang sudah diinstal sebelumnya.

Gerbang FastImagePull fitur memungkinkan mode tarik paralel snapshotter SOCI, yang mengunduh dan membongkar lapisan gambar secara bersamaan. Ini cocok dengan perilaku Mode Otomatis EKS pada keluarga instance G, P, dan Trn. containerd.configBlok menyetel snapshotter SOCI untuk gambar: ECR-hosted

  • max_concurrent_downloads_per_image: 20memungkinkan hingga 20 lapisan unduhan secara paralel per gambar. Defaultnya adalah 3 di Bottlerocket dan 20 di AL2023. Nilai yang disarankan untuk ECR.

  • concurrent_download_chunk_size: "16mb"membagi setiap lapisan menjadi potongan 16 MB yang diunduh secara paralel melalui permintaan rentang HTTP. Direkomendasikan untuk pendaftar yang mendukung jangkauan GET (ECR tidak).

  • max_concurrent_unpacks_per_image: 12membongkar hingga 12 lapisan sekaligus. Defaultnya adalah 1 di Bottlerocket dan 12 di AL2023.

  • discard_unpacked_layers: truemenghapus gumpalan lapisan terkompresi setelah membongkar untuk menghemat ruang disk.

Untuk opsi penyetelan SOCI lainnya (unduhan bersamaan per gambar, ukuran potongan, dll.), Lihat cetak biru Karpenter SOCI.

Validasi: EC2NodeClass

kubectl get ec2nodeclass gpu-inf

Output yang diharapkan:READY True. JikaFalse, jalankan kubectl describe ec2nodeclass gpu-inf dan periksa kondisi untuk tag subnet atau grup keamanan yang hilang.

Buat GPU NodePool

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: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF

amiFamily: al2023Label pada template node adalah apa yang DaemonSet digunakan plugin perangkat NVIDIA untuk memilih node ini.

Validasi yang NodePool telah dibuat:

kubectl get nodepool gpu-inf

Keluaran yang diharapkan

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

Di jalur Karpenter yang dikelola sendiri, kolom NODECLASS menunjukkan alih-alih. gpu-inf default

Langkah 3: Uji dengan sampel Pod

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

Verifikasi bahwa Pod sudah dijadwalkan dan diselesaikan dengan sukses.

kubectl get pods

Keluaran yang diharapkan

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

STATUS: Selesai berarti perintah nvidia-smi berjalan dan keluar. Periksa log Pod untuk melihat GPU terdeteksi oleh node.

kubectl logs nvidia-smi

Keluaran yang diharapkan

+-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 580.126.09 Driver Version: 580.126.09 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 RTX PRO 6000 Blac... On | 00000000:2B:00.0 Off | 0 | | N/A 30C P0 81W / 600W | 0MiB / 97887MiB | 0% Default | | | | Disabled | +-----------------------------------------+------------------------+----------------------+

Output menunjukkan model GPU, versi driver, versi CUDA, dan memori yang tersedia. Dalam contoh ini, Karpenter menyediakan instance G7e yang memiliki GPU NVIDIA RTX PRO 6000 Blackwell dengan memori 96 GB. 30C adalah suhu GPU saat ini dan P0 berarti GPU berada dalam kondisi kinerja tertinggi (idle tapi siap). 81W/600W menunjukkan penarikan daya saat ini vs kapasitas daya maks, dan 0MiB/97887MiB menunjukkan memori GPU saat ini yang digunakan vs total yang tersedia. Karena Pod baru saja menjalankan nvidia-smi dan keluar, tidak ada beban kerja yang menggunakan GPU sehingga memori berada pada 0 dan daya saat idle. Versi driver GPU NVIDIA (580.126.09) berasal dari Bottlerocket AMI, sedangkan versi CUDA (13.0) berasal dari gambar kontainer. Model dan memori GPU akan bervariasi tergantung pada jenis instance yang dipilih Karpenter. Instans G5 memiliki GPU NVIDIA A10G (24 GB), instans G6e memiliki GPU NVIDIA L40S (48 GB), dan instance G7e memiliki GPU NVIDIA RTX PRO 6000 (96 GB).

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

kubectl describe po nvidia-smi

Keluaran yang diharapkan

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

Peristiwa ini menunjukkan urutan penjadwalan Pod: Pod awalnya gagal menjadwalkan karena tidak ada node GPU yang ada (FailedScheduling), Karpenter menominasikan new NodeClaim (Nominated), scheduler menetapkan Pod setelah node siap (Terjadwal), dan kemudian gambar kontainer ditarik dan dimulai. EKS Auto Mode dilengkapi dengan parallel pull SOCI (Seekable OCI) yang dipasang dan dikonfigurasi di luar kotak pada instance G, P, dan Trn. Perhatikan karena tarikan paralel SOCI, gambar kontainer ditarik dari ECR dalam waktu kurang dari 2 detik (1,237 detik).

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

kubectl get nodeclaims

NodeClaim Output yang diharapkan:

NAME            TYPE          CAPACITY    ZONE         NODE                  READY   AGE
gpu-inf-xxxxx   g7e.2xlarge   spot        us-east-2a   i-0xxxxxxxxxxxx       True    2m

Jenis instans dan AZ akan bervariasi. Setiap G-family instance dengan generasi> 4 memenuhi syarat.

FailedCreatePodSandBoxPeringatan di kubectl describe pod nvidia-smi bersifat sementara dan diharapkan. VPC CNI menginisialisasi secara asinkron setelah node bergabung, dan kubelet mencoba ulang secara otomatis. Jika Pod tetap berada di dalamContainerCreating, periksa peristiwa node dengankubectl describe node <node-name>.

Tip

Jika tidak ada node yang muncul, periksa Kesalahan Kapasitas Tidak Cukup:

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 akan muncul di konsol Permintaan Spot EC2. Karpenter menggunakan API EC2 CreateFleetdengan. type: instant Instans muncul di konsol Instans EC2 dengan siklus hidup. spot

Langkah 4: Tambahkan kapasitas cadangan ke NodePool (opsional)

Untuk menggunakan kapasitas cadangan terlebih dahulu dengan Spot/On-Demand fallback, buat ODCR dan pasang ke Anda NodeClass, lalu perbarui dinamika NodePool dari Langkah 2 untuk juga memungkinkan kapasitas. reserved Panggilan API reservasi sama untuk kedua jalur; NodeClass lampiran berbeda karena Mode Otomatis EKS dan Karpenter yang dikelola sendiri menggunakan jenis yang berbeda. NodeClass

Awas

Perintah berikut menghasilkan biaya untuk jenis instans yang dicadangkan hingga Anda membatalkannyaaws ec2 cancel-capacity-reservation --capacity-reservation-id <id>.

Buat reservasi kapasitas:

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

Jika Anda mendapatkan InsufficientInstanceCapacity kesalahan, ubah CR_AZ ke AZ yang berbeda dan coba lagi.

Cari ID reservasi kapasitas dan simpan dalam variabel shell untuk langkah-langkah berikut:

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

Kemudian terapkan NodeClass dan NodePool perubahan untuk jalur Anda:

EKS Auto Mode

Dalam Mode Otomatis EKS, bundel default NodeClass hanya baca, jadi buat kustom NodeClass yang mereferensikan reservasi, lalu perbarui NodePool untuk menunjuk ke NodeClass dan tambahkan reserved kapasitas ke daftar. capacity-type

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

kubernetes.io/role/internal-elb: "1"Tag memastikan node diluncurkan di subnet pribadi saja.

Perbarui NodePool untuk menggunakan ODCR-backed NodeClass dan sertakan reserved sebagai tipe kapasitas:

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: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF
Self-managed Karpenter

Untuk Karpenter yang dikelola sendiri, terapkan kembali yang EC2NodeClass Anda buat di Langkah 2 dengan ditambahkan. capacityReservationSelectorTerms Nama dan bentuk bidang cocok dengan Mode Otomatis EKS yang NodeClass ditampilkan di tab lainnya.

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: | MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="BOUNDARY" --BOUNDARY Content-Type: application/node.eks.aws --- apiVersion: node.eks.aws/v1alpha1 kind: NodeConfig spec: featureGates: FastImagePull: true containerd: config: | [plugins."io.containerd.snapshotter.v1.soci"] [plugins."io.containerd.snapshotter.v1.soci".blob] max_concurrent_downloads_per_image = 20 concurrent_download_chunk_size = "16mb" max_concurrent_unpacks_per_image = 12 discard_unpacked_layers = true --BOUNDARY-- EOF

Satu-satunya perubahan dari Langkah 2 adalah capacityReservationSelectorTerms bidang baru. Semua bidang lainnya tetap sama.

Perbarui NodePool untuk menyertakan reserved sebagai tipe kapasitas:

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: kubernetes.io/arch operator: In values: ["amd64"] limits: cpu: 1000 memory: 5000Gi EOF

Karpenter memperlakukan reserved sebagai opsi yang paling hemat biaya dan meluncurkannya terlebih dahulu. Setelah reservasi penuh, itu jatuh kembali ke Spot atau On-Demand.

Setelah menerapkan perubahan, validasi bahwa Karpenter memprioritaskan kapasitas cadangan dan kembali ke Spot atau. On-Demand Menerapkan Deployment 2-replika yang meminta 1 GPU per Pod. ODCR adalah untuk 1 instance, jadi Pod pertama memicu Karpenter untuk meluncurkan node reserved. Pod kedua tidak bisa muat pada node reserved dan memicu Karpenter untuk meluncurkan node lain dari Spot atau kapasitas. 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

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

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

Kedua pod berjalan, masing-masing pada node yang berbeda.

Periksa NodeClaims untuk melihat jenis kapasitas:

kubectl get nodeclaims

Keluaran yang diharapkan

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

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

Bersihkan penerapan pengujian:

kubectl delete deployment gpu-overflow-test

Memantau

Instal tumpukan pemantauan yang mengumpulkan metrik cluster, node, dan GPU ke Amazon Managed Service for Prometheus (AMP), dan visualisasikan dengan Grafana. Bagan Helm kube-prometheus-stack menerapkan Prometheus untuk mengikis dan menulis metrik jarak jauh ke AMP, ditambah Grafana yang dikelola sendiri untuk dasbor. Eksportir NVIDIA DCGM menambahkan GPU-specific metrik (pemanfaatan, memori, suhu, daya, NVLink, aktivitas tensor).

Prometheus, Grafana, dan operator mendarat di node non-GPU secara default karena node GPU membawa noda. nvidia.com/gpu:NoSchedule Node-exporter dan Eksportir DCGM keduanya berjalan pada node GPU sehingga kami dapat mengikis metrik host dan GPU di seluruh armada.

Jika Anda membuka terminal baru, atur nama cluster dan wilayah:

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

Membuat ruang kerja AMP

Membuat ruang kerja AMP untuk menyimpan metrik:

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

Dapatkan ID ruang kerja:

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

Dapatkan titik akhir penulisan jarak jauh:

AMP_ENDPOINT=$(aws amp describe-workspace \ --workspace-id ${AMP_WORKSPACE_ID} \ --query 'workspace.prometheusEndpoint' \ --output text \ --region ${AWS_REGION}) echo "AMP Endpoint: ${AMP_ENDPOINT}"

Membuat kebijakan IAM dan asosiasi Identitas Pod EKS

Buat kebijakan IAM yang memungkinkan Prometheus menulis metrik dari jarak jauh dan Grafana untuk menanyainya:

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

Buat namespace pemantauan dan akun layanan untuk Prometheus dan Grafana:

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

Buat Asosiasi Identitas Pod EKS untuk menautkan akun layanan ke kebijakan IAM:

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}

Verifikasi kedua asosiasi Identitas Pod EKS telah dibuat:

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

Output yang diharapkan harus mencakup keduanya amp-iamproxy-ingest-service-account dan grafana-sa di monitoring namespace.

Instal kube-prometheus-stack

Tambahkan repo Helm:

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

File nilai ini menghilangkan NodeSelector untuk Prometheus, Grafana, dan operator: noda node GPU menjauhkan mereka dari node nvidia.com/gpu:NoSchedule GPU, sehingga mereka mendarat di sistem atau kumpulan tujuan umum secara default. Node-exporter menggunakan toleransi wildcard sehingga berjalan di setiap node — termasuk node GPU — untuk mengumpulkan metrik di seluruh armada.

Buat file nilai:

cat << EOF > /tmp/kube-prometheus-values.yaml prometheus: serviceAccount: create: false name: amp-iamproxy-ingest-service-account prometheusSpec: serviceAccountName: amp-iamproxy-ingest-service-account remoteWrite: - url: "${AMP_ENDPOINT}api/v1/remote_write" sigv4: region: "${AWS_REGION}" queueConfig: maxSamplesPerSend: 1000 maxShards: 200 capacity: 2500 retention: 5h scrapeInterval: 30s evaluationInterval: 30s podMonitorSelectorNilUsesHelmValues: false serviceMonitorSelectorNilUsesHelmValues: false alertmanager: enabled: false grafana: enabled: true serviceAccount: create: false name: grafana-sa 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 prometheus-node-exporter: tolerations: - operator: Exists EOF

Validasi variabel diisi dengan benar:

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

Anda akan melihat URL titik akhir AMP lengkap (dimulai denganhttps://aps-workspaces…​), wilayah Anda, dan baris pengekspor simpultolerations:. Jika ada yang kosong, ekspor ulang variabel dan buat ulang file.

Instal bagan:

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

Verifikasi pod sedang berjalan:

kubectl get pods -n monitoring

Keluaran yang diharapkan

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

Tumpukan menyebarkan komponen-komponen berikut:

  • Prometheus StatefulSet (): menggores metrik dan menulisnya dari jarak jauh ke AMP

  • Grafana: dasbor dan visualisasi, dikonfigurasi sebelumnya dengan sumber data AMP

  • kube-state-metrics: menghasilkan metrik tentang status objek Kubernetes (status Pod, sumber daya, status) requests/limits NodeClaim

  • node-eksportir (DaemonSet, satu per node): mengumpulkan metrik tingkat host (CPU, memori, disk, jaringan)

  • operator: mengelola sumber daya kustom Prometheus dan Alertmanager

Alertmanager dinonaktifkan dalam pengaturan ini.

Akses Grafana

Buka terminal terpisah dan port-forward untuk mengakses Grafana:

kubectl port-forward svc/kube-prometheus-stack-grafana 3000:80 -n monitoring

Buka http://localhost:3000 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

Untuk memverifikasi, pipa metrik berfungsi 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
  2. Arahkan ke Drilldown > Metrics dan cari metrik. up Anda akan melihat hasil dari target scrape cluster Anda.

    Validasi up metrik di Grafana

    Halaman Grafana Drilldown Metrics menampilkan metrik naik dengan bilah status hijau yang menunjukkan target gesekan aktif

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

Terapkan Eksportir DCGM untuk metrik GPU

Kube-prometheus-stack mengumpulkan metrik CPU dan memori tingkat node tetapi bukan metrik GPU. Eksportir NVIDIA DCGM menambahkan pemanfaatan GPU, penggunaan memori, suhu, penarikan daya, bandwidth NVLink, dan aktivitas tensor.

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

Tetapkan kunci pemilih node GPU untuk jalur Anda. Mode Otomatis EKS dan Karpenter yang dikelola sendiri menggunakan kunci label yang berbeda untuk produsen GPU.

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"

Buat file nilai eksportir DCGM:

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

customMetricsBidang ini mengesampingkan set metrik default eksportir DCGM dengan yang diperluas yang mencakup bandwidth NVLink, aktivitas tensor, throughput PCIe, kesalahan ECC, dan pelambatan termal. Untuk beban kerja inferensi, ini membantu Anda memahami apakah unit komputasi GPU sepenuhnya digunakan, apakah GPU menganggur di antara permintaan karena ukuran batch yang rendah, apakah transfer data antara CPU dan GPU merupakan hambatan, apakah pelambatan termal menyebabkan lonjakan latensi, dan berapa banyak ruang kepala memori GPU yang tersisa untuk batch yang lebih besar.

Instal eksportir DCGM:

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

tolerationsIzinkan eksportir untuk berjalan pada GPU-tainted node yang Anda sediakan di Langkah 2. serviceMonitorDengan release: kube-prometheus-stack label memastikan Prometheus menemukan dan menggoresnya secara otomatis.

Verifikasi eksportir DCGM: DaemonSet

kubectl get daemonset dcgm-exporter -n monitoring

Setelah node GPU berjalan, Anda akan melihat satu 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_DEV_USED

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

Dasbor Eksportir NVIDIA DCGM di Grafana

Grafana NVIDIA DCGM Exporter Dashboard menampilkan Pemanfaatan GPU, Suhu Rata-rata GPU, GPU Framebuffer Mem Digunakan, dan panel Total Daya GPU

Model bobot ember S3

Buat bucket Amazon S3 untuk menyimpan bobot model dan konfigurasikan Asosiasi Identitas Pod EKS sehingga pod beban kerja dapat membaca dan menulis padanya.

Jika Anda membuka terminal baru, atur nama cluster dan wilayah:

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

Buat ember S3

Buat bucket dengan akhiran acak untuk menghindari tabrakan nama:

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}

Bucket S3 yang dibuat setelah Januari 2023 memiliki enkripsi sisi server (AES256) dan pemblokiran akses publik diaktifkan secara default.

Konfigurasikan EKS Pod Identity untuk akses S3

Buat model-storage-sa ServiceAccount di default namespace, kebijakan IAM yang dicakup ke bucket model, dan Asosiasi Identitas Pod EKS yang menautkannya. Pod beban kerja yang disetel serviceAccountName: model-storage-sa akan dapat membaca dan menulis ke bucket.

kubectl create serviceaccount model-storage-sa

Buat kebijakan IAM:

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}"
catatan

Kebijakan ini memberikan s3:DeleteObject dan s3:PutObject untuk langkah validasi. Untuk pod inferensi produksi yang hanya membaca bobot model, hapus s3:PutObject dan ikuti s3:DeleteObject least-privilege.

Buat Asosiasi Identitas Pod EKS. eksctlmembuat peran IAM dengan kebijakan kepercayaan yang benar dan menautkannya ke 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}

Verifikasi asosiasi:

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

Output harus menyertakan model-storage-sa asosiasi di default namespace.

Jalankan Pod satu kali dengan image AWS CLI, menggunakan model-storage-sa ServiceAccount, untuk mengonfirmasi EKS Pod Identity tersambung 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 sampai 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-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

Identitas penelepon mengonfirmasi bahwa Pod mengambil ${CLUSTER_NAME}-model-storage-role peran melalui EKS Pod Identity. Perintah S3 mengkonfirmasi akses baca dan tulis.

Bersihkan Pod uji:

kubectl delete pod s3-test

Langkah selanjutnya

Dengan klaster Anda siap, Anda dapat melanjutkan ke Load & Serve Model untuk menerapkan model bahasa besar dan berinteraksi dengan titik akhir inferensi.

Pembersihan

Tip

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

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

Jika Anda membuat ODCR, batalkan terlebih dahulu:

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}) aws ec2 cancel-capacity-reservation --capacity-reservation-id ${CAPACITY_RESERVATION_ID}
penting

Membatalkan reservasi tidak menghentikan instans yang sedang berjalan. Mereka melanjutkan dengan On-Demand tarif standar sampai dihentikan. Hapus penerapan terlebih dahulu untuk menguras node yang dicadangkan sebelum membatalkan.

Cari kebijakan IAM ARN:

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

Cari ID ruang kerja AMP:

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

Copot pemasangan rilis Helm eksportir DCGM:

helm uninstall dcgm-exporter -n monitoring

Copot pemasangan rilis Helm kube-prometheus-stack:

helm uninstall kube-prometheus-stack -n monitoring

Hapus asosiasi Identitas Pod EKS untuk akun layanan konsumsi Prometheus:

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

Hapus asosiasi Identitas Pod EKS untuk akun layanan Grafana:

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

Hapus kebijakan IAM yang digunakan oleh Prometheus dan Grafana:

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

Menghapus ruang kerja AMP:

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

Hapus namespace pemantauan:

kubectl delete namespace monitoring

Cari nama bucket model:

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

Cari kebijakan IAM ARN:

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

Hapus bucket model S3 dan semua objeknya:

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

Hapus asosiasi Identitas Pod EKS:

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

Hapus kebijakan IAM:

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

Hapus Kubernetes ServiceAccount:

kubectl delete serviceaccount model-storage-sa
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