Unterstützung für die Verbesserung dieser Seite beitragen
Um zu diesem Benutzerhandbuch beizutragen, klicken Sie auf den Link Diese Seite auf GitHub bearbeiten, der sich im rechten Bereich jeder Seite befindet.
Leitfaden für bewährte Methoden zur Cluster-Einrichtung für Echtzeit-Inferenz in Amazon EKS
Einführung
Dieser Leitfaden bietet eine praktische Anleitung zum Einrichten eines Amazon Elastic Kubernetes Service (EKS)-Clusters, der für Echtzeit-Online-Inferenz-Workloads optimiert ist und bewährte Verfahren von AWS-Experten enthält. Er verwendet eine bewährte EKS-Schnellstartarchitektur – eine kuratierte Sammlung von Treibern, Instance-Typen und Konfigurationen, die auf bewährte AWS-Methoden für Modelle, Beschleuniger und Skalierung abgestimmt sind. Dieser Ansatz erspart Ihnen die Auswahl der Cluster-Einstellungen, sodass Sie schnell einen funktionsfähigen, vorkonfigurierten Cluster in Betrieb nehmen können. Dabei werden wir Beispiel-Workloads bereitstellen, um Ihre Konfiguration zu validieren, wichtige Architekturkonzepte erläutern (z. B. die Entkopplung von CPU-gebundenen Aufgaben von GPU-intensiven Berechnungen), häufig gestellte Fragen beantworten (z. B. warum Bottlerocket AMI gegenüber AL2023 bevorzugt wird) und die nächsten Schritte zur Erweiterung der Funktionen Ihres Clusters skizzieren.
Dieser Leitfaden wurde speziell für Techniker aus den Bereichen Machine Learning (ML) und Künstliche Intelligenz (KI), Plattform-Administratoren, Betreiber und Daten-/KI-Spezialisten entwickelt, die neu in AWS und im EKS-Ökosystem sind. Er setzt Kenntnisse über Kubernetes, aber keine Erfahrung mit EKS voraus. Es soll Ihnen dabei helfen, die erforderlichen Schritte und Prozesse zu verstehen, um Echtzeit-Online-Inferenz-Workloads zum Laufen zu bringen. Der Leitfaden vermittelt Ihnen die Grundlagen zum Erstellen eines Ein-Knoten- Inferenz-Clusters, einschließlich der Bereitstellung von GPU-Ressourcen, der Integration von Speicher für Modellartefakte, der Aktivierung des sicheren AWS-Service-Zugriffs und der Freigabe von Inferenz-Endpunkten. Dabei wird durchgehend Wert auf ein latenzarme, ausfallsicheres Design für benutzerorientierte Anwendungen wie Betrugserkennung, Echtzeit-Chatbots und Stimmungsanalyse in Kundenfeedback-Systemen gelegt.
In diesem Leitfaden konzentrieren wir uns ausschließlich auf die Einrichtung eines grundlegenden, präskriptiven Ausgangspunkts mithilfe von G5-EC2-Instances. Wenn Sie auf der Suche nach AWS-Inferentia-spezifischen Clusterkonfigurationen oder durchgängigen Workflows sind, besuchen Sie Verwendung von AWS-Inferentia-Instances mit Amazon EKS für Machine Learning oder unsere Workshops in Ressourcen für den Einstieg in KI/ML in Amazon EKS.
Bevor Sie beginnen
Stellen Sie zunächst sicher, dass Sie die folgenden Aufgaben durchgeführt haben:
Architektur
Echtzeit-Online-Inferenz bezeichnet den Prozess, bei dem ein trainiertes Machine-Learning-Modell verwendet wird, um mit minimaler Latenz Prognosen oder Ergebnisse zu eingehenden Datenströmen zu generieren. Dies ermöglicht beispielsweise die Echtzeit-Betrugserkennung, die Klassifizierung von Images oder die Erstellung von Wissensdiagrammen als Reaktion auf Benutzereingaben. Die Architektur eines Echtzeit-Online-Inferenzsystems ermöglicht Machine Learning-Prognosen mit niedriger Latenz in benutzerorientierten Anwendungen, indem sie die CPU-gebundene Verarbeitung des Web-Datenverkehrs von den GPU-intensiven KI-Berechnungen trennt. Dieser Prozess findet in der Regel innerhalb einer größeren Anwendungsumgebung statt und beinhaltet oft Backend-, Frontend-, Vektor- und Modell-Services. Der Fokus liegt dabei auf spezialisierten Komponenten, um eine unabhängige Skalierung, parallele Entwicklung und Ausfallsicherheit zu ermöglichen. Die Isolierung von Inferenzaufgaben auf dedizierter GPU-Hardware und die Nutzung von Benutzeroberflächen wie APIs und WebSockets stellen eine hohe Parallelität, eine schnelle Verarbeitung von Modellen wie Transformatoren und Benutzerinteraktionen über das Frontend sicher. Beachten Sie, dass Vektordatenbanken und Retrieval Augmented Generation (RAG)-Pipelines zwar häufig eine wichtige Rolle in Echtzeit-Inferenzsystemen spielen, diese Komponenten jedoch nicht in diesem Leitfaden behandelt werden. Eine typische Architektur umfasst in der Regel mindestens folgende Komponenten:
-
Frontend-Service: Dient als Benutzeroberfläche, verarbeitet die clientseitige Logik, rendert dynamische Inhalte und ermöglicht Echtzeit-Interaktionen. Er kommuniziert mit dem Backend-Service, um Inferenzanfragen zu initiieren und Ergebnisse anzuzeigen. Häufig initiiert er Anfragen an den Backend-Service, der WebSockets für Streaming-Aktualisierungen oder APIs für die strukturierte Datennutzung verwendet. Dieser Service erfordert in der Regel keinen dedizierten Load Balancer, da er auf Content Delivery Networks (CDNs) wie AWS CloudFront für statische Komponenten gehostet oder direkt von Web-Servern bereitgestellt werden kann. Die Skalierung erfolgt bei Bedarf für dynamische Inhalte über Auto-Scaling-Gruppen.
-
Backend-Service: Agiert als Orchestrator der Anwendung und verwaltet Unternehmenslogik wie Benutzerauthentifizierung, Datenvalidierung und Service-Koordination (z. B. über APIs für RESTful-Endpunkte oder WebSockets für persistente Verbindungen). Er kommuniziert mit dem Inferenz-Service, skaliert unabhängig auf Multi-Core-CPUs und RAM, um hohen Web- Datenverkehr zu bewältigen, der nicht auf GPUs basiert, und erfordert oft einen Load Balancer (wie AWS Application Load Balancer oder Network Load Balancer), um eingehende Anfragen auf mehrere Instances zu verteilen, insbesondere in Szenarien mit hoher Parallelität. Ein Ingress-Controller kann externe Zugriffs- und Routing-Regeln für verbesserte Sicherheit und Datenverkehrsgestaltung verwalten.
-
Inferenz-Service: Dient als Kernstück für KI-Berechnungen und wird auf GPUs mit ausreichendem VRAM (z. B. 8–12 GB für Modelle wie DistilBERT) ausgeführt. Er führt Vektoreinbettungen, Wissensextraktion und Modellinferenz (z. B. über APIs für Batch-Anfragen oder WebSockets für Echtzeit-Streaming) mithilfe benutzerdefinierter oder Open-Source-Modelle durch. Diese Isolierung verhindert Abhängigkeitskonflikte, ermöglicht Modellaktualisierungen ohne Ausfallzeiten und ermöglicht eine horizontale Skalierung mit Lastausgleich für mehrere gleichzeitige Anfragen. Um den Modell-Service effektiv verfügbar zu machen, wird er in der Regel hinter einem Load Balancer platziert, um GPU-gebundene Workloads auf replizierte Instances zu verteilen. Eine Ingress-Ressource oder ein Controller (wie beispielsweise der ALB-Ingress-Controller in AWS) übernimmt das externe Routing, die SSL-Terminierung und die pfadbasierte Weiterleitung, um einen sicheren und effizienten Zugriff zu gewährleisten, ohne einzelne GPUs zu überlasten.
Übersicht über die Lösung
Echtzeit-Online-Inferenzsysteme erfordern eine leistungsstarke, ausfallsichere Architektur, die extrem niedrige Latenzzeiten bietet und gleichzeitig unvorhersehbare, hohe Datenverkehrsausfälle bewältigen kann. Diese Lösungsübersicht erläutert, wie die folgenden AWS-Komponenten im von uns erstellten Amazon-EKS-Cluster zusammenarbeiten, um sicherzustellen, dass unser Cluster Machine-Learning-Modelle hosten und verwalten kann, die sofortige Prognosen zu Live-Daten mit minimaler Verzögerung für Endbenutzer bereitstellen.
-
Amazon-G5-EC2-Instances
– Für GPU-intensive Inferenzaufgaben verwenden wir die G5-EC2-Instance-Typen g5.xlarge und g5.2xlarge, die über eine einzelne (1) NVIDIA A10G-GPU mit 24 GB Speicher verfügen (z. B. 8 Milliarden Parameter bei FP16). Diese GPUs basieren auf der NVIDIA Ampere-Architektur und werden von NVIDIA A10G Tensor Core GPUs und AMD EPYC-Prozessoren der 2. Generation angetrieben. Sie unterstützen 4–8 vCPUs, bis zu 10 Gbit/s Netzwerkbandbreite und 250–450 GB lokalen NVMe-SSD-Speicher. Dies gewährleistet schnelle Datenübertragung und Rechenleistung für komplexe Modelle und macht sie ideal für Inferenzaufgaben mit geringer Latenz und hohem Durchsatz. Die Auswahl eines EC2-Instance-Typs ist anwendungsspezifisch und hängt von Ihrem Modell (z. B. Image-, Video- oder Textmodell) sowie Ihren Anforderungen an Latenz und Durchsatz ab. Wenn Sie beispielsweise ein Image- und/oder Videomodell verwenden, empfehlen wir den Einsatz von P5-EC2-Instances , um eine optimale Echtzeit-Latenz zu erzielen. Wir empfehlen, zunächst mit G5-EC2-Instances zu beginnen, da diese einen guten Ausgangspunkt für eine schnelle Inbetriebnahme bieten. Anschließend können Sie anhand von Leistungsbenchmark-Tests beurteilen, ob sie für Ihre Workloads geeignet sind. Für anspruchsvollere Fälle sollten Sie G6-EC2-Instances in Betracht ziehen. -
Amazon-EC2-M7g-Instances
– Für rechenintensive Aufgaben wie Datenvorverarbeitung, API-Anfragenbearbeitung, Hosting des Karpenter-Controllers, Add-Ons und andere Systemkomponenten verwenden wir den EC2-Instance-Typ m5.xlarge M7g. M7g-Instances sind ARM-basierte Instances mit 4 vCPUs, 16 GB Arbeitsspeicher, einer Netzwerkbandbreite von bis zu 12,5 Gbit/s und AWS-Graviton3-Prozessoren. Die Auswahl eines EC2-Instance-Typs ist anwendungsspezifisch und hängt von den Anforderungen Ihrer Workload hinsichtlich Rechenleistung, Arbeitsspeicher und Skalierbarkeit ab. Für rechenoptimierte Workloads können Sie C7g-EC2-Instances in Betracht ziehen, die ebenfalls mit Graviton3-Prozessoren ausgestattet sind, jedoch für bestimmte Anwendungsfälle auf eine höhere Rechenleistung als M7g-Instances optimiert sind. Alternativ bieten die neueren C8g-EC2-Instances (sofern verfügbar) eine um bis zu 30 % bessere Rechenleistung als C7g-Instances. Wir empfehlen den Einstieg mit M7g-EC2-Instances aufgrund ihrer Kosteneffizienz und Kompatibilität mit einer Vielzahl von Workloads (z. B. Anwendungsserver, Microservices, Gaming-Server, mittelgroße Datenspeicher). Anschließend sollten Sie durch Leistungsbenchmark-Tests prüfen, ob sie für Ihre Workloads geeignet sind. -
Mountpoint-CSI-Treiber für Amazon S3 – Für Workloads auf Einzel-GPU-Instances, bei denen mehrere Pods eine GPU gemeinsam nutzen (z. B. mehrere Pods, die auf demselben Knoten geplant sind, um dessen GPU-Ressourcen zu nutzen), verwenden wir den Mountpoint-S3-CSI-Treiber, um die Speichernutzung zu optimieren. Dies ist für Aufgaben wie die Inferenz großer Modelle in kostenbewussten, wenig komplexen Einrichtungen von entscheidender Bedeutung. Er stellt Amazon-S3-Buckets als POSIX-ähnliches Dateisystem zur Verfügung, das für den Kubernetes-Cluster verfügbar ist. Dadurch können Inferenz-Pods Modellartefakte (z. B. Modellgewichte) direkt in den Speicher lesen, ohne sie zuvor herunterladen zu müssen, und Datensätze mithilfe von Standard-Dateioperationen eingeben. Darüber hinaus verfügt S3 über praktisch unbegrenzte Speicherkapazität und beschleunigt datenintensive Inferenz-Workloads. Die Auswahl eines Speicher-CSI-Treibers ist anwendungsspezifisch und hängt von den Anforderungen Ihrer Workload hinsichtlich Durchsatz und Latenz ab. Obwohl der FSx für OpenZFS-CSI-Treiber eine Latenz von weniger als einer Millisekunde für zufällige E/A-Vorgänge oder vollständig POSIX-konforme gemeinsam genutzte persistente Volumes über Knoten hinweg bietet, empfehlen wir den Einstieg mit dem Mountpoint-S3-CSI-Treiber. Dieser bietet Skalierbarkeit, geringere Kosten für große Datensätze und eine integrierte Einbindung in den von S3 verwalteten Objektspeicher für leseintensive Inferenzmuster (z. B. Streaming-Modelleingaben). Anschließend können Sie anhand von Leistungsbenchmark-Tests beurteilen, ob er für Ihre Workloads geeignet ist.
-
EKS Pod Identity Agent – Um den Zugriff auf AWS-Services zu ermöglichen, verwenden wir den EKS Pod Identity Agent, der einen einzigen Service-Prinzipal nutzt und die Zuordnung von IAM-Rollen auf Pod-Ebene innerhalb des Amazon-EKS-Clusters vereinfacht. EKS Pod Identity bietet eine optimierte Alternative zum herkömmlichen Ansatz derIAM-Rollen für Servicekonten (IRSA), indem es einen einzigen Service-Prinzipal (pods.eks.amazonaws.com) verwendet, anstatt sich auf einzelne OIDC-Anbieter für jeden Cluster zu verlassen, was die Zuweisung von Berechtigungen vereinfacht. Darüber hinaus ermöglicht es die Wiederverwendung von Rollen über mehrere Cluster hinweg und unterstützt erweiterte Features wie IAM- Rollensitzungs-Tags und Ziel-IAM-Rollen.
-
EKS-Knoten-Überwachungsagent – Um die kontinuierliche Verfügbarkeit und Zuverlässigkeit der Inferenz-Services sicherzustellen, setzen wir den EKS-Knotenüberwachungsagenten mit automatischer Reparatur ein, der fehlerhafte Knoten automatisch erkennt und ersetzt und so Ausfallzeiten minimiert. Er überwacht fortlaufend die Knoten auf Hardware-, Kernel-, Netzwerk- und Speicherprobleme mithilfe erweiterter Zustandsprüfungen (z. B. KernelReady, NetworkingReady). Bei GPU-Knoten erkennt er beschleunigerspezifische Ausfälle und leitet eine effiziente Behebung ein. Hierzu werden fehlerhafte Knoten isoliert, 10 Minuten lang auf die Behebung vorübergehender GPU-Probleme gewartet und bei anhaltenden Ausfällen die Knoten nach 30 Minuten ersetzt.
-
Bottlerocket-AMI – Um eine sicherheitsoptimierte Grundlage für unseren EKS-Cluster zu schaffen, setzen wir das Bottlerocket-AMI ein, das ausschließlich die für den Betrieb von Containern erforderlichen Komponenten enthält und minimale Startzeiten für eine schnelle Skalierung bietet. Die Auswahl eines Knoten-AMI ist anwendungsspezifisch und hängt von den Anforderungen Ihrer Workload hinsichtlich Anpassung, Sicherheit und Skalierbarkeit ab. Obwohl die AL2023-AMI eine größere Flexibilität für Installationen und Anpassungen auf Host-Ebene bietet (z. B. die Angabe eines dedizierten Cache-Verzeichnisses in einem PV/PVC ohne zusätzliche Knoten-Konfigurationen), empfehlen wir, zunächst mit der Bottlerocket-AMI zu beginnen, da diese weniger Speicherplatz benötigt und über eine integrierte Optimierung für containerisierte Workloads (z. B empfehlen wir, zunächst mit dem Bottlerocket-AMI zu beginnen, da es weniger Speicherplatz benötigt und über integrierte Optimierungen für containerisierte Workloads (z. B. Microservices, Inferenz-Server, skalierbare APIs) verfügt. Anschließend können Sie durch Leistungsbenchmark-Tests beurteilen, ob es für Ihre Workloads geeignet ist.
-
AWS Load Balancer Controller (LBC) – Um Echtzeit-Inferenzendpunkte verfügbar zu machen, verwenden wir den AWS Load Balancer Controller, der automatisch Application Load Balancer (ALBs) für HTTP/HTTPS-Datenverkehr und Network Load Balancer (NLBs) für TCP/UDP-Datenverkehr auf Basis von Kubernetes-Ingress- und Service-Ressourcen bereitstellt und verwaltet. Dies ermöglicht die Integration von Inferenzmodellen mit externen Clients. Darüber hinaus unterstützt es Features wie pfadbasiertes Routing, um Inferenz-Anfragen auf mehrere Pods oder Knoten zu verteilen. Dadurch wird die Skalierbarkeit bei Datenverkehrsspitzen gewährleistet und die Latenz durch AWS-native Optimierungen wie Verbindungs-Multiplexing und Zustandsprüfungen minimiert.
1. Erstellen Ihres EKS-Clusters
In diesem Schritt erstellen wir einen Cluster mit CPU-Knoten und einer verwalteten Knotengruppe unter Verwendung einer AWS CloudFormation-basierten eksctl ClusterConfig
Standardmäßig erstellt eksctl eine dedizierte VPC für den Cluster mit einem CIDR-Block von 192.168.0.0/16. Das VPC umfasst drei öffentliche und drei private Subnetze, die jeweils auf drei verschiedene Availability Zones (oder zwei AZs in der us-east-1-Region) verteilt sind. Dies ist die ideale Methode zum Bereitstellen von Kubernetes-Workloads. Die Vorlage stellt außerdem ein Internet-Gateway bereit, das den öffentlichen Subnetzen über Standard-Routen in ihren Routing-Tabellen und ein einzelnes NAT-Gateway in einem der öffentlichen Subnetze Internetzugang gewährt. Die Standard-Routen in den Routing-Tabellen der privaten Subnetze leiten den ausgehenden Datenverkehr über das NAT-Gateway zum Internetzugang weiter. Weitere Informationen zu dieser Konfiguration finden Sie unter Bereitstellen von Knoten in privaten Subnetzen.
Überprüfung Ihrer Anmeldeinformationen
Überprüfen Sie, ob Ihre AWS-CLI-Anmeldeinformationen gültig sind und Sie sich bei AWS-Services anmelden können:
aws sts get-caller-identity
Bei Erfolg gibt die CLI Details zu Ihrer AWS-Identität zurück (Benutzer-ID, Konto und ARN).
Überprüfung der Verfügbarkeit von Instances
G5-Instance-Typen stehen in allen Regionen zur Verfügung. Überprüfen Sie Ihre nächstgelegene Region. Zum Beispiel:
aws ec2 describe-instance-types --instance-types g5.xlarge g5.2xlarge --region us-east-1
Bei Erfolg ist der G5-Instance-Typ in der von Ihnen angegebenen Region verfügbar.
Das Bottlerocket-AMI ist nicht in allen Regionen verfügbar. Überprüfen Sie dies, indem Sie eine Bottlerocket-AMI-ID für Ihre nächstgelegene Region abrufen. Zum Beispiel:
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
Bei Erfolg ist das Bottlerocket-AMI in der von Ihnen angegebenen Region verfügbar.
Vorbereitung Ihrer Umgebung
Legen Sie zunächst die folgenden Umgebungsvariablen in einem neuen Terminalfenster fest. Hinweis: Ersetzen Sie die Platzhalterbeispiele unbedingt durch Ihre individuellen Werte, einschließlich Cluster-Name, gewünschte Region, Karpenter-Vorversion
Tipp
Einige Variablen (wie ${AWS_REGION} und ${K8S_VERSION}) werden früh im Block definiert und dann in späteren Befehlen referenziert, um Konsistenz zu gewährleisten und Wiederholungen zu vermeiden. Führen Sie die Befehle unbedingt nacheinander aus, damit diese Werte ordnungsgemäß exportiert werden und in nachfolgenden Definitionen zur Verfügung stehen.
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/')"
Erstellung der erforderlichen Rollen und Richtlinien
Karpenter benötigt spezifische IAM-Rollen und -Richtlinien (z. B. Karpenter-Controller-IAM-Rolle, Instance-Profil und Richtlinien), um EC2-Instances als Kubernetes-Worker-Knoten zu verwalten. Es nutzt diese Rollen, um Aktionen wie das Starten und Beenden von EC2-Instances, das Taggen von Ressourcen und die Interaktion mit anderen AWS-Services durchzuführen. Erstellen Sie die Karpenter-Rollen und -Richtlinien mithilfe der Datei cloudformation.yaml
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}"
Der AWS LBC benötigt die Berechtigung, AWS Load Balancer bereitzustellen und zu verwalten, beispielsweise zum Erstellen von ALBs für Ingress-Ressourcen oder NLBs für Services vom Typ LoadBalancer. Diese Berechtigungsrichtlinie legen wir bei der Erstellung des Clusters fest. Bei der Erstellung des Clusters erstellen wir das Servicekonto mit eksctl in der ClusterConfig. Erstellen Sie die LBC-IAM-Richtlinie:
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)"
Wenn der Mountpoint-S3-CSI-Treiber installiert ist, werden seine DaemonSet-Pods so konfiguriert, dass sie ein Servicekonto für die Ausführung verwenden. Der Mountpoint für den Mountpoint-S3-CSI-Treiber benötigt die Berechtigung zur Interaktion mit dem Amazon-S3-Bucket, den Sie später in diesem Leitfaden erstellen. Diese Berechtigungsrichtlinie legen wir bei der Erstellung des Clusters fest. Bei der Erstellung des Clusters erstellen wir das Servicekonto mit eksctl in der ClusterConfig. Erstellen Sie die S3-IAM-Richtlinie:
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}/*\"]}]}"
Hinweis: Sollte bereits eine Rolle mit diesem Namen vorhanden sein, benennen Sie die Rolle um. Die Rolle, die wir in diesem Schritt erstellen, ist spezifisch für Ihren Cluster und Ihren S3-Bucket.
Den Cluster erstellen
In dieser Vorlage erstellt eksctl automatisch ein Kubernetes-Servicekonto für EKS Pod Identity, Knoten-Überwachungsagent, CoreDNS, Kubeproxy und das VPC-CNI-Plugin. Derzeit ist der Mountpoint-S3-CSI-Treiber für EKS Pod Identity nicht verfügbar, daher erstellen wir eine IAM-Rolle für das Servicekonto (IRSA) und einen OIDC-Endpunkt. Zusätzlich erstellen wir ein Servicekonto für AWS Load Balancer Controller (LBC). Für den Zugriff auf Bottlerocket-Knoten fügt eksctl automatisch AmazonSSMManagedInstanceCore für Bottlerocket hinzu, um sichere Shell-Sitzungen über SSM zu ermöglichen.
Führen Sie in demselben Terminal, in dem Sie Ihre Umgebungsvariablen festgelegt haben, den folgenden Befehlsblock aus, um den Cluster zu erstellen:
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
Dieser Vorgang dauert einige Minuten. Wenn Sie den Status überwachen möchten, besuchen Sie die AWS CloudFormation
2. Verifizierung des Zustands von Cluster-Knoten und Pods
Wir führen einige Zustandsprüfungen durch, um sicherzustellen, dass der Cluster einsatzbereit ist. Wenn der vorherige Befehl abgeschlossen ist, zeigen Sie die Instance-Typen an und überprüfen Sie mit dem folgenden Befehl, ob Ihre CPU-Systemknoten den Ready-Status erreicht haben:
kubectl get nodes -L node.kubernetes.io/instance-type
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
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
Überprüfen Sie alle Pod-Identity-Zuordnungen und wie diese eine Rolle einem Servicekonto in einem Namespace im Cluster zuordnen, mit dem folgenden Befehl:
eksctl get podidentityassociation --cluster ${EKS_CLUSTER_NAME} --region ${AWS_REGION}
Die Ausgabe sollte die IAM-Rollen für Karpenter („karpenter“) und AWS LBC („aws-load-balancer-controller“) anzeigen.
Überprüfen Sie, ob die DaemonSets verfügbar sind:
kubectl get daemonsets -n kube-system
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
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
Überprüfen Sie, ob alle Add-Ons auf dem Cluster installiert sind:
eksctl get addons --cluster ${EKS_CLUSTER_NAME} --region ${AWS_REGION}
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
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. Installation von Karpenter
Installieren Sie den Karpenter-Controller auf Ihren CPU-Worker-Knoten (cpu-worker), um Kosten zu optimieren und GPU-Ressourcen zu schonen. Wir installieren ihn im Namespace „kube-system“ und geben das Servicekonto „karpenter“ an, das wir bei der Erstellung des Clusters definiert haben. Darüber hinaus konfiguriert dieser Befehl den Cluster-Namen und eine Spot-Instance-Unterbrechungs-Warteschlange für CPU-Knoten. Karpenter wird IRSA verwenden, um diese IAM-Rolle zu übernehmen.
# 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
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
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
Überprüfen Sie, ob Karpenter ausgeführt wird:
kubectl get pods -n kube-system -l app.kubernetes.io/name=karpenter
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
NAME READY STATUS RESTARTS AGE karpenter-555895dc-865bc 1/1 Running 0 5m58s karpenter-555895dc-j7tk9 1/1 Running 0 5m58s
4. Einrichtung von Karpenter NodePools
In diesem Schritt konfigurieren wir sich gegenseitig ausschließende CPU und GPU Karpenter NodePoolslimits in der NodePool-Spezifikation begrenzt die maximalen Gesamtressourcen (z. B. CPU, Arbeitsspeicher, GPUs), die jeder NodePool über alle bereitgestellten Knoten hinweg verbrauchen kann, und verhindert die Bereitstellung zusätzlicher Knoten, wenn diese Grenzwerte überschritten werden. NodePools unterstützen zwar allgemeine Instance-Kategorien (z. B. c, g), jedoch lassen sich die Kosten für Ihre On-Demand-Workloads leichter abschätzen, wenn Sie bestimmte Instance-Typen
Einrichtung von GPU NodePool
In diesem NodePool legen wir Ressourcenbeschränkungen fest, um die Bereitstellung von Knoten mit GPU-Fähigkeiten zu verwalten. Diese Beschränkungen dienen dazu, die Gesamtressourcen aller Knoten im Pool zu begrenzen, wobei insgesamt bis zu 10 Instances zulässig sind. Jede Instance ist entweder vom Typ g5.xlarge (4 vCPUs, 16 GiB Arbeitsspeicher, 1 GPU) oder g5.2xlarge (8 vCPUs, 32 GiB Arbeitsspeicher, 1 GPU), sofern die Gesamtzahl der vCPUs 80 nicht überschreitet, der Gesamtspeicher 320 GiB nicht übersteigt und die Gesamtzahl der GPUs 10 nicht überschreitet. Beispielsweise kann der Pool 10 g5.2xlarge-Instances (80 vCPUs, 320 GiB, 10 GPUs) oder 10 g5.xlarge-Instances (40 vCPUs, 160 GiB, 10 GPUs) oder eine Kombination aus beispielsweise 5 g5.xlarge- und 5 g5.2xlarge- Instances (60 vCPUs, 240 GiB, 10 GPUs) bereitstellen. Dies gewährleistet Flexibilität entsprechend den Workload-Anforderungen unter Berücksichtigung der Ressourcenbeschränkungen.
Darüber hinaus geben wir die ID der Nvidia-Variante der Bottlerocket-AMI an. Schließlich legen wir eine UnterbrechungsrichtlinieconsolidateAfter: 30m) zu entfernen, und legen eine maximale Lebensdauer der Knoten auf 30 Tage (expireAfter: 720h) fest, um die Kosten zu optimieren und die Knotenintegrität für GPU-intensive Aufgaben aufrechtzuerhalten. Weitere Informationen finden Sie unter Deaktivieren der Karpenter-Konsolidierung für unterbrechungsempfindliche Workloads und Verwendung von ttlSecondsAfterFinished zur automatischen Bereinigung von Kubernetes-Aufträgen.
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
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
nodepool.karpenter.sh/gpu-a10g-inference-g5 created ec2nodeclass.karpenter.k8s.aws/gpu-a10g-inference-ec2 created
Überprüfen Sie, ob der NodePool erstellt wurde und ordnungsgemäß funktioniert:
kubectl get nodepool gpu-a10g-inference-g5 -o yaml
Suchen Sie nach status.conditions wie ValidationSucceeded: True, NodeClassReady: True und Ready: True, um zu bestätigen, dass der NodePool fehlerfrei ist.
Einrichtung von CPU NodePool
In diesem NodePool legen wir Limits fest, um ungefähr 50 Instances zu unterstützen, was einer moderaten CPU-Workload (z. B. 100–200 Pods) und typischen AWS-vCPU-Kontingenten (z. B. 128–1 152) entspricht. Die Limits werden unter der Annahme berechnet, dass der NodePool auf bis zu 50 m7.xlarge-Instances hochskaliert werden soll: CPU (4 vCPUs pro Instances × 50 Instances = 200 vCPUs) und Speicher (16 GiB pro Instances × 50 Instances = 800 GiB). Diese Limits dienen dazu, die Gesamtressourcen aller Knoten im Pool zu begrenzen, wobei bis zu 50 m7g.xlarge-Instances (mit jeweils 4 vCPUs und 16 GiB Arbeitsspeicher) zulässig sind, solange die Gesamtzahl der vCPUs 200 und der Gesamtarbeitsspeicher 800 GiB nicht überschreitet.
Darüber hinaus geben wir die ID der Standardvariante der Bottlerocket-AMI an. Schließlich legen wir eine UnterbrechungsrichtlinieconsolidateAfter: 60m) zu entfernen, und legen eine maximale Lebensdauer der Knoten auf 30 Tage (expireAfter: 720h) fest, um die Kosten zu optimieren und die Knotenintegrität für GPU-intensive Aufgaben aufrechtzuerhalten. Weitere Informationen finden Sie unter Deaktivieren der Karpenter-Konsolidierung für unterbrechungsempfindliche Workloads und Verwendung von ttlSecondsAfterFinished zur automatischen Bereinigung von Kubernetes-Aufträgen.
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
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
nodepool.karpenter.sh/cpu-inference-m7gxlarge created ec2nodeclass.karpenter.k8s.aws/cpu-inference-m7gxlarge-ec2 created
Überprüfen Sie, ob der NodePool erstellt wurde und ordnungsgemäß funktioniert:
kubectl get nodepool cpu-inference-m7gxlarge -o yaml
Suchen Sie nach status.conditions wie ValidationSucceeded: True, NodeClassReady: True und Ready: True, um zu bestätigen, dass der NodePool fehlerfrei ist.
5. Bereitstellung eines GPU-Pods zur Freigabe einer GPU
Sie benötigen das Nvidia-Geräte-Plugin, damit Kubernetes GPU-Geräte für den Kubernetes-Cluster freigeben kann. Normalerweise müssten Sie das Plugin als DaemonSet bereitstellen. Das Bottlerocket-AMI installiert das Plugin jedoch bereits als Teil des AMI. Das bedeutet, dass bei Verwendung von Bottlerocket-AMIs das Nvidia-Geräte-Plugin DaemonSet nicht bereitgestellt werden muss. Weitere Informationen finden Sie unter Kubernetes-Geräte-Plugin zur Freigabe von GPUs.
Bereitstellung eines Beispiel-Pods
Karpenter agiert dynamisch: Es stellt GPU-Knoten bereit, wenn eine Workload (Pod) GPU-Ressourcen anfordert. Um zu überprüfen, ob Pods GPUs anfordern und verwenden können, stellen Sie einen Pod bereit, der die nvidia.com/gpu-Ressource innerhalb seiner Grenzen anfordert (z. B. nvidia.com/gpu: 1). Weitere Informationen zu diesen Bezeichnungen finden Sie unter Planen von Workloads mit GPU-Anforderungen unter Verwendung bekannter Bezeichnungen.
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
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
pod/gpu-ndivia-smi created
Warten Sie einen Moment und prüfen Sie dann, ob der Pod den Status „Ausstehend“, „Container wird erstellt“, „Wird ausgeführt“ und schließlich „Abgeschlossen“ aufweist:
kubectl get pod gpu-nvidia-smi -w
Überprüfen Sie, ob der Knoten für den Pod zum GPU-Knoten-Pool gehört:
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"
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
Name Nodepool ip-192-168-83-245.ec2.internal gpu-a10g-inference-g5
Überprüfen Sie die Pod-Protokolle:
kubectl logs gpu-nvidia-smi
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
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. (Optional) Modell-Artefakte für die Bereitstellung vorbereiten und hochladen
In diesem Schritt stellen Sie einen Modell-Service für die Echtzeit-Image-Klassifizierung bereit, beginnend mit dem Hochladen der Modellgewichte in einen Amazon-S3-Bucket. Zur Demonstration verwenden wir das Open-Source-Vision-Modell GPUNet-0
Einrichten Ihrer -Umgebung
Um die Gewichte des GPUNet-0-Modells herunterzuladen, benötigen Sie in diesem Schritt Zugriff auf den NGC-Katalog von NVIDIA und Docker
-
Registrieren Sie sich für ein kostenloses NGC-Konto
und generieren Sie einen API-Schlüssel über das NGC-Dashboard (Benutzersymbol > Einstellungen > API-Schlüssel generieren > Persönlichen Schlüssel generieren > NGC-Katalog). -
Laden Sie die NGC CLI
(Linux/macOS/Windows) herunter, installieren Sie sie und konfigurieren Sie die CLI mit: ngc config set. Geben Sie Ihren API-Schlüssel ein, wenn Sie dazu aufgefordert werden. Setzen Sie „org“ aufnvidiaund drücken Sie die Eingabetaste, um die Standardeinstellungen für andere zu akzeptieren. Bei erfolgreicher Eingabe sollte etwa Folgendes angezeigt werden:Successfully saved NGC configuration to /Users/your-username/.ngc/config.
Verifizierung der Berechtigungen für Servicekonten
Bevor wir beginnen, überprüfen Sie die Berechtigungen des Kubernetes-Servicekontos:
kubectl get serviceaccount s3-csi-driver-sa -n kube-system -o yaml
Während der Cluster-Erstellung haben wir die S3CSIDriverPolicy an eine IAM-Rolle angefügt und das Servicekonto („s3-csi-driver-sa“) mit einer Annotation versehen. Die Mountpoint-S3-CSI-Treiber-Pods übernehmen die Berechtigungen der IAM-Rolle, wenn sie mit S3 interagieren. Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
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
Toleranz hinzufügen
Der S3-CSI-Treiber wird als DaemonSet auf allen Knoten ausgeführt. Pods verwenden den CSI-Treiber auf diesen Knoten, um S3-Volumes einzubinden. Um die Planung auf unseren GPU-Knoten mit Taints zu ermöglichen, fügen Sie dem DaemonSet eine Toleranz hinzu:
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"}}]'
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
daemonset.apps/s3-csi-node patched
Modellgewichte in S3 hochladen
In diesem Schritt erstellen Sie einen Amazon-S3-Bucket, laden die GPUNet-0-Modellgewichte von der NVIDIA GPU Cloud (NGC) herunter und laden sie in den Bucket hoch. Auf diese Gewichte greift unsere Anwendung zur Laufzeit für die Inferenz zu.
Erstellen Sie Ihren Amazon-S3-Bucket:
aws s3 mb s3://${S3_BUCKET_NAME} --region ${AWS_REGION}
Aktivieren Sie die S3-Versionsverwaltung für den Bucket, um zu verhindern, dass versehentliche Löschungen und Überschreibungen zu sofortigem und dauerhaftem Datenverlust führen:
aws s3api put-bucket-versioning --bucket ${S3_BUCKET_NAME} --versioning-configuration Status=Enabled
Wenden Sie eine Lebenszyklusregel auf den Bucket an, um überschriebene oder gelöschte Objektversionen 14 Tage nach ihrer Veraltung zu entfernen, abgelaufene Löschmarkierungen zu entfernen und unvollständige mehrteilige Uploads nach 7 Tagen zu entfernen. Weitere Informationen finden Sie unter Beispiele für S3-Lebenszykluskonfigurationen.
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}}]}'
Laden Sie die GPUNet-0-Modellgewichte von NGC herunter. Zum Beispiel unter macOS:
ngc registry model download-version nvidia/dle/gpunet_0_pyt_ckpt:21.12.0_amp --dest ~/downloads
Anmerkung
Möglicherweise müssen Sie diesen Download-Befehl an Ihr Betriebssystem anpassen. Damit dieser Befehl auf einem Linux-System funktioniert, müssen Sie das Verzeichnis wahrscheinlich als Teil des Befehls erstellen (z. B. mkdir ~/downloads).
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
{ "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]" }
Benennen Sie die Checkpoint-Datei um, damit sie der erwarteten Benennung in unserem Anwendungscode in späteren Schritten entspricht (eine Extraktion ist nicht erforderlich, da es sich um einen standardmäßigen PyTorch *.pth.tar-Checkpoint handelt, der das Modellstatus-Wörterbuch enthält):
mv ~/downloads/gpunet_0_pyt_ckpt_v21.12.0_amp/0.65ms.pth.tar gpunet-0.pth
Aktivieren Sie die gängige AWS-Laufzeit
aws configure set s3.preferred_transfer_client crt
Laden Sie die Modellgewichte in Ihren S3-Bucket hoch:
aws s3 cp gpunet-0.pth s3://${S3_BUCKET_NAME}/gpunet-0.pth
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
upload: ./gpunet-0.pth to s3://eks-rt-inference-models-us-east-1-1752722786/gpunet-0.pth
Modell-Service erstellen
In diesem Schritt richten Sie eine FastAPI-Web-Anwendung für die GPU-beschleunigte Image-Klassifizierung unter Verwendung des GPUNet-0-Vision-Modells ein. Die Anwendung lädt die Modellgewichte zur Laufzeit von Amazon S3 herunter, ruft die Modellarchitektur aus dem Repository von NVIDIA zum Zwischenspeichern ab und lädt ImageNet-Klassenbezeichnungen über HTTP herunter. Die Anwendung beinhaltet Image-Vorverarbeitungstransformationen und stellt zwei Endpunkte bereit: einen Root-GET-Endpunkt /predict für die Statusüberprüfung und einen POST-Endpunkt, der eine Bild-URL akzeptiert.
Wir bedienen das Modell unter Verwendung von FastAPI mit PyTorch und laden die Gewichte zur Laufzeit aus Amazon S3 in einer containerisierten Umgebung, um eine schnelle Prototypenerstellung und Kubernetes-Bereitstellung zu ermöglichen. Weitere Methoden wie optimiertes Batching oder Hochdurchsatz-Engines finden Sie unter Bereitstellen von ML-Modellen.
Erstellen der Anwendung
Erstellen Sie ein Verzeichnis für Ihre Anwendungsdateien, z. B. model-testing, wechseln Sie dann in dieses Verzeichnis und fügen Sie den folgenden Code zu einer neuen Datei mit dem Namen app.py hinzu:
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))
Docker-Datei erstellen
Die folgende Docker-Datei erstellt ein Container-Image für unsere Anwendung unter Verwendung des GPUNet-Modells aus dem GitHub-Repository Beispiele für Deep Learning mit NVIDIA für Tensor-Kerne
Wir reduzieren die Größe des Container-Images, indem wir ausschließlich eine PyTorch-Basis für die Laufzeit verwenden, nur die wesentlichen Pakete mit Cache-Bereinigung installieren, den Modell-Code vorab zwischenspeichern und das „Einbrennen” von Gewichten im Container-Image vermeiden, um schnellere Abrufe und Aktualisierungen zu ermöglichen. Weitere Informationen finden Sie unter Reduzieren der Größe von Container-Images.
Erstellen Sie im selben Verzeichnis wie app.py die Dockerfile:
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"]
Testen der Anwendung
Erstellen Sie aus demselben Verzeichnis wie Ihr app.py und yDockerfile das Container-Image für die Inferenz-Anwendung, das auf die AMD64-Architektur abzielt:
docker build --platform linux/amd64 -t gpunet-inference-app .
Legen Sie Umgebungsvariablen für Ihre AWS-Anmeldeinformationen und optional ein AWS-Sitzungs-Token fest. Zum Beispiel:
export AWS_REGION="us-east-1" export AWS_ACCESS_KEY_ID=ABCEXAMPLESCUJFEIELSMUHHAZ export AWS_SECRET_ACCESS_KEY=123EXAMPLEMZREoQXr8XkiicsOgWDQ5TpUsq0/Z
Führen Sie den Container lokal aus und fügen Sie AWS-Anmeldeinformationen als Umgebungsvariablen für den S3-Zugriff ein. Zum Beispiel:
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
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
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)
Testen Sie in einem neuen Terminalfenster den Inferenz-Endpunkt, indem Sie eine Beispiel-POST-Anfrage mit einer öffentlichen Image-URL als Abfrageparameter senden:
curl -X POST "http://localhost:8080/predict?image_url=http://images.cocodataset.org/test-stuff2017/000000024309.jpg"
Die erwartete Ausgabe sollte eine JSON-Antwort mit den fünf besten Prognosen sein, ähnlich wie hier (die tatsächlichen Bezeichnungen und Wahrscheinlichkeiten können je nach Image und Modellgenauigkeit leicht variieren):
{"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}]}
Beenden Sie die Anwendung mit „Strg + C“.
Übertragen des Containers an Amazon ECR
In diesem Schritt laden wir das Container-Image für den GPUNet-0-Modell-Service in die Amazon Elastic Container Registry (ECR) hoch, sodass es für die Bereitstellung in Amazon EKS verfügbar ist. Dieser Prozess umfasst die Erstellung eines neuen ECR-Repositorys zur Speicherung des Images, die Authentifizierung bei ECR sowie das Kennzeichnen und Übertragen des Container-Images in unsere Registry.
Navigieren Sie zunächst zurück zu dem Verzeichnis, in dem Sie zu Beginn dieser Anleitung Ihre Umgebungsvariablen festgelegt haben. Zum Beispiel:
cd ..
Erstellen Sie ein Repository in Amazon ECR:
aws ecr create-repository --repository-name gpunet-inference-app --region ${AWS_REGION}
Melden Sie sich bei Amazon ECR an:
aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
Login Succeeded
Kennzeichnen Sie das Image:
docker tag gpunet-inference-app:latest ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/gpunet-inference-app:latest
Übertragen Sie das Image in Ihr Amazon-ECR-Repository:
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/gpunet-inference-app:latest
Dieser letzte Schritt kann einige Minuten in Anspruch nehmen.
7. (Optional) Modell-Service verfügbar machen
In diesem Schritt stellen Sie Ihren Echtzeit-Inferenzmodell-Service mithilfe des AWS Load Balancer Controllers (LBC) extern in Amazon EKS bereit. Dazu gehört die Einrichtung des LBC, die Bereitstellung von Modellgewichten aus Amazon S3 als persistentes Volume mithilfe des Mountpoint-S3-CSI-Treibers, die Bereitstellung eines GPU-beschleunigten Anwendungs-Pods, die Erstellung eines Services und eines Ingresses zur Bereitstellung eines Application Load Balancer (ALB) sowie das Testen des Endpunkts.
Überprüfen Sie zunächst die Pod-Identity-Zuordnung für das AWS LBC und stellen Sie sicher, dass das Servicekonto ordnungsgemäß mit der erforderlichen IAM-Rolle verknüpft ist:
eksctl get podidentityassociation --cluster ${EKS_CLUSTER_NAME} --namespace kube-system --service-account-name aws-load-balancer-controller
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
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
Kennzeichnen Ihrer Cluster-Sicherheitsgruppe
Der AWS Load Balancer Controller unterstützt nur eine einzige Sicherheitsgruppe mit dem Tag-Schlüssel karpenter.sh/discovery: "${EKS_CLUSTER_NAME}" für die Sicherheitsgruppen-Auswahl von Karpenter. Beim Erstellen eines Clusters mit eksctl wird die Standard-Cluster-Sicherheitsgruppe (die das "kubernetes.io/cluster/<cluster-name>: owned"-Tag hat) nicht automatisch mit karpenter.sh/discovery-Tags versehen. Dieses Tag ist für Karpenter unerlässlich, um diese Sicherheitsgruppe zu erkennen und den bereitgestellten Knoten zuzuordnen. Durch das Anfügen dieser Sicherheitsgruppe wird die Kompatibilität mit dem AWS Load Balancer Controller (LBC) gewährleistet. Dadurch kann dieser automatisch die Regeln für den eingehenden Datenverkehr für Services verwalten, die über Ingress verfügbar sind, wie beispielsweise der Modell-Service in diesen Schritten.
Exportieren Sie die VPC-ID für Ihren Cluster:
CLUSTER_VPC_ID="$(aws eks describe-cluster --name ${EKS_CLUSTER_NAME} --query cluster.resourcesVpcConfig.vpcId --output text)"
Exportieren Sie die Standard-Sicherheitsgruppe für Ihren Cluster:
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)"
Fügen Sie das karpenter.sh/discovery-Tag zur Standard-Cluster-Sicherheitsgruppe hinzu. Dadurch können unsere CPU- und GPU-EC2NodeClass-Selektoren es verwenden:
aws ec2 create-tags --resources ${CLUSTER_SG_ID} --tags Key=karpenter.sh/discovery,Value=${EKS_CLUSTER_NAME}
Überprüfen Sie, ob das Tag hinzugefügt wurde:
aws ec2 describe-security-groups --group-ids ${CLUSTER_SG_ID} --query "SecurityGroups[].Tags"
Unter den Ergebnissen sollten Sie Folgendes mit dem Tag und Ihrem Cluster-Namen sehen. Zum Beispiel:
{ "Key": "karpenter.sh/discovery", "Value": "eks-rt-inference-us-east-1" }
Einrichtung des AWS Load Balancer Controller (LBC)
Der AWS LBC ist für die Verwaltung des eingehenden Datenverkehrs zu AI/ML-Workloads auf Amazon EKS unerlässlich und gewährleistet den Zugriff auf Inferenz-Endpunkte oder Datenverarbeitungs-Pipelines. Durch die Integration mit AWS Application Load Balancers (ALB) und Network Load Balancers (NLB) leitet der LBC den Datenverkehr dynamisch an containerisierte Anwendungen weiter, beispielsweise solche, die große Sprachmodelle, Computer-Vision-Modelle oder Echtzeit- Inferenz-Services ausführen. Da wir das Servicekonto und die Pod-Identity-Zuordnung bereits bei der Erstellung des Clusters erstellt haben, legen wir den serviceAccount.name so fest, dass er mit der Definition in unserer Cluster-Konfiguration übereinstimmt (aws-load-balancer-controller).
Fügen Sie das Helm-Chart-Repository eks-charts von AWS hinzu:
helm repo add eks https://aws.github.io/eks-charts
Aktualisieren Sie Ihre lokalen Helm-Repositorys mit den neuesten Diagrammen:
helm repo update eks
Stellen Sie den AWS LBC mithilfe von Helm bereit, geben Sie den Namen des EKS-Clusters an und verweisen Sie auf das zuvor erstellte Servicekonto:
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
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
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!
Einbinden des Modells in ein persistentes Volume
In diesem Schritt binden Sie Modellgewichte aus Ihrem Amazon-S3-Bucket mithilfe eines PersistentVolume (PV) ein, das vom CSI-Treiber für Mountpoint für Amazon S3 unterstützt wird. Dadurch können Kubernetes-Pods auf S3-Objekte als lokale Dateien zugreifen, wodurch ressourcenintensive Downloads in flüchtige Pod-Speicher oder Init-Container vermieden werden – ideal für große Modellgewichte mit mehreren Gigabyte.
Die PV bindet die gesamte Bucket-Root ein (kein Pfad in volumeAttributes angegeben), unterstützt den gleichzeitigen Lesezugriff durch mehrere Pods und macht Dateien wie die Modellgewichte (/models/gpunet-0.pth) innerhalb des Containers für die Inferenz verfügbar. Dadurch wird sichergestellt, dass der Fallback-„Download“ in unserer Anwendung (app.py) nicht ausgelöst wird, da die Datei über das Mount vorhanden ist. Durch die Entkopplung des Modells vom Container-Image werden der gemeinsame Zugriff und unabhängige Modellversionsaktualisierungen ohne Image-Neuerstellung ermöglicht.
Erstellen von PersistentVolume (PV)
Erstellen Sie eine PersistentVolume (PV)-Ressource, um den S3-Bucket mit Ihren Modellgewichten einzubinden, und ermöglichen Sie so mehreren Pods den schreibgeschützten Zugriff, ohne dass Dateien zur Laufzeit heruntergeladen werden müssen:
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
Erstellen von PersistentVolumeClaim (PVC)
Erstellen Sie einen PersistentVolumeClaim (PVC), um eine Bindung an den PV herzustellen, und fordern Sie schreibgeschützten Zugriff auf die eingebundenen S3-Modelldaten an:
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
Bereitstellen der Anwendung
Stellen Sie die Inferenz-Anwendung als Kubernetes-Bereitstellung bereit, indem Sie das S3-gestützte persistente Volume für den Modellzugriff mounten, GPU-Knotenselektoren und Toleranzen anwenden und Umgebungsvariablen für den Modellpfad festlegen. Diese Bereitstellung legt den Modellpfad (Umgebungsvariable von "/models/gpunet-0.pth") fest, sodass unsere Anwendung (in app.py) standardmäßig diesen Pfad verwendet Wenn das Volume der Bereitstellung in /models (schreibgeschützt) eingebunden ist, wird der Modell-Download nicht ausgelöst, wenn die Datei bereits über das PVC vorhanden ist.
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
Es kann einige Minuten dauern, bis Karpenter einen GPU-Knoten bereitstellt, falls noch keiner verfügbar ist. Überprüfen Sie, ob sich der Inferenz-Pod im Status „Ausgeführt“ befindet:
kubectl get pods -l app=gpunet-inference-app
Die erwartete Ausgabe sollte in etwa wie folgt aussehen:
NAME READY STATUS RESTARTS AGE gpunet-inference-app-5d4b6c7f8-abcde 1/1 Running 0 2m
Service mit Ingress und Load Balancer verfügbar machen
Erstellen Sie einen ClusterIP- Service, um die Inferenz-Bereitstellung intern innerhalb des EKS-Clusters freizugeben, wobei Sie den Port der Anwendung als Ziel angeben:
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
Erstellen Sie eine Ingress-Ressource, um über den AWS-LBC einen mit dem Internet verbundenen Application Load Balancer (ALB) bereitzustellen, der den externen Datenverkehr zum Inferenz-Service weiterleitet:
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
Warten Sie einige Minuten, bis der Application Load Balancer (ALB) die Bereitstellung abgeschlossen hat. Überwachen Sie den Status der Ingress-Ressource, um sicherzustellen, dass der ALB bereitgestellt wurde:
kubectl get ingress gpunet-model-ingress
Die erwartete Ausgabe sollte wie folgt aussehen (mit ausgefülltem Feld ADRESSE):
NAME CLASS HOSTS ADDRESS PORTS AGE gpunet-model-ingress alb * k8s-default-gpunetmo-183de3f819-516310036.us-east-1.elb.amazonaws.com 80 6m58s
Extrahieren und exportieren Sie den ALB-Host-Namen aus dem Ingress-Status zur Verwendung in nachfolgenden Tests:
export ALB_HOSTNAME=$(kubectl get ingress gpunet-model-ingress -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
Modell-Service testen
Validieren Sie den freigegebenen Inferenzendpunkt, indem Sie eine POST-Anfrage mit einer Beispielbild-URL (z. B. aus dem COCO-Datensatz) senden und so eine Echtzeit-Prognose simulieren:
curl -X POST "http://${ALB_HOSTNAME}/predict?image_url=http://images.cocodataset.org/test-stuff2017/000000024309.jpg"
Die erwartete Ausgabe sollte eine JSON-Antwort mit den fünf besten Prognosen sein, ähnlich wie hier (die tatsächlichen Bezeichnungen und Wahrscheinlichkeiten können je nach Image und Modellgenauigkeit leicht variieren):
{"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}]}
Optional können Sie in einer neuen POST-Anfrage mit dem Testen anderer Images fortfahren. Zum Beispiel:
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
Schlussfolgerung
In diesem Handbuch richten Sie einen Amazon-EKS-Cluster ein, der für GPU-beschleunigte Echtzeit-Inferenz-Workloads optimiert ist. Sie haben einen Cluster mit G5-EC2-Instances
Bereinigen
Um zukünftige Kosten zu vermeiden, müssen Sie den zugehörigen CloudFormation-Stack manuell löschen, um alle in dieser Anleitung erstellten Ressourcen, einschließlich des VPC-Netzwerks, zu entfernen.
Löschen Sie den CloudFormation-Stack mithilfe des --wait-Flags mit eksctl:
eksctl delete cluster --region ${AWS_REGION} --name ${EKS_CLUSTER_NAME} --wait
Nach Abschluss des Vorgangs sollte die folgende Antwort angezeigt werden:
2025-07-29 13:03:55 [✔] all cluster resources were deleted
Löschen Sie den in dieser Anleitung erstellten Amazon-S3-Bucket mithilfe der Amazon-S3-Konsole