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 ClusterConfig
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
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 CloudFormation
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. NodePoolslimits
Bidang 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
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 gangguanconsolidateAfter: 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 gangguanconsolidateAfter: 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
Siapkan lingkungan Anda
Untuk mengunduh bobot model GPUNet -0 Pada langkah ini, Anda memerlukan akses ke katalog NGC NVIDIA dan Docker
-
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 kenvidia
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
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
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
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