Leitfaden für bewährte Methoden zur Cluster-Einrichtung für Echtzeit-Inferenz in Amazon EKS - Amazon EKS

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-Vorlage. Durch die Initialisierung des Clusters ausschließlich mit CPU-Knoten können wir Karpenter ausschließlich zur Verwaltung von CPU-intensiven und GPU-Knoten verwenden, um die Ressourcenzuweisung mithilfe von Karpenter NodePools zu optimieren, die wir in späteren Schritten erstellen werden. Zur Unterstützung unserer Echtzeit-Inferenz-Workloads stellen wir den Cluster mit EKS Bottlerocket-AMI, EKS-Knoten-Überwachungsagent, EKS Pod Identity Agent, Mountpoint-S3-CSI-Treiber, AWS Load Balancer Controller (LBC) sowie den Treibern kube-proxy, vpc-cni und coredns bereit. Die m7g.xlarge-Instances werden für CPU-Systemaufgaben verwendet, darunter das Hosting des Karpenter-Controllers, Add-Ons und anderer Systemkomponenten.

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 und Kubernetes-Version.

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

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

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 NodePools. Das Feld limits 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, Kapazitätstypen und Ressourcenbeschränkungen angeben. In diesen NodePools setzen wir eine Vielzahl von Instance-Typen innerhalb der G5-Instance-Familie ein. Dadurch kann Karpenter automatisch den am besten geeigneten Instance-Typ basierend auf den Pod-Ressourcenanforderungen auswählen und so die Ressourcennutzung optimieren, während die Gesamtgrenzen des NodePools eingehalten werden. Weitere Informationen finden Sie unter Erstellung von NodePools.

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 Unterbrechungsrichtlinie fest, um leere Knoten nach 30 Minuten (consolidateAfter: 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 Unterbrechungsrichtlinie fest, um leere Knoten nach 60 Minuten (consolidateAfter: 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, das Teil von NVIDIAs GPUNet ist und die Inferenz mit geringer Latenz für Images mithilfe von NVIDIA-GPUs und TensorRT unterstützt. Dieses Modell wurde in ImageNet vorab trainiert, ermöglicht die Klassifizierung von Objekten in Fotos oder Videostreams in Echtzeit und gilt mit 11,9 Millionen Parametern als kleines Modell.

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, das auf Ihrem lokalen Rechner installiert sein muss. Befolgen Sie die folgenden Schritte, um ein kostenloses Konto einzurichten und die NGC-CLI zu konfigurieren:

  • 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“ auf nvidia und 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 in der AWS-CLI, um den S3-Durchsatz zu optimieren:

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 bereitgestellt und den Mountpoint-S3-CSI-Treiber, den EKS Pod Identity Agent, den EKS-Knoten-Überwachungsagent, Bottlerocket-AMI, den AWS Load Balancer Controller (LBC) und Karpenter installiert, um CPU- und GPU-Knoten-Pools zu verwalten. Sie haben das NVIDIA-Geräte-Plugin verwendet, um die GPU-Planung zu aktivieren, und S3 mit einem PersistentVolume und einem PersistentVolumeClaim für den Modellzugriff konfiguriert. Sie haben die Einrichtung validiert, indem Sie einen Beispiel-GPU-Pod bereitgestellt, den Modellzugriff für das NVIDIA-GPUNet-0-Modell in Amazon S3 eingerichtet, die Pod-Initialisierung aktiviert und den Inferenz-Service über Application Load Balancer verfügbar gemacht haben. Um Ihr Cluster optimal zu nutzen, konfigurieren Sie den EKS-Knoten-Überwachungsagent mit automatischer Reparatur. Führen Sie unbedingt Benchmark-Tests durch, einschließlich Bewertungen der GPU-Leistung, Latenz und des Durchsatzes, um die Reaktionszeiten zu optimieren. Weitere Informationen finden Sie unter Verwendung von Überwachungs- und Beobachtbarkeitstools für Ihre KI-/ML-Workloads.

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.