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 ClusterConfig
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 CloudFormation
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. NodePoolslimits
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
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örungsrichtlinieconsolidateAfter: 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.conditions
like“ ValidationSucceeded: True
NodeClassReady: 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örungsrichtlinieconsolidateAfter: 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.conditions
like“ ValidationSucceeded: True
NodeClassReady: 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
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
-
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 einnvidia
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
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
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.py
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 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
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