Panduan Pengaturan Kluster Praktik Terbaik untuk Inferensi Waktu Nyata di Amazon EKS - 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.

Panduan Pengaturan Kluster Praktik Terbaik untuk Inferensi Waktu Nyata di Amazon EKS

Pengantar

Panduan ini menawarkan panduan langsung untuk menyiapkan kluster Amazon Elastic Kubernetes Service (EKS) Amazon Elastic yang dioptimalkan untuk beban kerja inferensi online real-time, menggabungkan praktik terbaik yang dikuratori oleh para ahli di seluruh dunia. AWS Ini menggunakan Arsitektur EKS Quickstart yang berpendirian — serangkaian driver, tipe instans, dan konfigurasi yang dikuratori yang selaras dengan AWS praktik terbaik untuk model, akselerator, dan penskalaan. Pendekatan ini membantu Anda melewati tugas memilih pengaturan cluster, memungkinkan Anda untuk mendapatkan cluster fungsional yang telah dikonfigurasi sebelumnya dan berjalan dengan cepat. Sepanjang jalan, kami akan menerapkan beban kerja sampel untuk memvalidasi pengaturan Anda, menjelaskan konsep arsitektur utama (seperti memisahkan tugas terikat CPU dari komputasi intensif GPU), menjawab pertanyaan umum (misalnya, mengapa memilih Bottlerocket AMI di atas 023?) AL2 , dan uraikan langkah selanjutnya untuk memperluas kemampuan cluster Anda.

Dirancang khusus untuk insinyur Machine Learning dan Artificial Intelligence (AI), administrator platform, operator, dan data/AI spesialis yang baru mengenal ekosistem AWS dan EKS, panduan ini mengasumsikan keakraban dengan Kubernetes tetapi tidak memiliki pengalaman EKS sebelumnya. Ini dirancang untuk membantu Anda memahami langkah-langkah dan proses yang diperlukan untuk mendapatkan beban kerja inferensi online real-time dan berjalan. Panduan ini menunjukkan kepada Anda hal-hal penting dalam membuat cluster inferensi simpul tunggal, termasuk penyediaan sumber daya GPU, mengintegrasikan penyimpanan untuk artefak model, mengaktifkan akses layanan yang aman, dan mengekspos titik akhir inferensi. AWS Secara keseluruhan, ini menekankan latensi rendah, desain tangguh untuk aplikasi yang dihadapi pengguna seperti deteksi penipuan, chatbots waktu nyata, dan analisis sentimen dalam sistem umpan balik pelanggan.

Dalam panduan ini, kami fokus secara eksklusif pada pengaturan titik awal yang mendasar dan preskriptif menggunakan instans G5. EC2 Jika Anda mencari konfigurasi atau end-to-end alur kerja klaster AWS khusus Inferensia, lihat Menggunakan instans AWS Inferentia dengan Amazon EKS untuk Machine Learning atau lokakarya kami di. Sumber daya untuk memulai AI/ML di Amazon EKS

Sebelum Anda mulai

Sebelum memulai, pastikan Anda telah melakukan tugas-tugas berikut:

Arsitektur

Inferensi online real-time mengacu pada proses menggunakan model pembelajaran mesin terlatih untuk menghasilkan prediksi atau output pada aliran data yang masuk dengan latensi minimal. Misalnya, memungkinkan deteksi penipuan real-time, klasifikasi gambar, atau pembuatan grafik pengetahuan dalam menanggapi input pengguna. Arsitektur sistem inferensi online real-time memberikan prediksi pembelajaran mesin latensi rendah dalam aplikasi yang dihadapi pengguna dengan memisahkan penanganan lalu lintas web terikat CPU dari komputasi AI intensif GPU. Proses ini biasanya hidup dalam ekosistem aplikasi yang lebih besar, dan sering kali mencakup layanan backend, frontend, vektor, dan model, dengan fokus pada komponen khusus untuk memungkinkan penskalaan independen, pengembangan paralel, dan ketahanan terhadap kegagalan. Mengisolasi tugas inferensi pada perangkat keras GPU khusus dan memanfaatkan antarmuka seperti APIs dan WebSockets memastikan konkurensi tinggi, pemrosesan model yang cepat seperti transformator, dan interaksi pengguna melalui frontend. Perhatikan bahwa meskipun database vektor dan pipeline Retrieval Augmented Generation (RAG) sering memainkan peran besar dalam sistem inferensi waktu nyata, komponen ini tidak tercakup dalam panduan ini. Minimal, arsitektur khas sering kali mencakup:

  • Layanan Frontend: Berfungsi sebagai antarmuka yang menghadap pengguna, menangani logika sisi klien, merender konten dinamis, dan memfasilitasi interaksi waktu nyata, berkomunikasi dengan layanan backend untuk memulai permintaan inferensi dan menampilkan hasil, sering kali memulai permintaan ke layanan backend yang digunakan untuk streaming pembaruan atau untuk pertukaran data terstruktur. WebSockets APIs Layanan ini biasanya tidak memerlukan penyeimbang beban khusus, karena dapat di-host di jaringan pengiriman konten (CDNs) seperti AWS CloudFront untuk aset statis atau disajikan langsung dari server web, dengan penskalaan ditangani melalui grup auto-scaling jika diperlukan untuk konten dinamis.

  • Layanan Backend: Bertindak sebagai orkestrator aplikasi, mengelola logika bisnis seperti otentikasi pengguna, validasi data, dan koordinasi layanan (misalnya, melalui APIs untuk titik akhir atau untuk RESTful koneksi persisten). WebSockets Ini berkomunikasi dengan layanan inferensi, menskalakan secara independen pada multi-core CPUs dan RAM untuk menangani lalu lintas web yang tinggi tanpa mengandalkan GPUs, dan seringkali memerlukan penyeimbang beban (seperti AWS Application Load Balancer atau Network Load Balancer) untuk mendistribusikan permintaan masuk di beberapa instance, terutama dalam skenario konkurensi tinggi. Pengontrol ingress selanjutnya dapat mengelola akses eksternal dan aturan perutean untuk meningkatkan keamanan dan pembentukan lalu lintas.

  • Layanan Inferensi: Berfungsi sebagai inti untuk perhitungan AI, berjalan GPUs dengan VRAM yang cukup (misalnya, 8-12 GB untuk model seperti DistiLbert) untuk melakukan penyematan vektor, ekstraksi pengetahuan, dan inferensi model (misalnya, diekspos melalui permintaan batch atau APIs untuk streaming waktu nyata) menggunakan model kustom atau WebSockets sumber terbuka. Isolasi ini mencegah konflik ketergantungan, memungkinkan pembaruan model tanpa waktu henti, dan memungkinkan penskalaan horizontal dengan penyeimbangan beban untuk beberapa permintaan bersamaan. Untuk mengekspos layanan model secara efektif, biasanya berada di belakang penyeimbang beban untuk mendistribusikan beban kerja terikat GPU di seluruh instance yang direplikasi, sementara sumber daya masuk atau pengontrol (seperti ALB Ingress Controller in AWS) menangani perutean eksternal, penghentian SSL, dan penerusan berbasis jalur untuk memastikan akses yang aman dan efisien tanpa membebani individu. GPUs

Ikhtisar Solusi

Sistem inferensi online real-time membutuhkan kinerja tinggi, arsitektur tangguh yang dapat memberikan latensi ultra-rendah sambil menangani ledakan lalu lintas volume tinggi yang tidak dapat diprediksi. Ikhtisar solusi ini menjelaskan bagaimana AWS komponen berikut bekerja sama di klaster Amazon EKS yang akan kami buat untuk memastikan klaster kami dapat meng-host dan mengelola model pembelajaran mesin yang memberikan prediksi langsung pada data langsung dengan penundaan minimal bagi pengguna akhir.

  • EC2 Instans Amazon G5 — Untuk tugas inferensi intensif GPU, kami menggunakan tipe instans G5 g5.xlarge dan g5.2xlarge, yang menampilkan satu (1) GPU NVIDIA A10G dengan memori 24GB (mis., 8 EC2 miliar parameter pada). FP16 Berdasarkan Arsitektur NVIDIA Ampere, ini GPUs didukung oleh NVIDIA A10G Tensor Core GPUs dan prosesor AMD EPYC generasi ke-2, mendukung 4-8 v, bandwidth jaringan hingga 10 GbpsCPUs, dan penyimpanan NVMe SSD lokal 250-450 GB, memastikan pergerakan data yang cepat dan daya komputasi untuk model yang kompleks, menjadikannya ideal untuk tugas inferensi latensi rendah dan throughput tinggi. Memilih jenis EC2 instans bersifat spesifik aplikasi, bergantung pada model Anda (misalnya, gambar, video, model teks), serta persyaratan latensi dan throughput Anda. Misalnya, jika menggunakan model gambar dan atau video, Anda mungkin ingin menggunakan EC2 instans P5 untuk latensi real-time yang optimal. Kami merekomendasikan memulai dengan EC2 instans G5 karena menyediakan titik awal yang baik untuk bangun dan berjalan dengan cepat, kemudian mengevaluasi apakah itu cocok untuk beban kerja Anda melalui pengujian benchmark kinerja. Untuk kasus yang lebih lanjut, pertimbangkan EC2 instance G6.

  • Instans Amazon EC2 M7g - Untuk tugas-tugas intensif CPU seperti pra-pemrosesan data, penanganan permintaan API, hosting pengontrol Karpenter, add-on, dan komponen sistem lainnya, kami menggunakan tipe instans m5.xlarge m7g. EC2 Instans M7g adalah instance berbasis ARM yang memiliki memori 4 vCPUs, 16 GB, bandwidth jaringan hingga 12,5 Gbps, dan didukung oleh prosesor Graviton3. AWS Memilih jenis EC2 instans adalah spesifik aplikasi dan bergantung pada persyaratan komputasi, memori, dan skalabilitas beban kerja Anda. Untuk beban kerja yang dioptimalkan komputasi, Anda dapat mempertimbangkan EC2 instans C7g, yang juga menggunakan prosesor Graviton3 tetapi dioptimalkan untuk kinerja komputasi yang lebih tinggi daripada instans M7g untuk kasus penggunaan tertentu. Atau, EC2 instans C8g yang lebih baru (jika tersedia) memberikan kinerja komputasi hingga 30% lebih baik daripada instans C7g. Kami merekomendasikan memulai dengan EC2 instans m7G untuk efisiensi biaya dan kompatibilitasnya dengan berbagai beban kerja (misalnya, server aplikasi, layanan mikro, server game, penyimpanan data ukuran sedang), kemudian mengevaluasi apakah itu cocok untuk beban kerja Anda melalui pengujian benchmark kinerja.

  • Driver CSI Amazon S3 Mountpoint — Untuk beban kerja pada instans GPU tunggal di mana beberapa pod berbagi GPU (misalnya, beberapa pod yang dijadwalkan pada node yang sama untuk memanfaatkan sumber daya GPU-nya), kami menggunakan Driver CSI Mountpoint S3 untuk mengoptimalkan penggunaan memori—penting untuk tugas-tugas seperti inferensi model besar dalam pengaturan yang sensitif biaya dan kompleksitas rendah. Ini mengekspos bucket Amazon S3 sebagai sistem file seperti POSIX yang tersedia untuk cluster Kubernetes, yang memungkinkan pod inferensi untuk membaca artefak model (misalnya, bobot model) langsung ke memori tanpa harus mengunduhnya terlebih dahulu, dan memasukkan kumpulan data menggunakan operasi file standar. Selain itu, S3 memiliki kapasitas penyimpanan yang hampir tidak terbatas dan mempercepat beban kerja inferensi intensif data. Memilih driver CSI penyimpanan adalah aplikasi khusus, dan tergantung pada throughput beban kerja dan persyaratan latensi Anda. Meskipun FSx untuk OpenZFS CSI Driver menawarkan latensi sub-milidetik untuk volume persisten bersama yang acak I/O atau sepenuhnya sesuai POSIX di seluruh node, kami merekomendasikan untuk memulai dengan Driver Mountpoint S3 CSI karena skalabilitasnya, biaya yang lebih rendah untuk kumpulan data besar, dan integrasi bawaan dengan penyimpanan objek yang dikelola S3 untuk pola inferensi baca-berat (misalnya, input model streaming), kemudian mengevaluasi apakah itu cocok untuk pekerjaan Anda beban melalui pengujian benchmark kinerja.

  • Agen Identitas Pod EKS — Untuk mengaktifkan akses ke AWS layanan, kami menggunakan Agen Identitas Pod EKS, yang menggunakan prinsip layanan tunggal dan memfasilitasi asosiasi peran IAM tingkat pod dalam klaster Amazon EKS. EKS Pod Identity menawarkan alternatif yang efisien untuk pendekatan IAM Roles for Service Accounts (IRSA) tradisional dengan memanfaatkan prinsip layanan tunggal (pods.eks.amazonaws.com) alih-alih mengandalkan penyedia OIDC individual untuk setiap cluster, yang membuatnya lebih mudah untuk menetapkan izin. Selain itu, ini memungkinkan peran untuk digunakan kembali di beberapa cluster dan mendukung fitur-fitur canggih seperti tag sesi peran IAM dan peran IAM Target.

  • Agen Pemantauan Node EKS — Untuk memastikan ketersediaan dan keandalan layanan inferensi yang berkelanjutan, kami menggunakan Agen Pemantauan Node EKS dengan Perbaikan Otomatis, yang secara otomatis mendeteksi dan menggantikan node yang tidak sehat, meminimalkan waktu henti. Ini terus memantau node untuk masalah perangkat keras, kernel, jaringan, dan penyimpanan menggunakan pemeriksaan kesehatan yang ditingkatkan (misalnya, KernelReady, NetworkingReady). Untuk node GPU, ia mendeteksi kegagalan khusus akselerator, memulai remediasi yang anggun dengan menutup node yang tidak sehat, menunggu 10 menit untuk menyelesaikan masalah GPU sementara, dan mengganti node setelah 30 menit untuk kegagalan persisten.

  • Bottlerocket AMI — Untuk memberikan fondasi keamanan yang diperkuat untuk cluster EKS kami, kami menggunakan AMI Bottlerocket, yang hanya mencakup komponen penting yang diperlukan untuk menjalankan kontainer dan menawarkan waktu boot minimal untuk penskalaan cepat. Memilih node AMI bersifat spesifik untuk aplikasi dan bergantung pada persyaratan penyesuaian, keamanan, dan skalabilitas beban kerja Anda. Meskipun AMI AL2 023 memberikan fleksibilitas yang lebih besar untuk instalasi dan penyesuaian tingkat host (misalnya, menentukan direktori cache khusus PV/PVC tanpa konfigurasi node tambahan), kami sarankan memulai dengan AMI Bottlerocket untuk footprint yang lebih kecil dan pengoptimalan bawaan untuk beban kerja kontainer (misalnya, layanan mikro, server inferensi, dapat APIs diskalakan), kemudian mengevaluasi apakah itu cocok untuk beban kerja Anda melalui kinerja pengujian benchmark.

  • AWS Load Balancer Controller (LBC) — Untuk mengekspos endpoint inferensi real-time, kami menggunakan Load Balancer Controller, yang secara otomatis menyediakan dan mengelola Application AWS Load Balancers () untuk lalu lintas dan Network Load Balancers (ALBs) untuk HTTP/HTTPS lalu TCP/UDP lintas berdasarkan sumber daya Ingress dan Service Kubernetes, memungkinkan integrasi model inferensi dengan klien eksternal. NLBs Selain itu, ia mendukung fitur seperti routing berbasis jalur untuk mendistribusikan permintaan inferensi di beberapa pod atau node, memastikan skalabilitas selama lonjakan lalu lintas dan meminimalkan latensi melalui optimasi AWS-native seperti multiplexing koneksi dan pemeriksaan kesehatan.

1. Buat kluster EKS Anda

Pada langkah ini, kita membuat cluster dengan node CPU dan grup node terkelola menggunakan template AWS CloudFormation ClusterConfigeksctl -powered. Menginisialisasi cluster dengan hanya node CPU memungkinkan kita untuk menggunakan Karpenter secara eksklusif untuk mengelola CPU-intensif dan node GPU untuk alokasi sumber daya yang dioptimalkan menggunakan NodePools Karpenter yang kita buat di langkah selanjutnya. Untuk mendukung beban kerja inferensi real-time kami, kami menyediakan klaster dengan EKS Bottlerocket AMI, Agen Pemantau Node EKS, Agen Identitas Pod EKS, Driver Mountpoint S3 CSI, AWS Load Balancer Controller (LBC), dan driver kube-proxy, vpc-cni, dan coredns. Instans m7g.xlarge akan digunakan untuk tugas-tugas sistem CPU, termasuk hosting kontroler Karpenter, add-on, dan komponen sistem lainnya.

Secara default, eksctl akan membuat VPC khusus untuk cluster dengan blok CIDR. 192.168.0.0/16 VPC mencakup tiga subnet publik dan tiga subnet pribadi, masing-masing didistribusikan di tiga Availability Zone yang berbeda (atau dua AZs di us-east-1 wilayah tersebut) yang merupakan metode ideal untuk menerapkan beban kerja Kubernetes. Template ini juga menyebarkan gateway internet, menyediakan akses internet ke subnet publik melalui rute default di tabel rute mereka dan gateway NAT tunggal di salah satu subnet publik, dengan rute default di tabel rute subnet pribadi mengarahkan lalu lintas keluar melalui gateway NAT untuk akses internet. Untuk mempelajari lebih lanjut tentang pengaturan ini, lihat Menerapkan Node ke Subnet Pribadi.

Periksa kredensyal Anda

Periksa apakah AWS kredensi CLI Anda valid dan dapat mengautentikasi dengan layanan: AWS

aws sts get-caller-identity

Jika berhasil, CLI akan mengembalikan detail tentang AWS identitas Anda (UserId, Akun, dan Arn).

Periksa ketersediaan instans

Jenis instans G5 tidak tersedia di semua wilayah. Periksa wilayah terdekat Anda. Misalnya:

aws ec2 describe-instance-types --instance-types g5.xlarge g5.2xlarge --region us-east-1

Jika berhasil, jenis instans G5 tersedia di wilayah yang Anda tentukan.

The Bottlerocket AMI tidak tersedia di semua wilayah. Periksa dengan mengambil ID AMI Bottlerocket untuk wilayah terdekat Anda. Misalnya:

aws ssm get-parameter --name /aws/service/bottlerocket/aws-k8s-1.33/arm64/latest/image_id \ --region us-east-1 --query "Parameter.Value" --output text

Jika berhasil, AMI Bottlerocket tersedia di wilayah yang Anda tentukan.

Persiapkan lingkungan Anda

Pertama, atur variabel lingkungan berikut di jendela terminal baru. Catatan: Pastikan untuk mengganti placeholder sampel dengan nilai unik Anda, termasuk nama cluster, wilayah yang Anda inginkan, versi rilis Karpenter, dan versi Kubernetes.

Tip

Beberapa variabel (seperti ${AWS_REGION} dan${K8S_VERSION}) didefinisikan di awal blok dan kemudian direferensikan dalam perintah selanjutnya untuk konsistensi dan untuk menghindari pengulangan. Pastikan untuk menjalankan perintah secara berurutan sehingga nilai-nilai ini diekspor dengan benar dan tersedia untuk digunakan dalam definisi berikutnya.

export TEMPOUT="$(mktemp)" export K8S_VERSION=1.33 export KARPENTER_VERSION="1.5.0" export AWS_REGION="us-east-1" export EKS_CLUSTER_NAME="eks-rt-inference-${AWS_REGION}" export S3_BUCKET_NAME="eks-rt-inference-models-${AWS_REGION}-$(date +%s)" export NVIDIA_BOTTLEROCKET_AMI="$(aws ssm get-parameter --name /aws/service/bottlerocket/aws-k8s-${K8S_VERSION}-nvidia/x86_64/latest/image_id --query Parameter.Value --output text)" export STANDARD_BOTTLEROCKET_AMI="$(aws ssm get-parameter --name /aws/service/bottlerocket/aws-k8s-${K8S_VERSION}/arm64/latest/image_id --query Parameter.Value --output text)" export AWS_ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)" export ALIAS_VERSION="$(aws ssm get-parameter --name "/aws/service/eks/optimized-ami/${K8S_VERSION}/amazon-linux-2023/x86_64/standard/recommended/image_id" --query Parameter.Value | xargs aws ec2 describe-images --query 'Images[0].Name' --image-ids | sed -r 's/^.*(v[[:digit:]]+).*$/\1/')"

Buat peran dan kebijakan yang diperlukan

Karpenter membutuhkan peran dan kebijakan IAM tertentu (misalnya, peran IAM controller Karpenter, profil instance, dan kebijakan) untuk mengelola EC2 instance sebagai node pekerja Kubernetes. Ini menggunakan peran ini untuk melakukan tindakan seperti meluncurkan dan menghentikan EC2 instance, menandai sumber daya, dan berinteraksi dengan layanan lain. AWS Buat peran dan kebijakan Karpenter menggunakan cloudformation.yaml Karpenter:

curl -fsSL https://raw.githubusercontent.com/aws/karpenter-provider-aws/v${KARPENTER_VERSION}/website/content/en/preview/getting-started/getting-started-with-karpenter/cloudformation.yaml > "${TEMPOUT}" \ && aws cloudformation deploy \ --stack-name "Karpenter-${EKS_CLUSTER_NAME}" \ --template-file "${TEMPOUT}" \ --capabilities CAPABILITY_NAMED_IAM \ --parameter-overrides "ClusterName=${EKS_CLUSTER_NAME}"

AWS LBC memerlukan izin untuk menyediakan dan mengelola penyeimbang AWS beban, seperti membuat sumber daya Ingress atau ALBs NLBs untuk jenis layanan. LoadBalancer Kami akan menentukan kebijakan izin ini selama pembuatan klaster. Selama pembuatan cluster, kami akan membuat akun layanan dengan eksctl di. ClusterConfig Buat kebijakan IAM LBC:

aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document "$(curl -fsSL https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.13.0/docs/install/iam_policy.json)"

Ketika Driver Mountpoint S3 CSI diinstal, DaemonSet podnya dikonfigurasi untuk menggunakan akun layanan untuk dieksekusi. Driver Mountpoint untuk Mountpoint S3 CSI memerlukan izin untuk berinteraksi dengan bucket Amazon S3 yang Anda buat nanti dalam panduan ini. Kami akan menentukan kebijakan izin ini selama pembuatan klaster. Selama pembuatan cluster, kami akan membuat akun layanan dengan eksctl di. ClusterConfig Buat kebijakan IAM S3:

aws iam create-policy \ --policy-name S3CSIDriverPolicy \ --policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Action\": [\"s3:GetObject\", \"s3:PutObject\", \"s3:AbortMultipartUpload\", \"s3:DeleteObject\", \"s3:ListBucket\"], \"Resource\": [\"arn:aws:s3:::${S3_BUCKET_NAME}\", \"arn:aws:s3:::${S3_BUCKET_NAME}/*\"]}]}"

Catatan: jika peran sudah ada dengan nama ini, beri peran nama yang berbeda. Peran yang kami buat dalam langkah ini khusus untuk cluster dan bucket S3 Anda.

Buat cluster

Dalam template ini, eksctl secara otomatis membuat akun layanan Kubernetes untuk EKS Pod Identity, Node Monitoring Agent, CoreDNS, Kubeproxy, Plugin VPC CNI. Sampai hari ini, Driver Mountpoint S3 CSI tidak tersedia untuk EKS Pod Identity, jadi kami membuat IAM Roles for Service Account (IRSA) dan endpoint OIDC. Selain itu, kami membuat akun layanan untuk AWS Load Balancer Controller (LBC). Untuk akses ke node Bottlerocket, eksctl secara otomatis melampirkan SSMManaged InstanceCore Amazon untuk Bottlerocket untuk memungkinkan sesi shell aman melalui SSM.

Di terminal yang sama tempat Anda mengatur variabel lingkungan, jalankan blok perintah berikut untuk membuat cluster:

eksctl create cluster -f - <<EOF --- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ${EKS_CLUSTER_NAME} region: ${AWS_REGION} version: "${K8S_VERSION}" tags: karpenter.sh/discovery: ${EKS_CLUSTER_NAME} # Add more tags if needed for billing iam: # Creates an OIDC endpoint and IRSA service account for the Mountpoint S3 CSI Driver # Uses the S3 CSI Driver policy for permissions withOIDC: true podIdentityAssociations: # Creates the pod identity association and service account # Uses the Karpenter controller IAM policy for permissions - namespace: "kube-system" serviceAccountName: karpenter roleName: ${EKS_CLUSTER_NAME}-karpenter permissionPolicyARNs: - arn:aws:iam::${AWS_ACCOUNT_ID}:policy/KarpenterControllerPolicy-${EKS_CLUSTER_NAME} # Creates the pod identity association and service account # Uses the AWS LBC policy for permissions - namespace: kube-system serviceAccountName: aws-load-balancer-controller createServiceAccount: true roleName: AmazonEKSLoadBalancerControllerRole permissionPolicyARNs: - arn:aws:iam::${AWS_ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy iamIdentityMappings: - arn: "arn:aws:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${EKS_CLUSTER_NAME}" username: system:node:{{EC2PrivateDNSName}} groups: - system:bootstrappers - system:nodes managedNodeGroups: # Creates 2 CPU nodes for lightweight system tasks - name: ${EKS_CLUSTER_NAME}-m7-cpu instanceType: m7g.xlarge amiFamily: Bottlerocket desiredCapacity: 2 minSize: 1 maxSize: 10 labels: role: cpu-worker # Enable automatic Pod Identity associations for VPC CNI Driver, coreDNS, kube-proxy addonsConfig: autoApplyPodIdentityAssociations: true addons: # Installs the S3 CSI Driver addon and creates IAM role # Uses the S3 CSI Driver policy for IRSA permissions - name: aws-mountpoint-s3-csi-driver attachPolicyARNs: - "arn:aws:iam::${AWS_ACCOUNT_ID}:policy/S3CSIDriverPolicy" - name: eks-pod-identity-agent - name: eks-node-monitoring-agent - name: coredns - name: kube-proxy - name: vpc-cni EOF

Proses ini membutuhkan waktu beberapa menit untuk menyelesaikannya. Jika Anda ingin memantau status, lihat AWS CloudFormationkonsol.

2. Verifikasi Kesehatan Node dan Pod Cluster

Mari kita lakukan beberapa pemeriksaan kesehatan untuk memastikan cluster siap. Ketika perintah sebelumnya selesai, lihat jenis instance dan verifikasi bahwa node sistem CPU Anda telah mencapai Ready status dengan perintah berikut:

kubectl get nodes -L node.kubernetes.io/instance-type

Output yang diharapkan akan terlihat seperti ini:

NAME                             STATUS   ROLES    AGE     VERSION               INSTANCE-TYPE
ip-192-168-35-103.ec2.internal   Ready    <none>   12m     v1.33.0-eks-802817d   m7g.xlarge
ip-192-168-7-15.ec2.internal     Ready    <none>   12m     v1.33.0-eks-802817d   m7g.xlarge

Verifikasi semua asosiasi Identitas Pod dan bagaimana mereka memetakan peran ke akun layanan di namespace di klaster dengan perintah berikut:

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

Output harus menunjukkan peran IAM untuk Karpenter (“karpenter”) dan AWS LBC (” “). aws-load-balancer-controller

Verifikasi DaemonSets yang tersedia:

kubectl get daemonsets -n kube-system

Output yang diharapkan akan terlihat seperti ini:

NAME                           DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR          AGE
aws-node                       3       3       3     3          3         <none>                 12m
dcgm-server                    0       0       0     0          0         kubernetes.io/os=linux 12m
eks-node-monitoring-agent      3       3       3     3          3         kubernetes.io/os=linux 12m
eks-pod-identity-agent         3       3       3     3          3         <none>                 12m
kube-proxy                     3       3       3     3          3         <none>                 12m
s3-csi-node                    2       2       2     2          2         kubernetes.io/os=linux 12m

Verifikasi semua addons diinstal pada cluster:

eksctl get addons --cluster ${EKS_CLUSTER_NAME} --region ${AWS_REGION}

Output yang diharapkan akan terlihat seperti ini:

NAME                           VERSION              STATUS    ISSUES    IAMROLE                                           UPDATE AVAILABLE    CONFIGURATION VALUES    POD IDENTITY ASSOCIATION ROLES
aws-mountpoint-s3-csi-driver   v1.15.0-eksbuild.1   ACTIVE    0    arn:aws:iam::143095308808:role/eksctl-eks-rt-inference-us-east-1-addon-aws-m-Role1-RAUjk4sJnc0L
coredns                        v1.12.1-eksbuild.2   ACTIVE    0
eks-node-monitoring-agent      v1.3.0-eksbuild.2    ACTIVE    0
eks-pod-identity-agent         v1.3.7-eksbuild.2    ACTIVE    0
kube-proxy                     v1.33.0-eksbuild.2   ACTIVE    0
metrics-server                 v0.7.2-eksbuild.3    ACTIVE    0
vpc-cni                        v1.19.5-eksbuild.1   ACTIVE    0

3. Instal Karpenter

Instal pengontrol Karpenter pada node pekerja CPU Anda (cpu-worker) untuk mengoptimalkan biaya dan menghemat sumber daya GPU. Kami akan menginstalnya di namespace “kube-system” dan menentukan akun layanan “karpenter” yang kami tentukan selama pembuatan cluster. Selain itu, perintah ini mengonfigurasi nama cluster dan antrian interupsi Instance Spot untuk node CPU. Karpenter akan menggunakan IRSA untuk mengambil peran IAM ini.

# Logout of helm registry before pulling from public ECR helm registry logout public.ecr.aws # Install Karpenter helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter --version "${KARPENTER_VERSION}" --namespace "kube-system" --create-namespace \ --set "settings.clusterName=${EKS_CLUSTER_NAME}" \ --set "settings.interruptionQueue=${EKS_CLUSTER_NAME}" \ --set controller.resources.requests.cpu=1 \ --set controller.resources.requests.memory=1Gi \ --set controller.resources.limits.cpu=1 \ --set controller.resources.limits.memory=1Gi \ --set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"="arn:aws:iam::${AWS_ACCOUNT_ID}:role/${EKS_CLUSTER_NAME}-karpenter" \ --wait

Output yang diharapkan akan terlihat seperti ini:

Release "karpenter" does not exist. Installing it now.
Pulled: public.ecr.aws/karpenter/karpenter:1.5.0
Digest: sha256:9a155c7831fbff070669e58500f68d7ccdcf3f7c808dcb4c21d3885aa20c0a1c
NAME: karpenter
LAST DEPLOYED: Thu Jun 19 09:57:06 2025
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None

Verifikasi bahwa Karpenter sedang berjalan:

kubectl get pods -n kube-system -l app.kubernetes.io/name=karpenter

Output yang diharapkan akan terlihat seperti ini:

NAME                       READY   STATUS    RESTARTS   AGE
karpenter-555895dc-865bc   1/1     Running   0          5m58s
karpenter-555895dc-j7tk9   1/1     Running   0          5m58s

4. Pengaturan Karpenter NodePools

Pada langkah ini, kami mengkonfigurasi CPU dan GPU Karpenter yang saling eksklusif. NodePools limitsBidang dalam NodePool spesifikasi membatasi total sumber daya maksimum (misalnya, CPU, memori, GPUs) yang NodePool dapat dikonsumsi masing-masing di semua node yang disediakan, mencegah penyediaan node tambahan jika batas ini terlampaui. Sementara NodePools mendukung kategori instans luas (misalnya,c,g), menentukan jenis instans tertentu, jenis kapasitas, dan batasan sumber daya membantu Anda memperkirakan biaya untuk beban kerja sesuai permintaan dengan lebih mudah. Dalam hal ini NodePools, kami menggunakan beragam jenis instance dalam keluarga instance G5. Hal ini memungkinkan Karpenter untuk secara otomatis memilih jenis instans yang paling tepat berdasarkan permintaan sumber daya pod, mengoptimalkan pemanfaatan sumber daya sambil menghormati batas total. NodePool Untuk mempelajari lebih lanjut, lihat Membuat NodePools.

Siapkan GPU NodePool

Dalam hal ini NodePool, kami menetapkan batas sumber daya untuk mengelola penyediaan node dengan kemampuan GPU. Batas ini dirancang untuk membatasi total sumber daya di semua node di pool, memungkinkan hingga 10 instance secara total. Setiap instance dapat berupa g5.xlarge (4 v, memori CPUs 16 GiB, 1 GPU) atau g5.2xlarge (8 vCPUs, memori 32 GiB, 1 GPU), selama total CPUs v tidak melebihi 80, total memori tidak melebihi 320GiB, dan total tidak melebihi 10. GPUs Misalnya, kumpulan dapat menyediakan 10 instans g5.2xlarge (80 v, CPUs 320 GiB, 10), atau 10 instans g5.xlarge (40 v, 160 GiB, 10 GPUs)CPUs, atau campuran seperti 5 g5.xlarge dan 5 g5.2xlarge (60 v, 240 GiB, GPUs 10), memastikan fleksibilitas berdasarkan tuntutan beban kerja sambil menghormati kendala sumber daya. CPUs GPUs

Selain itu, kami menentukan ID varian Nvidia dari AMI Bottlerocket. Akhirnya, kami menetapkan kebijakan gangguan untuk menghapus node kosong setelah 30 menit (consolidateAfter: 30m) dan menetapkan masa pakai node maksimum 30 hari (expireAfter: 720h) untuk mengoptimalkan biaya dan menjaga kesehatan node untuk tugas-tugas intensif GPU. Untuk mempelajari lebih lanjut, lihat Menonaktifkan Konsolidasi Karpenter untuk beban kerja sensitif interupsi, dan Gunakan Pekerjaan Kubernetes yang ttlSecondsAfter Selesai untuk Membersihkan Otomatis.

cat <<EOF | envsubst | kubectl apply -f - apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-a10g-inference-g5 spec: template: metadata: labels: role: gpu-worker gpu-type: nvidia-a10g spec: requirements: - key: node.kubernetes.io/instance-type operator: In values: ["g5.xlarge", "g5.2xlarge"] - key: "karpenter.sh/capacity-type" operator: In values: ["on-demand"] taints: - key: nvidia.com/gpu value: "true" effect: NoSchedule nodeClassRef: name: gpu-a10g-inference-ec2 group: karpenter.k8s.aws kind: EC2NodeClass expireAfter: 720h limits: cpu: "80" memory: "320Gi" nvidia.com/gpu: "10" disruption: consolidationPolicy: WhenEmpty consolidateAfter: 30m --- apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass metadata: name: gpu-a10g-inference-ec2 spec: amiFamily: Bottlerocket amiSelectorTerms: - id: ${NVIDIA_BOTTLEROCKET_AMI} role: "KarpenterNodeRole-${EKS_CLUSTER_NAME}" subnetSelectorTerms: - tags: karpenter.sh/discovery: "${EKS_CLUSTER_NAME}" securityGroupSelectorTerms: - tags: karpenter.sh/discovery: "${EKS_CLUSTER_NAME}" tags: nvidia.com/gpu: "true" EOF

Output yang diharapkan akan terlihat seperti ini:

nodepool.karpenter.sh/gpu-a10g-inference-g5 created
ec2nodeclass.karpenter.k8s.aws/gpu-a10g-inference-ec2 created

Verifikasi NodePool dibuat dan sehat:

kubectl get nodepool gpu-a10g-inference-g5 -o yaml

Carilah status.conditions sukaValidationSucceeded: True,NodeClassReady: True, dan Ready: True untuk memastikan bahwa NodePool itu sehat.

Siapkan CPU NodePool

Dalam hal ini NodePool, kami menetapkan batas untuk mendukung sekitar 50 instance, menyelaraskan dengan beban kerja CPU moderat (misalnya, 100-200 pod) dan kuota AWS vCPU tipikal (misalnya, 128-1152). Batas dihitung dengan asumsi skala NodePool harus hingga 50 m7.xlarge instance: CPU (4 v CPUs per instance × 50 instance = 200 v) CPUs dan memori (16 GiB per instance × 50 instance = 800 GiB). Batas ini dirancang untuk membatasi total sumber daya di semua node di kolam, memungkinkan hingga 50 m7g.xlarge instance (masing-masing dengan memori 4 v dan CPUs 16 GiB), selama total v tidak melebihi 200 dan total memori CPUs tidak melebihi 800GiB.

Selain itu, kami menentukan ID varian standar AMI Bottlerocket. Akhirnya, kami menetapkan kebijakan gangguan untuk menghapus node kosong setelah 60 menit (consolidateAfter: 60m) dan menetapkan masa pakai node maksimum 30 hari (expireAfter: 720h) untuk mengoptimalkan biaya dan menjaga kesehatan node untuk tugas-tugas intensif GPU. Untuk mempelajari lebih lanjut, lihat Menonaktifkan Konsolidasi Karpenter untuk beban kerja sensitif interupsi, dan Gunakan Pekerjaan Kubernetes yang ttlSecondsAfter Selesai untuk Membersihkan Otomatis.

cat <<EOF | envsubst | kubectl apply -f - apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: cpu-inference-m7gxlarge spec: template: metadata: labels: role: cpu-worker spec: requirements: - key: node.kubernetes.io/instance-type operator: In values: ["m7g.xlarge"] - key: karpenter.sh/capacity-type operator: In values: ["on-demand"] taints: - key: role value: cpu-intensive effect: NoSchedule nodeClassRef: name: cpu-inference-m7gxlarge-ec2 group: karpenter.k8s.aws kind: EC2NodeClass expireAfter: 720h limits: cpu: "200" memory: "800Gi" disruption: consolidationPolicy: WhenEmpty consolidateAfter: 60m --- apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass metadata: name: cpu-inference-m7gxlarge-ec2 spec: amiFamily: Bottlerocket amiSelectorTerms: - id: ${STANDARD_BOTTLEROCKET_AMI} role: "KarpenterNodeRole-${EKS_CLUSTER_NAME}" subnetSelectorTerms: - tags: karpenter.sh/discovery: "${EKS_CLUSTER_NAME}" securityGroupSelectorTerms: - tags: karpenter.sh/discovery: "${EKS_CLUSTER_NAME}" EOF

Output yang diharapkan akan terlihat seperti ini:

nodepool.karpenter.sh/cpu-inference-m7gxlarge created
ec2nodeclass.karpenter.k8s.aws/cpu-inference-m7gxlarge-ec2 created

Verifikasi NodePool dibuat dan sehat:

kubectl get nodepool cpu-inference-m7gxlarge -o yaml

Carilah status.conditions sukaValidationSucceeded: True,NodeClassReady: True, dan Ready: True untuk memastikan bahwa NodePool itu sehat.

5. Menerapkan Pod GPU untuk Mengekspos GPU

Anda memerlukan Plugin Perangkat Nvidia untuk mengaktifkan Kubernetes mengekspos perangkat GPU ke cluster Kubernetes. Biasanya, Anda perlu menerapkan plugin sebagai DaemonSet; Namun, AMI Bottlerocket melakukan pra-instal plugin sebagai bagian dari AMI. Itu berarti saat menggunakan Bottlerocket AMIs, tidak perlu menggunakan plugin perangkat Nvidia. DaemonSet Untuk mempelajari lebih lanjut, lihat Plugin Perangkat Kubernetes untuk mengekspos. GPUs

Menerapkan pod sampel

Karpenter bertindak secara dinamis: ia menyediakan node GPU ketika beban kerja (pod) meminta sumber daya GPU. Untuk memverifikasi bahwa pod dapat meminta dan menggunakan GPUs, gunakan pod yang meminta nvidia.com/gpu sumber daya dalam batasnya (misalnya,nvidia.com/gpu: 1). Untuk mempelajari lebih lanjut tentang label ini, lihat Menjadwalkan beban kerja dengan persyaratan GPU menggunakan label Terkenal.

cat <<EOF | envsubst | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: gpu-nvidia-smi spec: restartPolicy: OnFailure tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" nodeSelector: role: gpu-worker # Matches GPU NodePool's label containers: - name: cuda-container image: nvidia/cuda:12.9.1-base-ubuntu20.04 command: ["nvidia-smi"] resources: limits: nvidia.com/gpu: 1 requests: nvidia.com/gpu: 1 EOF

Output yang diharapkan akan terlihat seperti ini:

pod/gpu-ndivia-smi created

Beri waktu sebentar kemudian periksa apakah Pod memiliki status “Pending”, “ContainerCreating,” “Running,” lalu status “Completed”:

kubectl get pod gpu-nvidia-smi -w

Verifikasi node untuk pod milik GPU NodePool:

kubectl get node $(kubectl get pod gpu-nvidia-smi -o jsonpath='{.spec.nodeName}') -o custom-columns="Name:.metadata.name,Nodepool:.metadata.labels.karpenter\.sh/nodepool"

Output yang diharapkan akan terlihat seperti ini:

Name                             Nodepool
ip-192-168-83-245.ec2.internal   gpu-a10g-inference-g5

Periksa log pod:

kubectl logs gpu-nvidia-smi

Output yang diharapkan akan terlihat seperti ini:

Thu Jul 17 04:31:33 2025 +---------------------------------------------------------------------------------------+ | NVIDIA-SMI 570.148.08 Driver Version: 570.148.08 CUDA Version: 12.9 | |-----------------------------------------+----------------------+----------------------+ | 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 A10G On | 00000000:00:1E.0 Off | 0 | | 0% 30C P8 9W / 300W | 0MiB / 23028MiB | 0% Default | | | | N/A | +---------------------------------------------------------------------------------------+ +---------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=======================================================================================| | No running processes found | +---------------------------------------------------------------------------------------+

6. (Opsional) Siapkan dan Unggah Artefak Model untuk Penerapan

Pada langkah ini, Anda akan menerapkan layanan model untuk klasifikasi gambar real-time, dimulai dengan mengunggah bobot model ke bucket Amazon S3. Untuk demonstrasi, kami menggunakan bagian model visi open-source GPUNet-0 dari NVIDIA GPUNet, yang mendukung inferensi latensi rendah pada gambar menggunakan NVIDIA dan TensorRT. GPUs Model ini sudah dilatih sebelumnya ImageNet, memungkinkan kita untuk mengklasifikasikan objek dalam foto atau aliran video dengan cepat, dan dianggap sebagai model kecil dengan 11, 9 juta parameter.

Siapkan lingkungan Anda

Untuk mengunduh bobot model GPUNet -0 Pada langkah ini, Anda memerlukan akses ke katalog NGC NVIDIA dan Docker yang diinstal pada mesin lokal Anda. Ikuti langkah-langkah ini untuk menyiapkan akun gratis dan mengonfigurasi CLI NGC:

  • Daftar untuk mendapatkan akun NGC gratis dan buat kunci API dari dasbor NGC (Ikon Pengguna> Pengaturan > Hasilkan Kunci API> Hasilkan Kunci Pribadi > Katalog NGC).

  • Unduh dan instal NGC CLI Linux/macOS/Windows () dan konfigurasikan CLI menggunakan:. ngc config set Masukkan kunci API Anda saat diminta; atur org ke nvidia dan tekan Enter untuk menerima default untuk orang lain. Jika berhasil, Anda akan melihat sesuatu seperti:Successfully saved NGC configuration to /Users/your-username/.ngc/config.

Verifikasi izin akun layanan

Sebelum kita mulai, periksa izin akun layanan Kubernetes:

kubectl get serviceaccount s3-csi-driver-sa -n kube-system -o yaml

Selama pembuatan klaster, kami melampirkan CSIDriver Kebijakan S3 ke peran IAM dan membuat anotasi akun layanan (“s3- “). csi-driver-sa Pod driver Mountpoint S3 CSI mewarisi izin peran IAM saat berinteraksi dengan S3. Output yang diharapkan akan terlihat seperti ini:

apiVersion: v1 kind: ServiceAccount metadata: annotations: eks.amazonaws.com/role-arn: arn:aws:iam::143095308808:role/eksctl-eks-rt-inference-us-east-1-addon-aws-m-Role1-fpXXjRYdKN8r creationTimestamp: "2025-07-17T03:55:29Z" labels: app.kubernetes.io/component: csi-driver app.kubernetes.io/instance: aws-mountpoint-s3-csi-driver app.kubernetes.io/managed-by: EKS app.kubernetes.io/name: aws-mountpoint-s3-csi-driver name: s3-csi-driver-sa namespace: kube-system resourceVersion: "2278" uid: 50b36272-6716-4c68-bdc3-c4054df1177c

Tambahkan toleransi

Driver S3 CSI berjalan sebagai DaemonSet pada semua node. Pod menggunakan driver CSI pada node tersebut untuk memasang volume S3. Untuk memungkinkannya menjadwalkan pada node GPU kami yang memiliki noda, tambahkan toleransi ke: DaemonSet

kubectl patch daemonset s3-csi-node -n kube-system --type='json' -p='[{"op": "add", "path": "/spec/template/spec/tolerations/-", "value": {"key": "nvidia.com/gpu", "operator": "Exists", "effect": "NoSchedule"}}]'

Output yang diharapkan akan terlihat seperti ini:

daemonset.apps/s3-csi-node patched

Unggah bobot model ke S3

Pada langkah ini, Anda akan membuat bucket Amazon S3, mengunduh bobot model GPUNet -0 dari NVIDIA GPU Cloud (NGC), dan mengunggahnya ke bucket. Bobot ini akan diakses oleh aplikasi kami saat runtime untuk inferensi.

Buat bucket Amazon S3 Anda:

aws s3 mb s3://${S3_BUCKET_NAME} --region ${AWS_REGION}

Aktifkan Pembuatan Versi S3 untuk bucket, untuk mencegah penghapusan dan penimpaan yang tidak disengaja menyebabkan kehilangan data langsung dan permanen:

aws s3api put-bucket-versioning --bucket ${S3_BUCKET_NAME} --versioning-configuration Status=Enabled

Terapkan aturan siklus hidup ke bucket untuk menghapus versi objek yang ditimpa atau dihapus 14 hari setelah tidak berlaku, hapus penanda hapus kedaluwarsa, dan hapus unggahan multi-bagian yang tidak lengkap setelah 7 hari. Untuk mempelajari lebih lanjut, lihat Contoh konfigurasi Siklus Hidup S3.

aws s3api put-bucket-lifecycle-configuration --bucket $S3_BUCKET_NAME --lifecycle-configuration '{"Rules":[{"ID":"LifecycleRule","Status":"Enabled","Filter":{},"Expiration":{"ExpiredObjectDeleteMarker":true},"NoncurrentVersionExpiration":{"NoncurrentDays":14},"AbortIncompleteMultipartUpload":{"DaysAfterInitiation":7}}]}'

Unduh bobot model GPUNet -0 dari NGC. Misalnya, di macOS:

ngc registry model download-version nvidia/dle/gpunet_0_pyt_ckpt:21.12.0_amp --dest ~/downloads
catatan

Anda mungkin perlu menyesuaikan perintah unduhan ini untuk sistem operasi Anda. Agar perintah ini bekerja pada sistem Linux, Anda mungkin perlu membuat direktori sebagai bagian dari perintah (misalnya,mkdir ~/downloads).

Output yang diharapkan akan terlihat seperti ini:

{ "download_end": "2025-07-18 08:22:39", "download_start": "2025-07-18 08:22:33", "download_time": "6s", "files_downloaded": 1, "local_path": "/Users/your-username/downloads/gpunet_0_pyt_ckpt_v21.12.0_amp", "size_downloaded": "181.85 MB", "status": "Completed", "transfer_id": "gpunet_0_pyt_ckpt[version=21.12.0_amp]" }

Ganti nama file pos pemeriksaan agar sesuai dengan penamaan yang diharapkan dalam kode aplikasi kami di langkah selanjutnya (tidak diperlukan ekstraksi, karena ini adalah pos pemeriksaan standar PyTorch *.pth.tar yang berisi kamus status model):

mv ~/downloads/gpunet_0_pyt_ckpt_v21.12.0_amp/0.65ms.pth.tar gpunet-0.pth

Aktifkan Runtime AWS Umum di AWS CLI untuk mengoptimalkan throughput S3:

aws configure set s3.preferred_transfer_client crt

Unggah bobot model ke bucket S3 Anda:

aws s3 cp gpunet-0.pth s3://${S3_BUCKET_NAME}/gpunet-0.pth

Output yang diharapkan akan terlihat seperti ini:

upload: ./gpunet-0.pth to s3://eks-rt-inference-models-us-east-1-1752722786/gpunet-0.pth

Buat Layanan Model

Pada langkah ini, Anda akan menyiapkan aplikasi web FasTapi untuk klasifikasi gambar yang dipercepat GPU menggunakan model visi GPUNet -0. Aplikasi mengunduh bobot model dari Amazon S3 saat runtime, mengambil arsitektur model dari repositori NVIDIA untuk caching, dan mengunduh label kelas melalui HTTP. ImageNet Aplikasi ini mencakup transformasi prapemrosesan gambar dan mengekspos dua titik akhir: GET root untuk pemeriksaan status dan /predict titik akhir POST yang menerima URL gambar.

Kami melayani model menggunakan FastAP dengan PyTorch, memuat bobot dari Amazon S3 saat runtime dalam pengaturan kontainer untuk pembuatan prototipe cepat dan penerapan Kubernetes. Untuk metode lain seperti batching yang dioptimalkan atau engine throughput tinggi, lihat Melayani Model ML.

Buat aplikasi

Buat direktori untuk file aplikasi Anda sepertimodel-testing, lalu ubah direktori ke dalamnya dan tambahkan kode berikut ke file baru bernamaapp.py:

import os import torch import json import requests from fastapi import FastAPI, HTTPException from PIL import Image from io import BytesIO, StringIO import torchvision.transforms as transforms from torch.nn.functional import softmax import warnings from contextlib import redirect_stdout, redirect_stderr import argparse import boto3 app = FastAPI() # Suppress specific warnings from the model code (quantization is optional and unused here) warnings.simplefilter("ignore", UserWarning) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") # Load model code from cache (if present) # Use backed cache directory torch.hub.set_dir('/cache/torch/hub') # Allowlist for secure deserialization (handles potential issues in older checkpoints) torch.serialization.add_safe_globals([argparse.Namespace]) # Load the model architecture only on container startup (changed to pretrained=False) # Precision (FP32 for full accuracy, could be 'fp16' for speed on Ampere+ GPUs) with redirect_stdout(StringIO()), redirect_stderr(StringIO()): gpunet = torch.hub.load('NVIDIA/DeepLearningExamples:torchhub', 'nvidia_gpunet', pretrained=False, model_type='GPUNet-0', model_math='fp32') # Download weights from S3 if not present, then load them model_path = os.getenv('MODEL_PATH', '/cache/torch/hub/checkpoints/gpunet-0.pth') os.makedirs(os.path.dirname(model_path), exist_ok=True) # Ensure checkpoints dir exists if not os.path.exists(model_path): s3 = boto3.client('s3') s3.download_file(os.getenv('S3_BUCKET_NAME'), 'gpunet-0.pth', model_path) checkpoint = torch.load(model_path, map_location=device, weights_only=True) gpunet.load_state_dict(checkpoint['state_dict']) # Move to GPU/CPU gpunet.to(device) gpunet.eval() # Preprocessing preprocess = transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ]) # Load ImageNet labels labels_url = "https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json" response = requests.get(labels_url) json_data = json.loads(response.text) labels = [json_data[str(i)][1].replace('_', ' ') for i in range(1000)] # Required, FastAPI root @app.get("/") async def hello(): return {"status": "hello"} # Serve model requests @app.post("/predict") async def predict(image_url: str): try: response = requests.get(image_url) response.raise_for_status() img = Image.open(BytesIO(response.content)).convert("RGB") input_tensor = preprocess(img).unsqueeze(0).to(device) with torch.no_grad(): output = gpunet(input_tensor) probs = softmax(output, dim=1)[0] top5_idx = probs.topk(5).indices.cpu().numpy() top5_probs = probs.topk(5).values.cpu().numpy() results = [{ "label": labels[idx], "probability": float(prob) } for idx, prob in zip(top5_idx, top5_probs)] return {"predictions": results} except Exception as e: raise HTTPException(status_code=400, detail=str(e))

Buat Dockerfile

Dockerfile berikut membuat gambar kontainer untuk aplikasi kami menggunakan GPUNet model dari NVIDIA Deep Learning Examples for Tensor Cores repositori. GitHub

Kami mengurangi ukuran gambar kontainer dengan menggunakan PyTorch basis runtime saja, menginstal hanya paket penting dengan pembersihan cache, kode model pra-caching, dan menghindari bobot “memanggang” dalam gambar kontainer untuk memungkinkan penarikan dan pembaruan yang lebih cepat. Untuk mempelajari lebih lanjut, lihat Mengurangi Ukuran Gambar Kontainer.

Di direktori yang sama denganapp.py, buatDockerfile:

FROM pytorch/pytorch:2.4.0-cuda12.4-cudnn9-runtime # Install required system packages required for git cloning RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* # Install application dependencies RUN pip install --no-cache-dir fastapi uvicorn requests pillow boto3 timm==0.5.4 # Pre-cache the GPUNet code from Torch Hub (without weights) # Clone the repository containing the GPUNet code RUN mkdir -p /cache/torch/hub && \ cd /cache/torch/hub && \ git clone --branch torchhub --depth 1 https://github.com/NVIDIA/DeepLearningExamples NVIDIA_DeepLearningExamples_torchhub COPY app.py /app/app.py WORKDIR /app CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "80"]

Uji aplikasi

Dari direktori yang sama dengan Anda app.py danDockerfile, buat image kontainer untuk aplikasi inferensi, menargetkan arsitektur AMD64 :

docker build --platform linux/amd64 -t gpunet-inference-app .

Tetapkan variabel lingkungan untuk AWS kredensil Anda, dan secara opsional token sesi. AWS Misalnya:

export AWS_REGION="us-east-1" export AWS_ACCESS_KEY_ID=ABCEXAMPLESCUJFEIELSMUHHAZ export AWS_SECRET_ACCESS_KEY=123EXAMPLEMZREoQXr8XkiicsOgWDQ5TpUsq0/Z

Jalankan kontainer secara lokal, menyuntikkan AWS kredensil sebagai variabel lingkungan untuk akses S3. Misalnya:

docker run --platform linux/amd64 -p 8080:80 \ -e S3_BUCKET_NAME=${S3_BUCKET_NAME} \ -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \ -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \ -e AWS_DEFAULT_REGION=${AWS_REGION} \ gpunet-inference-app

Output yang diharapkan akan terlihat seperti ini:

INFO:     Started server process [1]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)

Di jendela terminal baru, uji titik akhir inferensi dengan mengirimkan contoh permintaan POST dengan URL gambar publik sebagai parameter kueri:

curl -X POST "http://localhost:8080/predict?image_url=http://images.cocodataset.org/test-stuff2017/000000024309.jpg"

Output yang diharapkan harus berupa respons JSON dengan prediksi 5 teratas, mirip dengan ini (label dan probabilitas aktual mungkin sedikit berbeda berdasarkan presisi gambar dan model):

{"predictions":[{"label":"desk","probability":0.28885871171951294},{"label":"laptop","probability":0.24679335951805115},{"label":"notebook","probability":0.08539070934057236},{"label":"library","probability":0.030645888298749924},{"label":"monitor","probability":0.02989606373012066}]}

Keluar dari aplikasi menggunakan “Ctrl+C”.

Dorong wadah ke Amazon ECR

Pada langkah ini, kami mengunggah gambar penampung untuk layanan model GPUNet -0 ke Amazon Elastic Container Registry (ECR), membuatnya tersedia untuk penyebaran di Amazon EKS. Proses ini melibatkan pembuatan repositori ECR baru untuk menyimpan gambar, mengautentikasi dengan ECR, lalu menandai dan mendorong gambar kontainer ke registri kami.

Pertama, navigasikan kembali ke direktori tempat Anda mengatur variabel lingkungan di awal panduan ini. Misalnya:

cd ..

Buat repositori di Amazon ECR:

aws ecr create-repository --repository-name gpunet-inference-app --region ${AWS_REGION}

Masuk ke Amazon ECR:

aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com

Output yang diharapkan akan terlihat seperti ini:

Login Succeeded

Tandai gambar:

docker tag gpunet-inference-app:latest ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/gpunet-inference-app:latest

Dorong gambar ke repositori Amazon ECR Anda:

docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/gpunet-inference-app:latest

Langkah terakhir ini membutuhkan waktu beberapa menit untuk menyelesaikannya.

7. (Opsional) Paparkan Layanan Model

Pada langkah ini, Anda akan mengekspos layanan model inferensi real-time Anda secara eksternal di Amazon EKS menggunakan Load AWS Balancer Controller (LBC). Ini melibatkan pengaturan LBC, memasang bobot model dari Amazon S3 sebagai volume persisten menggunakan Driver CSI Mountpoint S3, menerapkan pod aplikasi yang dipercepat GPU, membuat layanan dan ingress untuk menyediakan Application Load Balancer (ALB), dan menguji titik akhir.

Pertama, verifikasi asosiasi Pod Identity untuk AWS LBC, dengan mengonfirmasi bahwa akun layanan ditautkan dengan benar ke peran IAM yang diperlukan:

eksctl get podidentityassociation --cluster ${EKS_CLUSTER_NAME} --namespace kube-system --service-account-name aws-load-balancer-controller

Output yang diharapkan akan terlihat seperti ini:

ASSOCIATION ARN                                                    NAMESPACE    SERVICE ACCOUNT NAME        IAM ROLE ARN    OWNER ARN
arn:aws:eks:us-east-1:143095308808:podidentityassociation/eks-rt-inference-us-east-1/a-buavluu2wp1jropya    kube-system     aws-load-balancer-controller    arn:aws:iam::143095308808:role/AmazonEKSLoadBalancerControllerRole

Tandai grup keamanan klaster Anda

AWS Load Balancer Controller hanya mendukung satu grup keamanan dengan kunci tag karpenter.sh/discovery: "${EKS_CLUSTER_NAME}" untuk pemilihan grup keamanan Karpenter. Saat membuat cluster dengan eksctl, grup keamanan cluster default (yang memiliki "kubernetes.io/cluster/<cluster-name>: owned" tag) tidak secara otomatis ditandai dengan tag. karpenter.sh/discovery Tag ini penting bagi Karpenter untuk menemukan dan melampirkan grup keamanan ini ke node yang disediakannya. Melampirkan grup keamanan ini memastikan kompatibilitas dengan AWS Load Balancer Controller (LBC), memungkinkannya untuk secara otomatis mengelola aturan lalu lintas masuk untuk layanan yang diekspos melalui Ingress, seperti layanan model dalam langkah-langkah ini.

Ekspor ID VPC untuk klaster Anda:

CLUSTER_VPC_ID="$(aws eks describe-cluster --name ${EKS_CLUSTER_NAME} --query cluster.resourcesVpcConfig.vpcId --output text)"

Ekspor grup keamanan default untuk klaster Anda:

CLUSTER_SG_ID="$(aws ec2 describe-security-groups --filters Name=vpc-id,Values=$CLUSTER_VPC_ID Name=tag-key,Values=kubernetes.io/cluster/${EKS_CLUSTER_NAME} --query 'SecurityGroups[].[GroupId]' --output text)"

Tambahkan karpenter.sh/discovery tag ke grup keamanan klaster default. Ini akan memungkinkan EC2 NodeClass pemilih CPU dan GPU kami untuk menggunakannya:

aws ec2 create-tags --resources ${CLUSTER_SG_ID} --tags Key=karpenter.sh/discovery,Value=${EKS_CLUSTER_NAME}

Verifikasi tag telah ditambahkan:

aws ec2 describe-security-groups --group-ids ${CLUSTER_SG_ID} --query "SecurityGroups[].Tags"

Di antara hasilnya, Anda akan melihat yang berikut dengan tag dan nama cluster Anda. Misalnya:

{ "Key": "karpenter.sh/discovery", "Value": "eks-rt-inference-us-east-1" }

Siapkan AWS Load Balancer Controller (LBC)

AWS LBC sangat penting untuk mengelola lalu lintas masuk ke beban AI/ML kerja di Amazon EKS, memastikan akses ke titik akhir inferensi atau saluran pemrosesan data. Dengan mengintegrasikan dengan AWS Application Load Balancers (ALB) dan Network Load Balancers (NLB), LBC secara dinamis merutekan lalu lintas ke aplikasi kontainer, seperti yang menjalankan model bahasa besar, model visi komputer, atau layanan inferensi real-time. Karena kami telah membuat akun layanan dan Asosiasi Identitas Pod selama pembuatan klaster, kami menetapkan serviceAccount.name untuk mencocokkan apa yang didefinisikan dalam konfigurasi klaster kami (aws-load-balancer-controller).

Tambahkan repositori AWSbagan Helm eks-charts milik:

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

Segarkan repositori Helm lokal Anda dengan bagan terbaru:

helm repo update eks

Terapkan AWS LBC menggunakan Helm, tentukan nama cluster EKS dan referensikan akun layanan yang telah dibuat sebelumnya:

helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ -n kube-system \ --set clusterName=${EKS_CLUSTER_NAME} \ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controller

Output yang diharapkan akan terlihat seperti ini:

NAME: aws-load-balancer-controller
LAST DEPLOYED: Wed Jul 9 15:03:31 2025
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!

Pasang model dalam volume persisten

Pada langkah ini, Anda akan memasang bobot model dari bucket Amazon S3 Anda menggunakan (PV) PersistentVolume yang didukung oleh driver Mountpoint untuk Amazon S3 CSI. Hal ini memungkinkan pod Kubernetes untuk mengakses objek S3 sebagai file lokal, menghilangkan unduhan intensif sumber daya ke penyimpanan pod sementara atau kontainer init—ideal untuk bobot model multi-gigabyte yang besar.

PV memasang seluruh root bucket (tidak ada jalur yang ditentukanvolumeAttributes), mendukung akses hanya-baca bersamaan oleh beberapa pod, dan mengekspos file seperti model weights (/models/gpunet-0.pth) di dalam container untuk inferensi. Ini memastikan fallback “download” di aplikasi kami (app.py) tidak terpicu karena file ada melalui mount. Dengan memisahkan model dari gambar kontainer, ini memungkinkan akses bersama dan pembaruan versi model independen tanpa pembuatan ulang gambar.

Buat PersistentVolume (PV)

Buat sumber daya PersistentVolume (PV) untuk memasang bucket S3 yang berisi bobot model Anda, memungkinkan akses hanya-baca untuk beberapa pod tanpa mengunduh file saat runtime:

cat <<EOF | envsubst | kubectl apply -f - apiVersion: v1 kind: PersistentVolume metadata: name: s3-model-pv spec: capacity: storage: 5Gi # Ignored by the driver; can be any value accessModes: - ReadOnlyMany # Read only persistentVolumeReclaimPolicy: Retain storageClassName: "" # Required for static provisioning claimRef: namespace: default # Adjust if you prefer a different namespace name: s3-model-pvc mountOptions: - allow-other # Enables multi-user access (useful for non-root pods) - region ${AWS_REGION} # Optional, include if your bucket is in a different region than the cluster csi: driver: s3.csi.aws.com volumeHandle: gpunet-model-volume # Must be unique across all PVs volumeAttributes: bucketName: ${S3_BUCKET_NAME} EOF

Buat PersistentVolumeClaim (PVC)

Buat PersistentVolumeClaim (PVC) untuk mengikat ke PV, meminta akses hanya-baca ke data model S3 yang dipasang:

cat <<EOF | envsubst | kubectl apply -f - apiVersion: v1 kind: PersistentVolumeClaim metadata: name: s3-model-pvc spec: accessModes: - ReadOnlyMany storageClassName: "" # Required for static provisioning resources: requests: storage: 5Gi # Ignored, match PV capacity volumeName: s3-model-pv # Bind to the PV created above EOF

Deploy aplikasi

Menerapkan aplikasi inferensi sebagai Deployment Kubernetes, memasang volume persisten yang didukung S3 untuk akses model, menerapkan pemilih dan toleransi node GPU, dan mengatur variabel lingkungan untuk jalur model. Deployment ini menetapkan jalur model (env var of"/models/gpunet-0.pth"), jadi aplikasi kita (inapp.py) akan menggunakan jalur ini secara default. Dengan pemasangan volume Deployment di /models (hanya-baca), unduhan model tidak akan terpicu jika file sudah ada melalui PVC.

cat <<EOF | envsubst | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: gpunet-inference-app spec: replicas: 1 selector: matchLabels: app: gpunet-inference-app template: metadata: labels: app: gpunet-inference-app spec: tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" nodeSelector: role: gpu-worker containers: - name: inference image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/gpunet-inference-app:latest ports: - containerPort: 80 env: - name: MODEL_PATH value: "/models/gpunet-0.pth" resources: limits: nvidia.com/gpu: 1 requests: nvidia.com/gpu: 1 volumeMounts: - name: model-volume mountPath: /models readOnly: true volumes: - name: model-volume persistentVolumeClaim: claimName: s3-model-pvc EOF

Ini akan memakan waktu beberapa menit bagi Karpenter untuk menyediakan node GPU jika belum tersedia. Verifikasi bahwa pod inferensi berada dalam status “Running”:

kubectl get pods -l app=gpunet-inference-app

Output yang diharapkan akan terlihat seperti ini:

NAME                               READY   STATUS    RESTARTS   AGE
gpunet-inference-app-5d4b6c7f8-abcde        1/1     Running   0          2m

Mengekspos Layanan dengan Ingress dan Load Balancer

Buat Layanan ClusterIP untuk mengekspos penyebaran inferensi secara internal dalam kluster EKS, menargetkan port aplikasi:

cat <<EOF | envsubst | kubectl apply -f - apiVersion: v1 kind: Service metadata: name: gpunet-model-service spec: type: ClusterIP ports: - port: 80 targetPort: 80 selector: app: gpunet-inference-app EOF

Buat sumber daya Ingress untuk menyediakan Application Load Balancer (ALB) yang menghadap internet melalui LBC, merutekan lalu AWS lintas eksternal ke layanan inferensi:

cat <<EOF | envsubst | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gpunet-model-ingress annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip spec: ingressClassName: alb rules: - http: paths: - path: / pathType: Prefix backend: service: name: gpunet-model-service port: number: 80 EOF

Berikan beberapa menit agar Application Load Balancer (ALB) menyelesaikan penyediaan. Pantau status sumber daya Ingress untuk mengonfirmasi bahwa ALB telah disediakan:

kubectl get ingress gpunet-model-ingress

Output yang diharapkan akan terlihat seperti ini (dengan bidang ADDRESS terisi):

NAME                   CLASS   HOSTS   ADDRESS                                         PORTS   AGE
gpunet-model-ingress   alb     *       k8s-default-gpunetmo-183de3f819-516310036.us-east-1.elb.amazonaws.com   80      6m58s

Ekstrak dan ekspor nama host ALB dari status Ingress untuk digunakan dalam pengujian berikutnya:

export ALB_HOSTNAME=$(kubectl get ingress gpunet-model-ingress -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')

Uji Layanan Model

Validasi titik akhir inferensi terbuka dengan mengirimkan permintaan POST dengan URL gambar sampel (misalnya, dari kumpulan data COCO), mensimulasikan prediksi waktu nyata:

curl -X POST "http://${ALB_HOSTNAME}/predict?image_url=http://images.cocodataset.org/test-stuff2017/000000024309.jpg"

Output yang diharapkan harus berupa respons JSON dengan prediksi 5 teratas, mirip dengan ini (label dan probabilitas aktual mungkin sedikit berbeda berdasarkan presisi gambar dan model):

{"predictions":[{"label":"desk","probability":0.2888975441455841},{"label":"laptop","probability":0.2464350312948227},{"label":"notebook","probability":0.08554483205080032},{"label":"library","probability":0.030612602829933167},{"label":"monitor","probability":0.029896672815084457}]}

Anda dapat secara opsional melanjutkan pengujian gambar lain dalam permintaan POST baru. Misalnya:

http://images.cocodataset.org/test-stuff2017/000000024309.jpg
http://images.cocodataset.org/test-stuff2017/000000028117.jpg
http://images.cocodataset.org/test-stuff2017/000000006149.jpg
http://images.cocodataset.org/test-stuff2017/000000004954.jpg

Kesimpulan

Dalam panduan ini, Anda menyiapkan klaster Amazon EKS yang dioptimalkan untuk beban kerja inferensi real-time yang dipercepat GPU. Anda menyediakan cluster dengan EC2 instans G5, menginstal Mountpoint S3 CSI Driver, EKS Pod Identity Agent, EKS Node Monitoring Agent, Bottlerocket AMI, Load Balancer Controller (LBC), dan Karpenter untuk mengelola CPU dan AWS GPU. NodePools Anda menggunakan Plugin Perangkat NVIDIA untuk mengaktifkan penjadwalan GPU dan mengkonfigurasi S3 dengan PersistentVolume dan PersistentVolumeClaim untuk akses model. Anda memvalidasi penyiapan dengan menerapkan contoh pod GPU, menyiapkan akses model untuk model NVIDIA GPUNet-0 di Amazon S3, mengaktifkan inisialisasi pod, dan mengekspos layanan inferensi melalui Application Load Balancer. Untuk sepenuhnya memanfaatkan cluster Anda, konfigurasikan Agen Pemantauan Node EKS dengan perbaikan otomatis. Pastikan untuk melakukan tes benchmark, termasuk kinerja GPU, latensi, dan penilaian throughput untuk mengoptimalkan waktu respons. Untuk mempelajari lebih lanjut, lihat Menggunakan Alat Pemantauan dan Pengamatan untuk Beban AI/ML Kerja Anda.

Bersihkan

Untuk menghindari biaya future charge, Anda perlu menghapus CloudFormation tumpukan terkait secara manual untuk menghapus semua sumber daya yang dibuat selama panduan ini, termasuk jaringan VPC.

Hapus CloudFormation tumpukan menggunakan --wait bendera dengan eksctl:

eksctl delete cluster --region ${AWS_REGION} --name ${EKS_CLUSTER_NAME} --wait

Setelah selesai, Anda akan melihat output respons berikut:

2025-07-29 13:03:55 [✔]  all cluster resources were deleted

Hapus bucket Amazon S3 yang dibuat selama panduan ini menggunakan Konsol Amazon S3.