Leitfaden zur Clustereinrichtung mit bewährten Methoden für Echtzeit-Inferenz auf Amazon EKS - Amazon EKS

Hilf mit, diese Seite zu verbessern

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Wenn Sie zu diesem Benutzerhandbuch beitragen möchten, wählen Sie den GitHub Link Diese Seite bearbeiten auf, der sich im rechten Bereich jeder Seite befindet.

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Leitfaden zur Clustereinrichtung mit bewährten Methoden für Echtzeit-Inferenz auf Amazon EKS

Einführung

Dieser Leitfaden bietet eine praktische Anleitung zur Einrichtung eines Amazon Elastic Kubernetes Service (EKS) -Clusters, der für Online-Inferenz-Workloads in Echtzeit optimiert ist, und beinhaltet durchweg von Experten kuratierte Best Practices. AWS Es verwendet eine eigenwillige EKS-Schnellstart-Architektur — eine kuratierte Zusammenstellung von Treibern, Instance-Typen und Konfigurationen, die auf bewährte Methoden für Modelle, Beschleuniger und Skalierung abgestimmt sind. AWS Dieser Ansatz hilft Ihnen, die Aufgabe der Auswahl von Clustereinstellungen zu umgehen, sodass Sie schnell einen funktionierenden, vorkonfigurierten Cluster einrichten und zum Laufen bringen können. Unterwegs stellen wir Beispiel-Workloads bereit, um Ihr Setup zu validieren, erklären wichtige Architekturkonzepte (wie die Entkopplung CPU-gebundener Aufgaben von GPU-intensiven Berechnungen) und gehen auf häufig gestellte Fragen ein (z. B. warum sollten Sie Bottlerocket AMI anstelle von 023 wählen?) AL2 und skizzieren die nächsten Schritte zur Erweiterung der Funktionen Ihres Clusters.

Dieser Leitfaden wurde speziell für Ingenieure, Plattformadministratoren, Betreiber und data/AI Spezialisten für Machine Learning (ML) und künstliche Intelligenz (KI) entwickelt AWS und setzt Vertrautheit mit Kubernetes voraus, jedoch keine EKS-Vorkenntnisse. Es soll Ihnen helfen, die Schritte und Prozesse zu verstehen, die erforderlich sind, um Online-Inferenz-Workloads in Echtzeit zum Laufen zu bringen. Der Leitfaden zeigt Ihnen die Grundlagen der Erstellung eines Inferenzclusters mit einem Knoten, einschließlich der Bereitstellung von GPU-Ressourcen, der Integration von Speicher für Modellartefakte, der Bereitstellung eines sicheren AWS Servicezugriffs und der Offenlegung von Inferenzendpunkten. Der Schwerpunkt liegt durchweg auf einem robusten Design mit niedriger Latenz für benutzerorientierte Anwendungen wie Betrugserkennung, Echtzeit-Chatbots und Stimmungsanalysen in Kundenfeedbacksystemen.

In diesem Leitfaden konzentrieren wir uns ausschließlich auf die Einrichtung eines grundlegenden, präskriptiven Ausgangspunkts mithilfe von G5-Instances. EC2 Wenn Sie nach AWS Inferentia-spezifischen Cluster-Konfigurationen oder end-to-end Workflows suchen, finden Sie unsere Workshops unter. Verwenden Sie AWS Inferentia-Instances mit Amazon EKS für Machine Learning Ressourcen für den Einstieg in AI/ML Amazon EKS

Bevor Sie beginnen

Bevor Sie beginnen, stellen Sie sicher, dass Sie die folgenden Aufgaben ausgeführt haben:

Architektur

Online-Inferenz in Echtzeit bezieht sich auf den Prozess, bei dem mithilfe eines trainierten Modells für maschinelles Lernen Vorhersagen oder Ausgaben für eingehende Datenströme mit minimaler Latenz generiert werden. Es ermöglicht beispielsweise die Betrugserkennung in Echtzeit, die Klassifizierung von Bildern oder die Erstellung von Wissensgraphen als Reaktion auf Benutzereingaben. Die Architektur eines Online-Inferenzsystems in Echtzeit ermöglicht Vorhersagen für maschinelles Lernen mit geringer Latenz in benutzerorientierten Anwendungen, indem die Verarbeitung von CPU-gebundenem Web-Traffic von GPU-intensiven KI-Berechnungen entkoppelt wird. Dieser Prozess findet in der Regel in einem größeren Anwendungsökosystem statt und umfasst häufig Backend-, Frontend-, Vektor- und Modellservices, wobei der Schwerpunkt auf speziellen Komponenten liegt, die eine unabhängige Skalierung, parallel Entwicklung und Ausfallsicherheit ermöglichen. Durch die Isolierung von Inferenzaufgaben auf dedizierter GPU-Hardware und die Nutzung von Schnittstellen wie z. B. APIs WebSockets eine hohe Parallelität, eine schnelle Verarbeitung von Modellen wie Transformatoren und Benutzerinteraktionen über das Frontend wird gewährleistet. Beachten Sie, dass Vektordatenbanken und RAG-Pipelines (Retrieval Augmented Generation) zwar häufig eine große Rolle in Echtzeit-Inferenzsystemen spielen, diese Komponenten jedoch in diesem Handbuch nicht behandelt werden. Eine typische Architektur umfasst häufig mindestens:

  • Frontend-Dienst: Dient als Benutzerschnittstelle, verarbeitet die clientseitige Logik, rendert dynamische Inhalte und erleichtert Interaktionen in Echtzeit. Er kommuniziert mit dem Backend-Service, um Inferenzanfragen zu initiieren und Ergebnisse anzuzeigen. Dabei werden häufig Anfragen an den Backend-Service gestellt, der für Streaming-Updates oder für den strukturierten Datenaustausch verwendet WebSockets wird. APIs Für diesen Dienst ist in der Regel kein dedizierter Load Balancer erforderlich, da er in Content Delivery Networks (CDNs) gehostet werden kann, z. B. AWS CloudFront für statische Ressourcen, oder direkt von Webservern aus bereitgestellt werden kann, wobei die Skalierung bei Bedarf für dynamische Inhalte über Gruppen mit auto-scaling erfolgt.

  • Backend-Service: fungiert als Orchestrator der Anwendung und verwaltet die Geschäftslogik wie Benutzerauthentifizierung, Datenvalidierung und Dienstkoordination (z. B. über APIs für RESTful Endpunkte oder WebSockets für persistente Verbindungen). Es kommuniziert mit dem Inferenzdienst, skaliert unabhängig auf Multi-Core CPUs und RAM, um hohen Webverkehr zu bewältigen, ohne darauf angewiesen zu sein GPUs, und benötigt häufig einen Load Balancer (wie AWS Application Load Balancer oder Network Load Balancer), um eingehende Anfragen auf mehrere Instanzen zu verteilen, insbesondere in Szenarien mit hoher Parallelität. Ein Ingress-Controller kann externe Zugriffs- und Routing-Regeln für mehr Sicherheit und Traffic-Shaping weiter verwalten.

  • Inference Service: Dient als Kern für KI-Berechnungen und läuft GPUs mit ausreichend VRAM (z. B. 8-12 GB für Modelle wie DistilBert), um Vektoreinbettungen, Wissensextraktion und Modellinferenz (z. B. verfügbar APIs für Batch-Anfragen oder für Echtzeit-Streaming) mithilfe benutzerdefinierter Modelle oder WebSockets Open-Source-Modelle durchzuführen. Diese Isolierung verhindert Abhängigkeitskonflikte, ermöglicht Modellaktualisierungen ohne Ausfallzeiten und ermöglicht eine horizontale Skalierung mit Lastenausgleich für mehrere gleichzeitige Anfragen. Um den Modelldienst effektiv verfügbar zu machen, befindet er sich in der Regel hinter einem Load Balancer, um GPU-gebundene Workloads auf replizierte Instanzen zu verteilen, während eine Eingangsressource oder ein Controller (z. B. der ALB Ingress Controller in AWS) das externe Routing, die SSL-Terminierung und die pfadbasierte Weiterleitung übernimmt, um einen sicheren und effizienten Zugriff zu gewährleisten, ohne einzelne Personen zu überfordern. GPUs

Übersicht über die Lösung

Online-Inferenzsysteme in Echtzeit erfordern eine leistungsstarke, belastbare Architektur, die extrem niedrige Latenz bietet und gleichzeitig unvorhersehbare Datenfluten mit hohem Datenvolumen bewältigen kann. In dieser Lösungsübersicht wird erklärt, wie die folgenden AWS Komponenten in dem Amazon EKS-Cluster zusammenarbeiten, den wir erstellen werden, um sicherzustellen, dass unser Cluster Modelle für maschinelles Lernen hosten und verwalten kann, die sofortige Vorhersagen zu Live-Daten mit minimaler Verzögerung für Endbenutzer liefern.

  • Amazon EC2 G5-Instances — Für GPU-intensive Inferenzaufgaben verwenden wir die EC2 Instance-Typen g5.xlarge und g5.2xlarge G5, die über eine einzelne (1) NVIDIA A10G-GPU mit 24 GB Arbeitsspeicher verfügen (z. B. 8 Milliarden Parameter bei). FP16 Diese basieren auf der NVIDIA Ampere-Architektur und GPUs 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, was eine schnelle Datenbewegung und Rechenleistung für komplexe Modelle gewährleistet und sie somit ideal für Inferenzaufgaben mit niedriger Latenz und hohem Durchsatz macht. Die Auswahl eines EC2 Instance-Typs ist anwendungsspezifisch und hängt von Ihrem Modell (z. B. Bild-, Video-, Textmodell) und Ihren Latenz- und Durchsatzanforderungen ab. Wenn Sie beispielsweise ein Bild- und/oder Videomodell verwenden, möchten Sie möglicherweise EC2 P5-Instances verwenden, um eine optimale Latenz in Echtzeit zu erzielen. Wir empfehlen, mit EC2 G5-Instances zu beginnen, da dies einen guten Ausgangspunkt für eine schnelle Inbetriebnahme bietet. Anschließend können Sie anhand von Performance-Benchmark-Tests beurteilen, ob sie für Ihre Workloads geeignet sind. Für fortgeschrittenere Fälle sollten Sie EC2 G6-Instances in Betracht ziehen.

  • Amazon EC2 M7g-Instances — Für CPU-intensive Aufgaben wie Datenvorverarbeitung, Bearbeitung von API-Anfragen, Hosten des Karpenter Controllers, Add-Ons und anderer Systemkomponenten verwenden wir den Instance-Typ m5.xlarge M7g. EC2 M7g-Instances sind ARM-basierte Instances, die über 4 V, 16 GB Arbeitsspeicher und bis zu 12,5 Gbit/s Netzwerkbandbreite verfügen CPUs und von Graviton3-Prozessoren angetrieben werden. AWS Die Auswahl eines EC2 Instance-Typs ist anwendungsspezifisch und hängt von den Rechen-, Speicher- und Skalierbarkeitsanforderungen Ihres Workloads ab. Für rechenoptimierte Workloads könnten Sie EC2 C7g-Instances in Betracht ziehen, die ebenfalls Graviton3-Prozessoren verwenden, aber für bestimmte Anwendungsfälle für eine höhere Rechenleistung als M7g-Instances optimiert sind. Alternativ bieten neuere EC2 C8g-Instances (sofern verfügbar) eine bis zu 30% bessere Rechenleistung als C7g-Instances. Wir empfehlen, mit EC2 M7g-Instances zu beginnen, da sie kosteneffizient sind und mit einer Vielzahl von Workloads kompatibel sind (z. B. Anwendungsserver, Microservices, Gaming-Server, Datenspeicher mittlerer Größe). Anschließend sollten Sie anhand von Leistungsbenchmarktests prüfen, ob sie für Ihre Workloads geeignet sind.

  • Amazon S3 Mountpoint CSI-Treiber — Für Workloads auf Single-GPU-Instances, bei denen sich mehrere Pods eine GPU teilen (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 — unverzichtbar für Aufgaben wie Inferenz großer Modelle in kostensensitiven Setups mit geringer Komplexität. Es stellt Amazon S3 S3-Buckets als POSIX-ähnliches Dateisystem zur Verfügung, das dem Kubernetes-Cluster zur Verfügung steht. Dadurch können Inferenz-Pods Modellartefakte (z. B. Modellgewichte) direkt in den Speicher lesen, ohne sie zuerst herunterladen zu müssen, und Datensätze mithilfe von Standarddateioperationen 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 Durchsatz- und Latenzanforderungen Ihres Workloads ab. Obwohl der FSx für OpenZFS CSI Driver eine Latenz von unter einer Millisekunde für zufällige I/O oder vollständig POSIX-konforme, knotenübergreifende gemeinsame persistente Volumes bietet, empfehlen wir, mit dem Mountpoint S3 CSI-Treiber zu beginnen, da er Skalierbarkeit, geringere Kosten für große Datensätze und integrierte Integration mit S3-verwaltetem Objektspeicher für leseintensive Inferenzmuster (z. B. Streaming-Modelleingaben) bietet, und dann anhand von Performance-Benchmark-Tests zu prüfen, ob er für Ihre Workloads geeignet ist.

  • EKS Pod Identity Agent — Um den Zugriff auf AWS Dienste zu ermöglichen, verwenden wir den EKS Pod Identity Agent, der einen einzigen Dienstprinzipal verwendet und IAM-Rollenzuordnungen auf Pod-Ebene innerhalb des Amazon EKS-Clusters ermöglicht. EKS Pod Identity bietet eine optimierte Alternative zum herkömmlichen IRSA-Ansatz (IAM Roles for Service Accounts), indem ein einziger Dienstprinzipal (pods.eks.amazonaws.com) verwendet wird, anstatt sich auf einzelne OIDC-Anbieter für jeden Cluster zu verlassen, was die Zuweisung von Berechtigungen erleichtert. Darüber hinaus ermöglicht es die Wiederverwendung von Rollen in mehreren Clustern und unterstützt erweiterte Funktionen wie IAM-Rollensitzungs-Tags und Target-IAM-Rollen.

  • EKS Node Monitoring Agent — Um die kontinuierliche Verfügbarkeit und Zuverlässigkeit der Inferenzdienste zu gewährleisten, verwenden wir den EKS Node Monitoring Agent with Auto Repair, der fehlerhafte Knoten automatisch erkennt und ersetzt und so Ausfallzeiten minimiert. Er überwacht Knoten kontinuierlich auf Hardware-, Kernel-, Netzwerk- und Speicherprobleme mithilfe erweiterter Integritätsprüfungen (z. B., KernelReady). NetworkingReady Bei GPU-Knoten erkennt es beschleunigerspezifische Fehler und leitet eine reibungslose Behebung ein, indem fehlerhafte Knoten gesperrt werden, 10 Minuten auf die Behebung vorübergehender GPU-Probleme gewartet und Knoten nach 30 Minuten bei dauerhaften Ausfällen ersetzt werden.

  • Bottlerocket AMI — Um eine sichere Grundlage für unseren EKS-Cluster bereitzustellen, verwenden wir das Bottlerocket AMI, das nur die wesentlichen Komponenten enthält, die für den Betrieb von Containern erforderlich sind, und minimale Startzeiten für eine schnelle Skalierung bietet. Die Auswahl eines Node-AMI ist anwendungsspezifisch und hängt von den Anpassungs-, Sicherheits- und Skalierbarkeitsanforderungen Ihres Workloads ab. Obwohl das AL2023 AMI mehr Flexibilität für Installationen und Anpassungen auf Host-Ebene bietet (z. B. die Angabe eines dedizierten Cache-Verzeichnisses in einer Konfiguration PV/PVC ohne zusätzliche Knoten), empfehlen wir, mit dem Bottlerocket-AMI zu beginnen, da es einen geringeren Platzbedarf hat und die integrierte Optimierung für containerisierte Workloads (z. B. Microservices, Inferenzserver, skalierbar APIs) bietet, und dann anhand von Performance-Benchmark-Tests zu prüfen, ob es für Ihre Workloads geeignet ist.

  • AWS Load Balancer Controller (LBC) — Um Inferenzendpunkte in Echtzeit verfügbar zu machen, verwenden wir den Load AWS Balancer Controller, der automatisch Application Load Balancer () für Traffic und Network Load Balancer (ALBs) für HTTP/HTTPS Traffic auf Basis von Kubernetes Ingress- und Service-Ressourcen bereitstellt und verwaltet und so die Integration von Inferenzmodellen mit externen Clients ermöglicht. NLBs TCP/UDP Darüber hinaus unterstützt es Funktionen wie pfadbasiertes Routing zur Verteilung von Inferenzanfragen auf mehrere Pods oder Knoten, wodurch die Skalierbarkeit bei Verkehrsspitzen gewährleistet und die Latenz durch AWS native Optimierungen wie Verbindungsmultiplexing und Integritätsprüfungen minimiert wird.

1. Erstellen Sie Ihren EKS-Cluster

In diesem Schritt erstellen wir mithilfe einer AWS CloudFormation ClusterConfigeksctl-Vorlage einen Cluster mit CPU-Knoten und einer verwalteten Knotengruppe. Durch die Initialisierung des Clusters nur mit CPU-Knoten können wir Karpenter ausschließlich zur Verwaltung von CPU-intensiven Knoten und GPU-Knoten verwenden, um die Ressourcenzuweisung mithilfe von Karpenter zu optimieren, das wir in späteren Schritten erstellen. NodePools Zur Unterstützung unserer Echtzeit-Inferenz-Workloads stellen wir den Cluster mit dem EKS Bottlerocket AMI, dem EKS Node Monitoring Agent, dem EKS Pod Identity Agent, dem Mountpoint S3 CSI Driver, dem Load AWS Balancer Controller (LBC) und den Treibern kube-proxy, vpc-cni und coredns bereit. Die m7g.xlarge-Instances werden für CPU-Systemaufgaben verwendet, einschließlich des Hostings des Karpenter Controllers, Add-Ons und anderer Systemkomponenten.

Standardmäßig eksctl wird eine dedizierte VPC für den Cluster mit einem CIDR-Block von erstellt. 192.168.0.0/16 Die VPC umfasst drei öffentliche Subnetze 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 für die Bereitstellung von Kubernetes-Workloads. Die Vorlage stellt außerdem ein Internet-Gateway bereit, das den Internetzugang zu den öffentlichen Subnetzen über Standardrouten in ihren Routing-Tabellen und ein einzelnes NAT-Gateway in einem der öffentlichen Subnetze ermöglicht, wobei Standardrouten in den Routing-Tabellen der privaten Subnetze den ausgehenden Verkehr über das NAT-Gateway für den Internetzugang leiten. Weitere Informationen zu diesem Setup finden Sie unter Bereitstellen von Knoten in privaten Subnetzen.

Überprüfen Sie Ihre Anmeldedaten

Prüfen Sie, ob Ihre AWS CLI-Anmeldeinformationen gültig sind und sich bei AWS Diensten authentifizieren können:

aws sts get-caller-identity

Bei Erfolg gibt die CLI Details zu Ihrer AWS Identität (UserId, Ihrem Konto und Ihrem ARN) zurück.

Überprüfen Sie die Verfügbarkeit der Instanz

G5-Instance-Typen sind nicht in allen Regionen verfügbar. Überprüfen Sie die Region in Ihrer Nähe. 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.

Bereiten Sie Ihre Umgebung vor

Stellen Sie zunächst die folgenden Umgebungsvariablen in einem neuen Terminalfenster ein. Hinweis: Achten Sie darauf, die Beispiel-Platzhalter durch Ihre eindeutigen Werte zu ersetzen, einschließlich Clustername, gewünschte Region, Karpenter Release-Version und Kubernetes-Version.

Tipp

Einige Variablen (wie ${AWS_REGION} und${K8S_VERSION}) werden zu Beginn des Blocks definiert und dann aus Gründen der Konsistenz und zur Vermeidung von Wiederholungen in späteren Befehlen referenziert. Stellen Sie sicher, dass Sie die Befehle nacheinander ausführen, damit diese Werte ordnungsgemäß exportiert werden und in nachfolgenden Definitionen verwendet werden können.

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/')"

Erstellen Sie die erforderlichen Rollen und Richtlinien

Karpenter benötigt spezielle IAM-Rollen und -Richtlinien (z. B. die IAM-Rolle des Karpenter Controllers, das Instanzprofil und die Richtlinien), um Instanzen als Kubernetes-Worker-Knoten zu verwalten EC2 . Es verwendet diese Rollen, um Aktionen wie das Starten und Beenden von EC2 Instanzen, das Markieren von Ressourcen und die Interaktion mit anderen Diensten auszuführen. AWS Erstellen Sie die Rollen und Richtlinien von Karpenter mithilfe von 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}"

Das AWS LBC benötigt die Erlaubnis, AWS Load Balancer bereitzustellen und zu verwalten, z. B. zum Erstellen von Ingress-Ressourcen oder für Dienste vom Typ. ALBs NLBs LoadBalancer Wir geben diese Berechtigungsrichtlinie bei der Clustererstellung an. Während der Clustererstellung erstellen wir das Dienstkonto mit eksctl im. 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, sind seine DaemonSet Pods so konfiguriert, dass sie ein Dienstkonto für die Ausführung verwenden. Der Mountpoint for Mountpoint S3 CSI-Treiber benötigt die Erlaubnis, mit dem Amazon S3 S3-Bucket zu interagieren, den Sie später in diesem Handbuch erstellen. Wir werden diese Berechtigungsrichtlinie bei der Clustererstellung angeben. Während der Clustererstellung erstellen wir das Dienstkonto mit eksctl im. 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: Wenn bereits eine Rolle mit diesem Namen existiert, geben Sie der Rolle einen anderen Namen. 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-Dienstkonto für EKS Pod Identity, Node Monitoring Agent, CoreDNS, Kubeproxy und das VPC CNI Plugin. Ab heute ist der Mountpoint S3 CSI-Treiber nicht für EKS Pod Identity verfügbar. Daher erstellen wir ein IAM-Rollen für das Dienstkonto (IRSA) und einen OIDC-Endpunkt. Darüber hinaus erstellen wir ein Dienstkonto für den Load AWS Balancer Controller (LBC). Für den Zugriff auf Bottlerocket-Knoten hängt eksctl automatisch Amazon SSMManaged InstanceCore for Bottlerocket an, um sichere Shell-Sitzungen über SSM zu ermöglichen.

Führen Sie im selben 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, schauen Sie in der AWS CloudFormationKonsole nach.

2. Überprüfen Sie den Health des Clusterknotens und des Pods

Lassen Sie uns einige Integritätsprüfungen durchführen, um sicherzustellen, dass der Cluster bereit ist. Wenn der vorherige Befehl abgeschlossen ist, sehen Sie sich 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 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 mit dem folgenden Befehl alle Pod Identity-Verknüpfungen und wie sie einem Dienstkonto in einem Namespace im Cluster eine Rolle zuordnen:

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

Die Ausgabe sollte die IAM-Rollen für Karpenter („karpenter“) und LBC (“ „) enthalten. AWS aws-load-balancer-controller

Stellen Sie sicher, dass sie verfügbar sind: DaemonSets

kubectl get daemonsets -n kube-system

Die erwartete Ausgabe sollte 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

Stellen Sie sicher, dass alle Addons auf dem Cluster installiert sind:

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

Die erwartete Ausgabe sollte 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. Installiere Karpenter

Installieren Sie den Karpenter Controller auf Ihren CPU-Worker-Knoten (cpu-worker), um die Kosten zu optimieren und GPU-Ressourcen zu schonen. Wir werden ihn im Namespace „kube-system“ installieren und das Dienstkonto „Karpenter“ angeben, das wir bei der Clustererstellung definiert haben. Darüber hinaus konfiguriert dieser Befehl den Clusternamen und eine Spot-Instance-Unterbrechungswarteschlange 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 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

Stellen Sie sicher, dass Karpenter läuft:

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

Die erwartete Ausgabe sollte 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. Richten Sie Karpenter ein NodePools

In diesem Schritt konfigurieren wir die sich gegenseitig ausschließende CPU- und GPU-Karpenter. NodePools Das limits Feld in der NodePool Spezifikation schränkt die maximalen Gesamtressourcen (z. B. CPU, Speicher GPUs) ein, die jeder für alle bereitgestellten Knoten verbrauchen NodePool kann. Dadurch wird verhindert, dass zusätzliche Knoten bereitgestellt werden, wenn diese Grenzwerte überschritten werden. NodePools Unterstützt zwar breite Instanzkategorien (z. B.,g)c, aber die Angabe bestimmter Instanztypen, Kapazitätstypen und Ressourcenlimits hilft Ihnen dabei, die Kosten für Ihre On-Demand-Workloads einfacher abzuschätzen. In diesen NodePools Fällen verwenden wir eine Vielzahl von Instance-Typen innerhalb der G5-Instance-Familie. Auf diese Weise kann Karpenter auf der Grundlage von Pod-Ressourcenanfragen automatisch den am besten geeigneten Instanztyp auswählen, wodurch die Ressourcennutzung optimiert und gleichzeitig die NodePool Gesamtlimits eingehalten werden. Weitere Informationen finden Sie unter Erstellen. NodePools

Richten Sie die GPU ein NodePool

Darin legen wir Ressourcenlimits fest NodePool, um die Bereitstellung von Knoten mit GPU-Fähigkeiten zu verwalten. Diese Grenzwerte dienen dazu, die Gesamtressourcen auf allen Knoten im Pool zu begrenzen, sodass insgesamt bis zu 10 Instanzen möglich sind. Jede Instanz kann entweder g5.xlarge (4 VCPUs, 16 GiB Arbeitsspeicher, 1 GPU) oder g5.2xlarge (8 VCPUs, 32 GiB Speicher, 1 GPU) sein, solange die Summe v 80 CPUs nicht überschreitet, der Gesamtspeicher 320 GiB nicht überschreitet und die Summe 10 nicht überschreitet. GPUs Der Pool kann beispielsweise 10 g5.2xlarge-Instances (80 vCPUs, 320 GiB, 10 GPUs) oder 10 g5.xlarge-Instances (40 v, 160 GiBCPUs, 10 GPUs) oder eine Mischung wie 5 g5.xlarge- und 5 g5.2xlarge (60 v, 240 GiB, 10 GPUs) bereitstellenCPUs, wodurch Flexibilität je nach Workload-Anforderungen gewährleistet und gleichzeitig Ressourcenbeschränkungen eingehalten werden.

Zusätzlich geben wir die ID der Nvidia-Variante des Bottlerocket AMI an. Schließlich haben wir eine Störungsrichtlinie festgelegt, um leere Knoten nach 30 Minuten (consolidateAfter: 30m) zu entfernen, und legen eine maximale Lebensdauer von Knoten von 30 Tagen (expireAfter: 720h) fest, um die Kosten zu optimieren und den Zustand der Knoten für GPU-intensive Aufgaben aufrechtzuerhalten. Weitere Informationen finden Sie unter Deaktivieren von Karpenter Consolidation für unterbrechungssensitive Workloads und Verwenden Sie ttlSecondsAfter Fertig, um Kubernetes-Jobs automatisch zu bereinigen.

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 wie folgt aussehen:

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

Stellen Sie sicher, NodePool dass das erstellt wurde und fehlerfrei ist:

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

Suchen Sie nach „status.conditionslike“ ValidationSucceeded: TrueNodeClassReady: True, und bestätigen Ready: True Sie, dass der NodePool fehlerfrei ist.

Richten Sie die CPU ein NodePool

Dabei NodePool haben wir Grenzwerte für die Unterstützung von etwa 50 Instances festgelegt, die auf eine moderate CPU-Arbeitslast (z. B. 100-200 Pods) und typische AWS vCPU-Kontingente (z. B. 128-1152) abgestimmt sind. Die Grenzwerte werden unter der Annahme berechnet, dass bis zu 50 m7.xlarge-Instances skaliert werden NodePool sollten: CPU (4 V CPUs pro Instanz × 50 Instanzen = 200 VCPUs) und Arbeitsspeicher (16 GiB pro Instanz × 50 Instanzen = 800 GiB). Diese Grenzwerte sind so konzipiert, dass sie die Gesamtressourcen auf allen Knoten im Pool begrenzen, sodass bis zu 50 m7g.xlarge-Instances (jeweils mit 4 V CPUs und 16 GiB Speicher) zulässig sind, sofern die Gesamt-V 200 CPUs nicht überschreiten und der Gesamtspeicher 800 GiB nicht überschreitet.

Zusätzlich geben wir die ID der Standardvariante des Bottlerocket AMI an. Schließlich haben wir eine Störungsrichtlinie festgelegt, nach der leere Knoten nach 60 Minuten (consolidateAfter: 60m) entfernt werden, und eine maximale Lebensdauer der Knoten von 30 Tagen (expireAfter: 720h) festgelegt, um die Kosten zu optimieren und den Zustand der Knoten für GPU-intensive Aufgaben aufrechtzuerhalten. Weitere Informationen finden Sie unter Deaktivieren von Karpenter Consolidation für unterbrechungssensitive Workloads und Verwenden Sie ttlSecondsAfter Fertig, um Kubernetes-Jobs automatisch zu bereinigen.

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 wie folgt aussehen:

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

Stellen Sie sicher, NodePool dass das erstellt wurde und fehlerfrei ist:

kubectl get nodepool cpu-inference-m7gxlarge -o yaml

Suchen Sie nach „status.conditionslike“ ValidationSucceeded: TrueNodeClassReady: True, und bestätigen Ready: True Sie, dass der NodePool fehlerfrei ist.

5. Stellen Sie einen GPU-Pod bereit, um eine GPU verfügbar zu machen

Sie benötigen das Nvidia-Geräte-Plugin, damit Kubernetes GPU-Geräte für den Kubernetes-Cluster verfügbar machen kann. In der Regel müssten Sie das Plug-in als DaemonSet bereitstellen. Das Bottlerocket-AMI installiert das Plugin jedoch als Teil des AMI vor. Das heißt, wenn Sie Bottlerocket verwenden AMIs, müssen Sie das Nvidia-Geräte-Plugin nicht bereitstellen. DaemonSet Weitere Informationen finden Sie unter Kubernetes Device Plugin to Expose. GPUs

Stellen Sie einen Beispiel-Pod bereit

Karpenter agiert dynamisch: Es stellt GPU-Knoten bereit, wenn ein Workload (Pod) GPU-Ressourcen anfordert. Um zu überprüfen, ob Pods angefordert und verwendet werden können GPUs, stellen Sie einen Pod bereit, der die nvidia.com/gpu Ressource innerhalb ihrer Grenzen anfordert (z. B.nvidia.com/gpu: 1). Weitere Informationen zu diesen Labels finden Sie unter Planen von Workloads mit GPU-Anforderungen mithilfe von bekannten Labels.

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 wie folgt aussehen:

pod/gpu-ndivia-smi created

Warten Sie eine Minute und überprüfen Sie dann, ob der Pod den Status „Ausstehend“ContainerCreating, „Wird ausgeführt“ und dann den Status „Abgeschlossen“ hat:

kubectl get pod gpu-nvidia-smi -w

Stellen Sie sicher, dass der Knoten für den Pod zur GPU gehört NodePool:

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

Die erwartete Ausgabe sollte wie folgt aussehen:

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

Überprüfe die Protokolle des Pods:

kubectl logs gpu-nvidia-smi

Die erwartete Ausgabe sollte 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) Modellartefakte für die Bereitstellung vorbereiten und hochladen

In diesem Schritt stellen Sie einen Modellservice für die Bildklassifizierung in Echtzeit bereit, beginnend mit dem Hochladen von Modellgewichten in einen Amazon S3 S3-Bucket. Zur Demonstration verwenden wir das Open-Source-Modell GPUNet-0 Vision von NVIDIA GPUNet, das Inferenzen mit niedriger Latenz auf Bildern mit NVIDIA und TensorRT unterstützt. GPUs Dieses Modell ist vortrainiert ImageNet, ermöglicht es uns, Objekte in Fotos oder Videostreams im Handumdrehen zu klassifizieren. Es gilt als kleines Modell mit 11,9 Millionen Parametern.

So richten Sie Ihre Umgebung ein

Um die Gewichte des Modells GPUNet -0 herunterzuladen In diesem Schritt benötigen Sie Zugriff auf den NGC-Katalog von NVIDIA und müssen Docker auf Ihrem lokalen Computer installiert sein. Gehen Sie wie folgt vor, um ein kostenloses Konto einzurichten und die NGC-CLI zu konfigurieren:

  • Eröffnen Sie ein kostenloses NGC-Konto und generieren Sie einen API-Schlüssel über das NGC-Dashboard (Benutzersymbol > Setup > 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. Stellen Sie org auf ein nvidia und drücken Sie die Eingabetaste, um die Standardeinstellungen für andere zu akzeptieren. Wenn das erfolgreich ist, solltest du etwas wie das Folgende sehen:Successfully saved NGC configuration to /Users/your-username/.ngc/config.

Überprüfen Sie die Berechtigungen des Dienstkontos

Bevor wir beginnen, überprüfen Sie die Berechtigungen des Kubernetes-Dienstkontos:

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

Bei der Clustererstellung haben wir die CSIDriver S3-Richtlinie an eine IAM-Rolle angehängt und das Dienstkonto mit Anmerkungen versehen („s3-“). csi-driver-sa Die Mountpoint S3 CSI-Treiber-Pods erben bei der Interaktion mit S3 die Berechtigungen der IAM-Rolle. Die erwartete Ausgabe sollte 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

Fügen Sie eine Toleranz hinzu

Der S3 CSI-Treiber wird DaemonSet auf allen Knoten als a ausgeführt. Pods verwenden den CSI-Treiber auf diesen Knoten, um S3-Volumes zu mounten. Damit es auch auf unseren GPU-Knoten, die Fehler aufweisen, einplanen kann, fügen Sie folgende Toleranzen hinzu: DaemonSet

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

Die erwartete Ausgabe sollte wie folgt aussehen:

daemonset.apps/s3-csi-node patched

Laden Sie Modellgewichte auf S3 hoch

In diesem Schritt erstellen Sie einen Amazon S3 S3-Bucket, laden die GPUNet -0 Modellgewichte von NVIDIA GPU Cloud (NGC) herunter und laden sie in den Bucket hoch. Unsere Anwendung greift zur Laufzeit auf diese Gewichte zu, um daraus Rückschlüsse ziehen zu können.

Erstellen Sie Ihren Amazon S3 S3-Bucket:

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

Aktivieren Sie die S3-Versionierung 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, nachdem sie nicht mehr aktuell sind, 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-Lifecycle-Konfigurationen.

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 Gewichte des Modells GPUNet -0 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 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 in späteren Schritten so um, dass sie der erwarteten Benennung in unserem Anwendungscode entspricht (es ist kein Extrahieren erforderlich, da es sich um einen standardmäßigen PyTorch *.pth.tar-Checkpoint handelt, der das Modellstatuswörterbuch enthält):

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

Aktivieren Sie die AWS Common Runtime 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 wie folgt aussehen:

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

Erstellen Sie den Model Service

In diesem Schritt richten Sie eine FastAPI-Webanwendung für die GPU-beschleunigte Bildklassifizierung mithilfe des GPUNet -0 Vision-Modells ein. Die Anwendung lädt zur Laufzeit Modellgewichte von Amazon S3 herunter, ruft die Modellarchitektur zum Zwischenspeichern aus dem NVIDIA-Repository ab und lädt ImageNet Klassenbezeichnungen über HTTP herunter. Die Anwendung umfasst Bildvorverarbeitungstransformationen und stellt zwei Endpunkte zur Verfügung: einen ROOT-GET zur Statusüberprüfung und einen /predict POST-Endpunkt, der eine Bild-URL akzeptiert.

Wir bieten das Modell mithilfe von FastAPI an und laden Gewichte zur Laufzeit aus Amazon S3 in einem containerisierten Setup für schnelles Prototyping und Kubernetes-Bereitstellung. PyTorch Weitere Methoden wie optimiertes Batching oder Engines mit hohem Durchsatz finden Sie unter Serving ML Models.

Erstellen der Anwendung

Erstellen Sie ein Verzeichnis für Ihre Anwendungsdateien wiemodel-testing, ändern Sie dann die Verzeichnisse in dieses Verzeichnis und fügen Sie den folgenden Code zu einer neuen Datei mit dem Namen hinzu: app.py

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

Erstellen Sie das Dockerfile

Das folgende Dockerfile erstellt ein Container-Image für unsere Anwendung, das das GPUNet Modell aus dem Repository NVIDIA Deep Learning Examples for Tensor Cores verwendet. GitHub

Wir reduzieren die Größe des Container-Images, indem wir eine reine PyTorch Runtime-Basis verwenden, nur wichtige Pakete mit Cache-Bereinigung installieren, Modellcode vorab zwischenspeichern und vermeiden, dass Gewichte im Container-Image „überbacken“ werden, um schnellere Abrufe und Updates zu ermöglichen. Weitere Informationen finden Sie unter Reduzieren der Größe von Container-Images.

Erstellen Sie im selben Verzeichnis wie app.pyDockerfile:

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 Dockerfile erstellen Sie das Container-Image für die Inferenzanwendung, wobei die AMD64 Architektur ins Visier genommen wird:

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

Legen Sie Umgebungsvariablen für Ihre AWS Anmeldeinformationen und optional ein AWS Sitzungstoken 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 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 Inferenzendpunkt, indem Sie eine Beispiel-POST-Anfrage mit einer öffentlichen Bild-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 Top-5-Vorhersagen sein, ähnlich der folgenden (die tatsächlichen Bezeichnungen und Wahrscheinlichkeiten können je nach Bild- 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“.

Den Container an Amazon ECR weiterleiten

In diesem Schritt laden wir das Container-Image für den Service GPUNet -0 Model in Amazon Elastic Container Registry (ECR) hoch, sodass es für die Bereitstellung auf Amazon EKS verfügbar ist. Dieser Prozess umfasst die Erstellung eines neuen ECR-Repositorys zum Speichern des Images, die Authentifizierung mit ECR, das anschließende Markieren und Übertragen des Container-Images in unsere Registry.

Navigieren Sie zunächst zurück zu dem Verzeichnis, in dem Sie zu Beginn dieses Handbuchs 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 wie folgt aussehen:

Login Succeeded

Markiere das Bild:

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

Pushen Sie das Bild in Ihr Amazon ECR-Repository:

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

Dieser letzte Schritt dauert mehrere Minuten.

7. (Optional) Machen Sie den Model Service verfügbar

In diesem Schritt stellen Sie Ihren Echtzeit-Inferenzmodell-Service mithilfe des Load AWS Balancer Controllers (LBC) extern auf Amazon EKS zur Verfügung. Dazu gehören die Einrichtung des LBC, das Mounten von Modellgewichten aus Amazon S3 als persistentes Volume mithilfe des Mountpoint S3 CSI-Treibers, die Bereitstellung eines GPU-beschleunigten Anwendungs-Pods, die Erstellung eines Service und Ingress zur Bereitstellung eines Application Load Balancer (ALB) und das Testen des Endpunkts.

Überprüfen Sie zunächst die Pod-Identity-Zuordnung für den AWS LBC und stellen Sie sicher, dass das Dienstkonto 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 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 Sie Ihre Cluster-Sicherheitsgruppe

Der Load AWS Balancer Controller unterstützt nur eine einzige Sicherheitsgruppe mit dem Tag-Schlüssel karpenter.sh/discovery: "${EKS_CLUSTER_NAME}" für die Sicherheitsgruppenauswahl von Karpenter. Beim Erstellen eines Clusters mit eksctl wird die standardmäßige Cluster-Sicherheitsgruppe (die das "kubernetes.io/cluster/<cluster-name>: owned" Tag enthält) nicht automatisch mit Tags gekennzeichnet. karpenter.sh/discovery Dieses Tag ist wichtig, damit Karpenter diese Sicherheitsgruppe erkennen und den von ihr bereitgestellten Knoten zuordnen kann. Durch das Anhängen dieser Sicherheitsgruppe wird die Kompatibilität mit dem Load AWS Balancer Controller (LBC) gewährleistet, sodass dieser automatisch Regeln für eingehenden Datenverkehr für Dienste verwalten kann, die über Ingress verfügbar gemacht werden, z. B. den Modelldienst 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 Standardsicherheitsgruppe 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 der standardmäßigen Cluster-Sicherheitsgruppe hinzu. Dadurch können unsere CPU- und EC2 NodeClass GPU-Selektoren es verwenden:

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

Stellen Sie sicher, dass das Tag hinzugefügt wurde:

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

Unter den Ergebnissen sollte Folgendes mit dem Tag und Ihrem Clusternamen angezeigt werden. Zum Beispiel:

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

Den AWS Load Balancer Controller (LBC) einrichten

Der AWS LBC ist unverzichtbar für die Verwaltung des eingehenden Datenverkehrs zu AI/ML Workloads auf Amazon EKS und gewährleistet den Zugriff auf Inferenzendpunkte oder Datenverarbeitungspipelines. Durch die Integration mit AWS Application Load Balancers (ALB) und Network Load Balancers (NLB) leitet der LBC den Datenverkehr dynamisch an containerisierte Anwendungen weiter, z. B. solche, die umfangreiche Sprachmodelle, Computer-Vision-Modelle oder Echtzeit-Inferenzdienste ausführen. Da wir das Dienstkonto und die Pod Identity Association bereits bei der Clustererstellung erstellt haben, stellen wir die so ein, dass sie den serviceAccount.name Definitionen in unserer Cluster-Konfiguration () entsprechen. aws-load-balancer-controller

Fügen Sie das Helm-Chart-Repository von AWS-owned eks-charts 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 das AWS LBC mithilfe von Helm bereit, geben Sie den Namen des EKS-Clusters an und verweisen Sie auf das vorab erstellte Dienstkonto:

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

Hängen Sie das Modell in ein persistentes Volume ein

In diesem Schritt mounten Sie Modellgewichte aus Ihrem Amazon S3-Bucket mithilfe eines PersistentVolume (PV), das vom Mountpoint for Amazon S3 CSI-Treiber unterstützt wird. Dadurch können Kubernetes-Pods auf S3-Objekte als lokale Dateien zugreifen, wodurch ressourcenintensive Downloads in kurzlebige Pod-Speicher- oder Init-Container vermieden werden — ideal für große Modellgewichte mit mehreren Gigabyte.

Das PV mountet das gesamte Bucket-Stammverzeichnis (kein Pfad ist in angegebenvolumeAttributes), unterstützt den gleichzeitigen schreibgeschützten Zugriff mehrerer Pods und macht Dateien wie die Modellgewichte () innerhalb des Containers für Rückschlüsse verfügbar. /models/gpunet-0.pth Dadurch wird sichergestellt, dass der Fallback-"Download“ in unserer Anwendung (app.py) nicht ausgelöst wird, weil die Datei über den Mount existiert. Durch die Entkopplung des Modells vom Container-Image werden der gemeinsame Zugriff und unabhängige Aktualisierungen der Modellversionen ohne Neuerstellungen des Images ermöglicht.

Erstellen Sie das PersistentVolume (PV)

Erstellen Sie eine PersistentVolume (PV-) Ressource, um den S3-Bucket zu mounten, der Ihre Modellgewichte enthält, und ermöglichen Sie so den schreibgeschützten Zugriff für mehrere Pods, 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 Sie das PersistentVolumeClaim (PVC)

Erstellen Sie ein PersistentVolumeClaim (PVC), das an das PV gebunden werden soll, und fordern Sie schreibgeschützten Zugriff auf die Daten des bereitgestellten S3-Modells 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 Inferenzanwendung als Kubernetes-Bereitstellung bereit, mounten Sie das S3-gestützte persistente Volume für den Modellzugriff, wenden Sie GPU-Knotenselektoren und -Toleranzen an und legen Sie Umgebungsvariablen für den Modellpfad fest. Dieses Deployment legt den Modellpfad (env var of"/models/gpunet-0.pth") fest, sodass unsere Anwendung (inapp.py) diesen Pfad standardmäßig verwendet. Wenn das Volume Mount des Deployments auf /models (schreibgeschützt) eingestellt 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 wird einige Minuten dauern, bis Karpenter einen GPU-Knoten bereitstellt, falls noch keiner verfügbar ist. Stellen Sie sicher, dass sich der Inferenz-Pod im Status „Wird ausgeführt“ befindet:

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

Die erwartete Ausgabe sollte wie folgt aussehen:

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

Den Service mit Ingress und Load Balancer verfügbar machen

Erstellen Sie einen ClusterIP-Dienst, um die Inferenzbereitstellung intern innerhalb des EKS-Clusters verfügbar zu machen und dabei auf den Port der Anwendung abzuzielen:

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 einen mit dem Internet verbundenen Application Load Balancer (ALB) über den AWS LBC bereitzustellen und externen Datenverkehr an den Inferenzdienst weiterzuleiten:

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 aufgefülltem ADDRESS-Feld):

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-Hostnamen 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}')

Testen Sie den Model Service

Überprüfen Sie den exponierten Inferenzendpunkt, indem Sie eine POST-Anfrage mit einer Beispiel-Bild-URL (z. B. aus dem COCO-Datensatz) senden und so eine Vorhersage in Echtzeit 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 Top-5-Vorhersagen sein, ähnlich der folgenden (die tatsächlichen Bezeichnungen und Wahrscheinlichkeiten können je nach Bild- 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}]}

Sie können optional mit dem Testen anderer Bilder in einer neuen POST-Anfrage 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 Inferenz-Workloads in Echtzeit optimiert ist. Sie haben einen Cluster mit EC2 G5-Instanzen bereitgestellt, den Mountpoint S3 CSI-Treiber, den EKS Pod Identity Agent, den EKS Node Monitoring Agent, das Bottlerocket AMI, den Load AWS Balancer Controller (LBC) und Karpenter zur Verwaltung von CPU und GPU installiert. NodePools Sie haben das NVIDIA-Geräte-Plugin verwendet, um die GPU-Planung zu aktivieren, und S3 mit einem und für den Modellzugriff konfiguriert. PersistentVolume PersistentVolumeClaim Sie haben das Setup validiert, indem Sie einen Beispiel-GPU-Pod bereitgestellt, den Modellzugriff für das NVIDIA GPUNet-0-Modell auf Amazon S3 eingerichtet, die Pod-Initialisierung aktiviert und den Inferenzservice über Application Load Balancer verfügbar gemacht haben. Um Ihren Cluster vollständig zu nutzen, konfigurieren Sie den EKS Node Monitoring Agent 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 Verwenden von Überwachungs- und Observability-Tools für Ihre AI/ML Workloads.

Bereinigen

Um future Gebühren zu vermeiden, müssen Sie den zugehörigen CloudFormation Stack manuell löschen, um alle in diesem Handbuch erstellten Ressourcen, einschließlich des VPC-Netzwerks, zu löschen.

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 sollten Sie die folgende Antwortausgabe sehen:

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

Löschen Sie den in dieser Anleitung erstellten Amazon S3 S3-Bucket mithilfe der Amazon S3 S3-Konsole.