View a markdown version of this page

Identifizieren Sie Schwellenwerte für Skalierungsmetriken für KI-Inferenz - Amazon EKS

Unterstützung für die Verbesserung dieser Seite beitragen

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.

Um zu diesem Benutzerhandbuch beizutragen, wählen Sie den GitHub Link Diese Seite bearbeiten unter, 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.

Identifizieren Sie Schwellenwerte für Skalierungsmetriken für KI-Inferenz

In diesem Abschnitt wird gezeigt, wie Sie einen vLLM-Inferenzserver auf Amazon EKS auslasten, um festzustellen, wann er überlastet ist. Verwenden Sie die Ergebnisse des Lasttests, um die Warteschlangentiefe und die Latenzschwellenwerte für die horizontale Autoskalierung im nachfolgenden Abschnitt zu konfigurieren. Automatische Skalierung der KI-Inferenz mit HPA und KEDA

In der exemplarischen Vorgehensweise werden die folgenden Tools verwendet:

  • k6 (Grafana k6) ist ein Open-Source-Tool zum Testen von Lasten, das als grafana/k6 Container-Image ausgeführt wird und Inferenzanforderungen mit kontrollierten Anforderungsraten an das Replikat sendet.

  • Ministral-3-8B-Instruct-2512 g6e.4xlargeModell auf einer Instanz. Sie können dieselbe Methode auf jedes Open-Source-Modell und jeden GPU-Typ anwenden.

Voraussetzungen

Dieser Abschnitt baut auf zwei früheren Abschnitten in der Dokumentation auf. Füllen Sie beide aus, bevor Sie beginnen:

Bestätigen Sie jeden der folgenden Punkte, bevor Sie beginnen, und füllen Sie zuerst den verlinkten Abschnitt aus, falls eine Überprüfung fehlschlägt.

Wenn Sie ein neues Terminal geöffnet haben, legen Sie den Clusternamen und die Region fest, die Sie zuvor verwendet haben:

export CLUSTER_NAME=ai-eks-docs export AWS_REGION=us-east-2

Erfassen Sie den Namen des Amazon S3-Modell-Buckets, der in den Schritten zum Cluster-Setup erstellt wurde. Der Lastgenerator übergibt diesen Wert an vLLM.

MODEL_BUCKET=$(aws s3api list-buckets \ --query "Buckets[?starts_with(Name, '${CLUSTER_NAME}-models-')].Name | [0]" \ --output text) echo "Model bucket: ${MODEL_BUCKET}"

Vergewissern Sie sich, dass der Monitoring-Stack läuft

Der Kube-Prometheus-Stack aus dem Monitoring-Setup wird im Namespace ausgeführt. monitoring

kubectl get pods -n monitoring

Die Prometheus- und Grafana-Pods sollten sein: Running

NAME READY STATUS RESTARTS AGE kube-prometheus-stack-grafana-6f9c8b7d5c-2xk9p 3/3 Running 0 3h kube-prometheus-stack-operator-7b8c9d6f4-q4m7n 1/1 Running 0 3h prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 3h

Wenn diese fehlen, schließen Sie das Überwachen Monitoring-Setup ab, bevor Sie fortfahren.

Vergewissern Sie sich, dass das vLLM-Modell läuft

Die vllm-inference-app Deployment- und vllm-inference-svc Service-Modelle von Load & Serve werden im default Namespace ausgeführt.

kubectl get deployment vllm-inference-app

Die Bereitstellung sollte den Bericht „1/1Bereit“ melden:

NAME READY UP-TO-DATE AVAILABLE AGE vllm-inference-app 1/1 1 1 3h

Wenn das Deployment fehlt oder noch nicht bereit ist, füllen Sie Load & Serve Models aus, bevor Sie fortfahren.

Greifen Sie auf Grafana zu

Sie verfolgen den Lasttest im vorinstallierten vLLM-Dashboard. Stellen Sie daher sicher, dass der Grafana-Load Balancer, den Sie im Abschnitt Access Grafana eingerichtet haben, erreichbar ist. Greifen Sie auf Grafana zu Drucken Sie seine URL aus:

echo "http://$(kubectl get ingress kube-prometheus-stack-grafana -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')"

Öffnen Sie die URL in Ihrem Browser und melden Sie sich mit dem folgenden Befehl mit dem Benutzernamen admin und dem Passwort an:

kubectl --namespace monitoring get secrets kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 -d ; echo

Bestätigen Sie, dass der vLLM existiert ServiceMonitor

Das vllm-inference-app ServiceMonitor, das im Schritt „vLLM überwachen“ erstellt wurde, wird im default Namespace ausgeführt und teilt Prometheus mit, wo die vLLM-Metriken abgefragt werden sollen.

kubectl get servicemonitor vllm-inference-app

Erwartete Ausgabe:

NAME AGE vllm-inference-app 3h

Wenn es fehlt, schließen Sie den Schritt Monitor vLLM ab. Schritt 4: Überwachen Sie vLLM

Schritt 1: Wärmen Sie die GPU auf

Obwohl das Modell in den GPU-Speicher geladen wird und das Replikat Bereit meldet, dauern die ersten Anforderungen länger als die späteren, da vLLM und die GPU bei den ersten Inferenzen die Initialisierung abschließen. vLLM erfasst CUDA-Diagramme, kompiliert und optimiert GPU-Kernel automatisch und weist ihre KV-Cache-Speicherpools zu, während die GPU ihre Taktraten vom Leerlauf in den Boost-Bereich erhöht.

Da es sich um einmalige Kosten handelt, zeichnet die Messung der Schwellenwerte vor dem Aufwärmen die Startzeit auf und nicht den stationären Betrieb. Beim folgenden Warm-Up werden 100 aufeinanderfolgende Anforderungen gesendet, um diese Initialisierung abzuschließen. Der darauffolgende Auslastungstest misst also die Kapazität im stationären Zustand.

Erstellen Sie zunächst das, das das ConfigMap Aufwärmskript enthält (). warmup.js Das Skript liest das Zielmodell aus der MODEL Umgebungsvariablen, die der Job anhand des zuvor erfassten MODEL_BUCKET Werts festlegt:

Beispiel k6 Aufwärmen ConfigMap
cat << 'EOF' | kubectl apply -f - apiVersion: v1 kind: ConfigMap metadata: name: vllm-warmup-script namespace: default data: warmup.js: | import http from 'k6/http'; export default function () { const payload = JSON.stringify({ model: __ENV.MODEL, prompt: 'Write a brief technical explanation about cloud computing concepts.', max_tokens: 100, temperature: 0.7, }); const params = { headers: { 'Content-Type': 'application/json' }, timeout: '240s' }; http.post('http://vllm-inference-svc:8000/v1/completions', payload, params); } EOF

Führen Sie dann den Aufwärm-Job aus. Ein einzelner Client sendet 100 aufeinanderfolgende Anfragen:

Beispiel Warm-up Auftrag
cat << EOF | kubectl apply -f - apiVersion: batch/v1 kind: Job metadata: name: vllm-warmup namespace: default spec: backoffLimit: 0 template: spec: restartPolicy: Never containers: - name: k6 image: grafana/k6:latest env: - name: MODEL value: "s3://${MODEL_BUCKET}/Ministral-3-8B-Instruct-2512/" args: ["run", "--vus", "1", "--iterations", "100", "/scripts/warmup.js"] volumeMounts: - name: script mountPath: /scripts volumes: - name: script configMap: name: vllm-warmup-script EOF

Warten Sie, bis das Aufwärmen abgeschlossen ist (es dauert ein paar Minuten):

kubectl wait --for=condition=complete job/vllm-warmup --timeout=600s

Öffnen Sie Grafana (öffnen Sie den Hostnamen des Load Balancers; Einzelheiten finden Sie unter Access Grafana) und navigieren Sie zu Dashboards > GPU-Überwachung > Leistungstests — vLLM-Lastanalyse. Das Feld „vLLM Request Rate“ zeigt den Anstieg des Aufwärmdatenverkehrs. Das Feld „Durchschnittliche vLLM-Latenz“ zeigt, dass die erste Anfrage langsamer ist. Dies entspricht den einmaligen GPU-Aufwärmkosten.

Das vLLM-Dashboard zeigt den Effekt des GPU-Aufwärmens auf die Latenz

Ein kurzer Aufwärm-Traffic, bei dem die Latenz bei der ersten Anforderung von etwa 2,6 Sekunden auf einen gleichbleibenden Ausgangswert sinkt, wenn sich die GPU erwärmt.

Löschen Sie dann den Aufwärmjob:

kubectl delete job vllm-warmup

Schritt 2: Ladung mit steigenden Anforderungsraten senden

In diesem Schritt führen Sie einen Auslastungstest durch, der Anfragen mit steigender Geschwindigkeit an das einzelne vLLM-Replikat sendet: 10, 20, 30, 40, 50, 60 und 70 Anforderungen pro Sekunde. Dadurch wird eine steigende Benutzernachfrage simuliert. Der Test verwendet k6 in einem Modell mit konstanter Ankunftsrate, bei dem die TARGET_RPS Umgebungsvariable die Zielanforderungsrate festlegt. Jede Rate läuft 60 Sekunden lang, damit sich die Metriken stabilisieren können, gefolgt von einer Pause von 30 Sekunden vor der nächsten Ratenerhöhung.

Ziel dieses Tests ist es, den Sättigungspunkt zu ermitteln, d. h. die Anforderungsrate, bei der ein einzelnes Replikat mit eingehenden Anfragen nicht mehr Schritt halten kann. Sie überwachen die Warteschlangentiefe (vllm:num_requests_waiting) und die Ende-zu-Ende-Latenz (vllm:e2e_request_latency_seconds). Zunehmende Warteschlangentiefe und Latenz deuten darauf hin, dass sich das Replikat der Sättigung nähert.

Erstellen Sie zunächst das, das ConfigMap das k6-Load-Test-Skript () enthält. script.js Das Skript liest das Zielmodell aus der MODEL Umgebungsvariablen, die jeder Pod anhand des zuvor erfassten MODEL_BUCKET Werts festlegt:

Beispiel k6-Auslastungstest ConfigMap
cat << 'EOF' | kubectl apply -f - apiVersion: v1 kind: ConfigMap metadata: name: vllm-loadtest-script namespace: default data: script.js: | import http from 'k6/http'; // Dictionary of 10-letter words for variation (prevents prompt caching) const words = [ 'revolution', 'technology', 'javascript', 'kubernetes', 'basketball', 'strawberry', 'watermelon', 'blueberries', 'throughout', 'background', 'playground', 'understand', 'everything', 'protection', 'complexity' ]; export const options = { noConnectionReuse: true, scenarios: { constant_request_rate: { executor: 'constant-arrival-rate', rate: __ENV.TARGET_RPS || 10, // Overridden by TARGET_RPS env var timeUnit: '1s', duration: __ENV.DURATION || '60s', // Overridden by DURATION env var preAllocatedVUs: 50, maxVUs: 500, }, }, }; export default function () { const randomWord = words[Math.floor(Math.random() * words.length)]; const payload = JSON.stringify({ model: __ENV.MODEL, prompt: `Starting with the word "${randomWord}", write a brief technical explanation about cloud computing concepts. Cover containerization, orchestration, and scalability in about 80 words.`, max_tokens: 100, temperature: 0.7, }); const params = { headers: { 'Content-Type': 'application/json' }, timeout: '240s' }; http.post('http://vllm-inference-svc:8000/v1/completions', payload, params); } EOF

Führen Sie dann den Lasttest bei jeder Anforderungsrate aus. In der folgenden Schleife wird für jede Rate ein separater Job gesendet:

Beispiel Testschleife laden
for RPS in 10 20 30 40 50 60 70; do echo "=== Testing at ${RPS} req/s ===" cat << EOF | kubectl apply -f - apiVersion: batch/v1 kind: Job metadata: name: vllm-loadtest-${RPS} namespace: default labels: app: vllm-loadtest spec: backoffLimit: 0 template: metadata: labels: app: vllm-loadtest spec: restartPolicy: Never containers: - name: k6 image: grafana/k6:latest env: - name: K6_PROMETHEUS_RW_SERVER_URL value: "http://kube-prometheus-stack-prometheus.monitoring.svc.cluster.local:9090/api/v1/write" - name: MODEL value: "s3://${MODEL_BUCKET}/Ministral-3-8B-Instruct-2512/" - name: TARGET_RPS value: "${RPS}" - name: DURATION value: "60s" args: ["run", "-o", "experimental-prometheus-rw", "/scripts/script.js"] volumeMounts: - name: script mountPath: /scripts volumes: - name: script configMap: name: vllm-loadtest-script EOF kubectl wait --for=condition=complete job/vllm-loadtest-${RPS} --timeout=180s sleep 30 done

Beobachten Sie die Metriken in Grafana, während der Test ausgeführt wird (siehe Schritt 3). Jede Rate erstellt ihren eigenen Job (vllm-loadtest-10Throughvllm-loadtest-70), sodass Sie jeden Testlauf mit kubectl get jobs überprüfen können. Wenn Sie fertig sind, löschen Sie alle Load-Test-Jobs:

kubectl delete jobs -l app=vllm-loadtest

Schritt 3: Messen Sie die Metriken unter Last

Achten Sie während des Ladevorgangs auf die beiden Metriken, die für die automatische Skalierung verantwortlich sind:

  • Warteschlangentiefe (vllm:num_requests_waiting) — wie viele Anfragen darauf warten, bearbeitet zu werden.

  • p95 Ende-zu-Ende-Latenz (vllm:e2e_request_latency_seconds) — die 95. Perzentilantwortzeit.

Sehen Sie sich die Metriken in Grafana an

Öffnen Sie Grafana (öffnen Sie den Load Balancer-Hostnamen und melden Sie sich an alsadmin; Einzelheiten finden Sie unter Access Grafana) und navigieren Sie zu Dashboards > GPU-Überwachung > Leistungstests — vLLM Load Analysis. Dieses Dashboard liest Daten von Amazon Managed Service for Prometheus, sodass Panels den Live-Status um bis zu einer Minute verzögern können, da die Messwerte stapelweise per Fernzugriff geschrieben werden.

Leistungstests — vLLM Load Analysis Dashboard während des Lasttests

Sechs Panels zeigen die CPU- und Speicherauslastung des K6-Pods pro Lasttest-Job, den schrittweisen Anstieg der vLLM-Anforderungsrate, den Anstieg der durchschnittlichen Latenz, sobald das Replikat voll ist, die pro Anfrage generierten Token und den Anstieg der Warteschlangentiefe von Null bei Sättigung.

Basierend auf den Ergebnissen des Lasttests blieb die Warteschlangentiefe bei 50 gleichzeitigen Anfragen nahe Null. Dann stieg sie bei 60 gleichzeitigen Anfragen stark an und erreichte ihren Höhepunkt zwischen etwa 150 und 350 Anfragen in der Warteschlange. Gleichzeitig stieg die p95-Ende-Latenz von einem konstanten Ausgangswert von etwa 2,5 Sekunden auf 6—10 Sekunden. Dieses Verhalten weist auf das Einsetzen einer anhaltenden Überlastung hin und legt nahe, dass die automatische Skalierung beginnen sollte, bevor die Warteschlangentiefe Werte erreicht, die dazu führen, dass sich die Latenz 10 Sekunden nähert. Ein praktischer Ausgangspunkt ist das Auslösen der Skalierung, wenn die Warteschlangentiefe 30 bis 60 Sekunden lang 25 Anfragen überschreitet. Als sekundäres Signal können Sie die Skalierung auch auslösen, wenn die p95-Ende-Latenz innerhalb desselben Intervalls 5 Sekunden überschreitet. Auf diese Weise können Arbeitslastmuster berücksichtigt werden, bei denen die Latenz zunimmt, bevor die Warteschlangentiefe zunimmt.

Schritt 4: Wählen Sie die Metriken und Schwellenwerte für die Skalierung

Anhand der am Sättigungspunkt beobachteten Metriken bestimmen Sie im nächsten Abschnitt die Schwellenwerte, die für die Konfiguration der automatischen Skalierung verwendet werden.

  • Warteschlangentiefe (vllm:num_requests_waiting) — Die Anzahl der Anfragen, die darauf warten, verarbeitet zu werden, sobald ein Replikat überlastet ist. Legen Sie den Schwellenwert über dem Punkt fest, an dem die Warteschlange zuerst positiv bleibt, sodass vorübergehende Spitzen keine Skalierung auslösen. Beim Auslastungstest in diesem Abschnitt blieb die Warteschlangentiefe bei 50 gleichzeitigen Anfragen nahe Null und erhöhte sich stark auf etwa 150—350 Anfragen in der Warteschlange bei 60 gleichzeitigen Anforderungen. Ein praktischer Ausgangspunkt ist das Auslösen einer Skalierung, wenn die Warteschlangentiefe 30 bis 60 Sekunden lang 25 Anfragen überschreitet.

  • Latenz (vllm:e2e_request_latency_seconds) — Die durchgängige Reaktionszeit, wenn sich ein Replikat seiner Kapazitätsgrenze nähert. Legen Sie den Schwellenwert unter Ihr Latenz-SLO fest, sodass das Autoscaling herunterskaliert wird, bevor die für den Benutzer sichtbare Latenz inakzeptabel wird. Für den Auslastungstest in diesem Abschnitt blieb die p95-Ende-Latenz stabil bei etwa 2,5 Sekunden und stieg bei Sättigung auf 6—10 Sekunden an. Als sekundäres Signal besteht ein praktischer Ausgangspunkt darin, die Skalierung auszulösen, wenn die p95-Ende-Latenz 30—60 Sekunden lang 5 Sekunden lang überschreitet. Auf diese Weise können Arbeitslastmuster berücksichtigt werden, bei denen die Latenz steigt, bevor die Warteschlangentiefe zunimmt, oder wenn die Latenz ohne Warteschlangenbildung zunimmt.

  • Scale-down— die Geschwindigkeit, mit der der Autoscaler Replikate entfernt, wenn die Nachfrage sinkt. Skalieren Sie langsamer nach unten als nach oben. Skalieren Sie in diesem Beispiel nur dann nach unten, wenn die Warteschlangentiefe erreicht ist 0 und die p95-Ende-Latenz 5 Minuten lang unter 3 Sekunden liegt. Dadurch wird verhindert, dass der Autoscaler während kurzer Datenverkehrspausen Replikate entfernt, und es wird eine Oszillation vermieden.

Diese Werte bieten einen Ausgangspunkt für die Konfiguration von Autoscaling im nächsten Abschnitt. Wiederholen Sie diesen Vorgang für Ihr eigenes Modell, Ihren GPU-Typ und Ihre Anforderungsmuster, um die geeigneten Schwellenwerte für Ihre Bereitstellung zu ermitteln.