Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Gilt für: ✔️ AKS Automatic ✔️ AKS Standard
MLOps ist eine Reihe von Methoden für die Bereitstellung, Überwachung und Verwaltung von Machine Learning-Modellen in Produktionsumgebungen.
Wichtige bewährte Methoden für MLOps, die in diesem Artikel behandelt werden:
- Infrastruktur als Code (IaC)
- Containerisierung
- Modellverwaltung und Versionsverwaltung
- Automatisierung
- Skalierbarkeit und Ressourcenmanagement
- Zuverlässigkeit lang laufender Batchaufträge
- Sicherheit und Compliance
In diesem Artikel werden Best Practices und Überlegungen beschrieben, die Sie bei der Verwendung von MLOps in AKS berücksichtigen sollten. Weitere Informationen zu MLOps finden Sie unter Machine Learning Operations (MLOps) für KI- und Machine Learning-Workflows.
Wählen Sie Ihren AKS-Modus für MLOps aus.
AKS unterstützt zwei Clustermodi: AKS Automatic and AKS Standard. Wählen Sie AKS Automatic aus, wenn Sie eine produktionsbereite Grundkonfiguration mit weniger laufendem Plattformmanagement wünschen. Wählen Sie AKS Standard aus, wenn Sie eine tiefere Kontrolle über die Clusterinfrastruktur- und Plattformkonfiguration benötigen.
Die MLOps-Methoden in diesem Artikel gelten für beide Modi. Die Implementierungsverantwortung unterscheidet sich jedoch vom Modus: AKS Automatic bietet mehr vorkonfigurierte Standardwerte, während AKS Standard in der Regel explizitere Plattformkonfiguration und Lebenszyklusbesitz erfordert.
| Area | AKS Automatik | AKS Standard |
|---|---|---|
| Grundkonfiguration des Clusters | Vorkonfigurierte Knotenpools, Netzwerkeinstellungen und Überwachung – sofort einsatzbereit | Erfordert eine manuelle Konfiguration von Knotenpools, CNI und Observability Stack |
| Systemknotenpoolvorgänge | Automatische Knotenbereitstellung und vom Dienst verwaltete Skalierung | Der Operator muss die Größe des Knotenpools, Skalierungsregeln und Wartungsfenster konfigurieren. |
| Kontrollen der Sicherheitsbasislinie | Standardmäßig aktiviert: Netzwerkrichtlinien, Pod-Sicherheitsstandards und Workload-Identität | Operatoren müssen Netzwerkrichtlinien, Podsicherheit und Identitätseinstellungen explizit aktivieren und konfigurieren. |
| Netzwerkbasisplan | Vorkonfigurierte Azure CNI-Überlagerung mit Standardingressmustern | Volle Flexibilität beim Auswählen des CNI-Plug-Ins, Konfigurieren von benutzerdefinierten Eingangscontrollern und Definieren der Netzwerktopologie |
| Vorgänge und Upgrades | Automatisches Knotenimage und Kubernetes-Versionsupgrades | Betreiber planen und verwalten den Zeitpunkt von Upgrades und die Rollout-Strategie |
| Fokus der MLOps-Implementierung | Validieren, verwalten und Standardwerte optimieren | Entwerfen und Konfigurieren von Plattformsteuerelementen |
| GPU-Kapazität und -Planung | Geeignete GPU-Kapazität kann anhand der Ressourcenanforderungen von Workloads und der Schedulingeinschränkungen automatisch bereitgestellt werden, vorbehaltlich der regionalen SKU-Verfügbarkeit und des Abonnementkontingents | Operatoren erstellen und verwalten GPU-Knotenpools, Bezeichnungen, Taints, Autoscaler-Grenzwerte, Treiber und Geräte-Plug-In-Konfiguration |
| Verteilte Schulung | Die Standardmäßige Kubernetes-Planung und automatische Knotenbereitstellung bieten einen Ausgangspunkt; Schulungsoperatoren, Gangplaner und Topologieoptimierung bleiben die Auswahlmöglichkeiten auf Workloadebene | Operatoren installieren explizit Schulungsoperatoren und Scheduler und entwerfen GPU-Knotenpools, Netzwerke, Skalierung und Platzierung für verteilte Aufträge |
Infrastruktur als Code (IaC)
Wichtige Erkenntnis: Definieren und Version IaC-Vorlagen für jede Phase Ihrer KI-Pipeline, um Konsistenz, Kosteneffizienz und schnellere Bereitstellungen sicherzustellen.
IaC ermöglicht eine konsistente und reproduzierbare Infrastrukturbereitstellung und -verwaltung für eine Reihe von Anwendungstypen. Bei unterschiedlichen Anwendungsbereitstellungen kann sich Ihre IaC-Implementierung in der gesamten KI-Pipeline ändern, da die Für das Ableiten, Bereitstellen, Trainieren und Optimieren von Modellen benötigte Rechenleistung und Ressourcen variieren können. Die Definition und Versionsverwaltung von IaC-Vorlagen für Ihre KI-Entwicklerteams kann dazu beitragen, Konsistenz und Kosteneffizienz für alle Auftragstypen zu gewährleisten und gleichzeitig Hardwareanforderungen zu klären und den Bereitstellungsprozess zu beschleunigen.
Bei AKS Automatic kann sich IaC stärker auf Workloaddefinitionen, Leitplanken für Richtlinien und die Konsistenz der Umgebung konzentrieren als auf Plattformstandardwerte. In AKS Standard enthält IaC häufig explizitere Clusterplattformeinstellungen wie Netzwerk, Skalierung und betriebliche Konfigurationsoptionen.
Containerisierung
Wichtige Erkenntnis: Paketmodellgewichtungen, Metadaten und Konfigurationen in Containerimages, um Portabilität, vereinfachte Versionsverwaltung und geringere Speicherkosten zu ermöglichen.
Das Verwalten von Modellgewichtungen, Metadaten und Konfigurationen in Containerimages ermöglicht Portabilität, vereinfachte Versionsverwaltung und verringerte Speicherkosten im Laufe der Zeit. Vorteile der Containerisierung:
- Verwenden Sie vorhandene Container-Images, insbesondere für Large Language Models (LLMs) mit Millionen bis Milliarden von Parametern sowie für Stable-Diffusion-Modelle, die in sicheren Container-Registern gespeichert sind.
- Vermeiden Sie einen einzelnen Fehlerpunkt in Ihrer Pipeline, indem Sie mehrere einfache Container verwenden, die die eindeutigen Abhängigkeiten für jede Aufgabe enthalten, anstatt ein großes Image zu verwalten.
- Speichern Sie große Text- und Bilddatensätze außerhalb Des Basiscontainerimages, und verweisen Sie bei Bedarf zur Laufzeit auf sie. Erste Schritte mit dem Kubernetes AI Toolchain Operator (KAITO) zur Bereitstellung eines LLM auf AKS.
Container-Lieferkettenkontrollen bleiben in beiden Modi unerlässlich. Selbst mit standardmäßig vorkonfigurierten Plattformvorgaben in AKS Automatic bleiben die Herkunft von Images, deren Sicherheitsüberprüfung und die Laufzeithärtung zentrale MLOps-Aufgaben.
Dockerfile-Muster für ML-Workloads:
Verwenden Sie ein explizites, CUDA-fähiges Basisimagetag für GPU-Schulungsworkloads (z. B pytorch/pytorch:2.4.1-cuda12.4-cudnn9-runtime. ) anstelle eines nicht markierten Basisimageverweises. Fixieren Sie das Image für die Produktion per Digest, um reproduzierbare Builds und ein vorhersagbares CUDA/cuDNN-Verhalten sicherzustellen. Verwalten Sie getrennte CPU- und GPU-Image-Varianten, sodass die Platzierung durch den Scheduler und die Laufzeitabhängigkeiten explizit bleiben.
Modellverwaltung und Versionsverwaltung
Wichtige Erkenntnis: Versionieren Sie Ihre Modelle systematisch, um Konsistenz in allen Umgebungen zu gewährleisten und eine schnellere Iteration mit parametereffizienten Feinabstimmungsmethoden zu ermöglichen.
Modellverwaltung und Versionsverwaltung sind für das Nachverfolgen von Änderungen an Ihren Modellen im Laufe der Zeit unerlässlich. Durch die Versionierung Ihrer Modelle können Sie:
- Sorgen Sie für eine einfache Bereitstellung in unterschiedlichen Umgebungen durch Konsistenz in Ihren Modellcontainern.
- Verwenden Sie PEFT-Methoden (Parameter-Efficient Fine-Tuning), um einen Teil der Modellgewichtungen schneller zu durchlaufen und neue Versionen in schlanken Containern zu verwalten.
In AKS Automatic können vorkonfigurierte Plattformbasispläne die Umgebungsparität vereinfachen. In AKS Standard müssen Teams häufig die Parität durch plattform- und bereitstellungskonfiguration expliziter erzwingen.
Automatisierung
Wichtige Erkenntnis: Automatisieren Sie die Erfassung von Daten, modellieren Sie die Leistungsüberwachung und Umschulungspipelinen, um manuelle Fehler zu reduzieren und die Konsistenz im gesamten ML-Lebenszyklus sicherzustellen.
Die Automatisierung hilft dabei, manuelle Fehler zu reduzieren, die Effizienz zu steigern und die Konsistenz im gesamten ML-Lebenszyklus sicherzustellen. Vorteile der Aufgabenautomatisierung:
- Integrieren Sie Warnungstools, um einen Vektoreinzug auszulösen, wenn neue Daten in Ihre Anwendung fließen.
- Legen Sie Modellleistungsschwellenwerte fest, um Beeinträchtigungen nachzuverfolgen und Pipelines für erneutes Training auszulösen.
In beiden AKS-Modi sollten Sie neben Triggern für die Modellqualität auch Automatisierung für die Richtlinienvalidierung, die Erkennung von Konfigurationsabweichungen und die Release-Governance einbeziehen.
Skalierbarkeit und Ressourcenmanagement
Wichtige Herausforderung: Optimieren Sie die Ressourcennutzung durch verteilte Computer, automatische Skalierung und Notfallwiederherstellung, um unterschiedliche KI-Pipelineanforderungen kosteneffizient zu verarbeiten.
Skalierbarkeit und Ressourcenmanagement sind wichtig, um sicherzustellen, dass Ihre KI-Pipeline die Anforderungen Ihrer Anwendung verarbeiten kann. Vorteile der Optimierung des Ressourceneinsatzes:
- Integrieren Sie Tools, die Ihre zugeordneten CPU-, GPU- und Speicherressourcen effizient über verteilte Computer und mehrere Parallelitätsebenen wie Daten, Modell und Pipeline-Parallelität verwenden.
- Aktivieren Sie die automatische Skalierung Ihrer Rechenressourcen, um hohe Volumen an Modellanfragen in Spitzenzeiten zu bewältigen und sie in Schwachlastzeiten wieder zu reduzieren.
- Planen Sie die Notfallwiederherstellung, indem Sie bewährte Methoden zur Ausfallsicherheit und Zuverlässigkeit von AKS ausführen.
AKS Automatic kann den Einrichtungsaufwand für allgemeine Skalierungs- und Betriebsmuster reduzieren, während AKS Standard eine tiefere Kontrolle über benutzerdefinierte Skalierungsarchitekturen bietet.
Lang andauernde Batchaufträge ausführen
Wichtigste Erkenntnis: Führen Sie zeitlich begrenzte Aufgaben als Kubernetes-JobJob aus, speichern Sie den Fortschritt außerhalb des Pods, behandeln Sie Beendigungssignale und gehen Sie davon aus, dass der Job möglicherweise mehr als einmal gestartet wird.
Upgrades von Knoten, Neustarts, Ereignisse beim Herunterskalieren, Ressourcendruck, Präemption und Infrastrukturausfälle können lang laufende Batch-Aufträge unterbrechen. Ein Kubernetes-Job ersetzt einen ausgefallenen oder gelöschten Pod, aber der Ersatz wird auf einem anderen Knoten gestartet, ohne die lokalen Dateien oder den Prozessspeicher des vorherigen Pods. Entwerfen Sie die Anwendung so, dass sie aus einem persistenten Zustand fortgesetzt werden kann und Arbeit sicher wiederholt werden kann.
Verwenden Sie diese Methoden für gewöhnliche CPU-, Arbeitsspeicher- oder E/A-intensive Batchaufträge. Die Anleitung zu Gang-Scheduling und Workload-Warteschlangen gilt, wenn bei einem verteilten Workload mehrere Worker gleichzeitig gestartet werden müssen oder wenn Teams gemeinsame Kontingente benötigen. Ein Einzelarbeits- oder unabhängig paralleler Batchauftrag benötigt normalerweise keine Gangplanung.
Konfigurieren von Prüfpunkten, Wiederholungen und Beenden
Im folgenden Beispiel wird eine Abfolge von Arbeitsaufgaben verarbeitet und das nächste Element auf einem Azure Files persistenten Volume aufgezeichnet. Stellt den Prüfpunkt nach dem Austausch eines Pods wieder her und speichert den Fortschritt, wenn der Prozess SIGTERM empfängt:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: batch-checkpoints
spec:
accessModes:
- ReadWriteMany
storageClassName: azurefile-csi
resources:
requests:
storage: 10Gi
---
apiVersion: batch/v1
kind: Job
metadata:
name: checkpointed-batch
spec:
backoffLimit: 6
activeDeadlineSeconds: 86400
ttlSecondsAfterFinished: 86400
podFailurePolicy:
rules:
- action: Ignore
onPodConditions:
- type: DisruptionTarget
template:
metadata:
labels:
app: checkpointed-batch
spec:
restartPolicy: Never
terminationGracePeriodSeconds: 120
containers:
- name: worker
image: ubuntu:24.04
command:
- /bin/bash
- -c
- |
set -euo pipefail
CHECKPOINT=/checkpoints/next-item
NEXT_ITEM=1
if [[ -f "${CHECKPOINT}" ]]; then
NEXT_ITEM="$(cat "${CHECKPOINT}")"
echo "Resuming at item ${NEXT_ITEM}."
fi
save_checkpoint() {
printf '%s\n' "${NEXT_ITEM}" > "${CHECKPOINT}.tmp"
mv "${CHECKPOINT}.tmp" "${CHECKPOINT}"
echo "Saved checkpoint for item ${NEXT_ITEM}."
}
terminate() {
echo "Received a termination signal."
save_checkpoint
exit 143
}
trap terminate TERM INT
while (( NEXT_ITEM <= 1000 )); do
echo "Processing item ${NEXT_ITEM}."
sleep 10
NEXT_ITEM=$((NEXT_ITEM + 1))
save_checkpoint
done
echo "Batch completed."
resources:
requests:
cpu: "1"
memory: 1Gi
limits:
cpu: "1"
memory: 1Gi
volumeMounts:
- name: checkpoints
mountPath: /checkpoints
volumes:
- name: checkpoints
persistentVolumeClaim:
claimName: batch-checkpoints
Ersetzen Sie die Beispielschleife durch Ihre Batchanwendung, und wählen Sie Speicher aus, der den Durchsatz und die Wiederherstellungsanforderungen erfüllt. Verwenden Sie die Workloadidentität anstelle eingebetteter Anmeldeinformationen, wenn die Anwendungsprüfpunkte direkt an Azure Blob Storage oder einen anderen Azure Dienst übertragen werden.
Wenden Sie diese Zuverlässigkeitskontrollen gezielt an:
-
Checkpointing und Idempotenz: Speichern Sie den Fortschritt in Intervallen, die Ihrem Recovery Point Objective entsprechen. Speichern Sie Checkpoints und persistierte Ausgaben im persistenten Speicher, nicht im Container-Dateisystem,
emptyDir, oder im knotenlokalen Speicher. Verwenden Sie atomische Schreibvorgänge, Idempotenzschlüssel, transaktionale Ausgabe oder Deduplizierung, da dasselbe Job-Programm manchmal mehr als einmal starten kann. -
Neustartverhalten: Ein Job unterstützt
restartPolicy: NeveroderOnFailure. MitNeverführt ein fehlerhafter Container zu einem fehlgeschlagenen Pod, und der Job-Controller erstellt einen Ersatz. MitOnFailurekann der Kubelet den Container im selben Pod neu starten. Verwenden SieNever, wenn separate Pods bei Fehlern und separate Protokolle die Diagnose erleichtern, und sorgen Sie dafür, dass jeder der beiden Wege sicher wiederaufgenommen werden kann. -
Wiederholungsgrenzwerte: Legen Sie
backoffLimitbasierend auf der Anzahl der vorübergehenden Fehler fest, die die Workload tolerieren kann. Verwenden SiepodFailurePolicy, um bei bekannten Exit-Codes, für die kein neuer Versuch erfolgen soll, sofort fehlzuschlagen oder, wie im Beispiel, zu verhindern, dass freiwillige Unterbrechungen das Retry-Budget verbrauchen. Eine Störung kann den Pod weiterhin anhalten; die Richtlinie ändert nur, wie der Job diesen Fehler wertet. -
Stichtage: Legen Sie fest
activeDeadlineSeconds, wann der Auftrag nach einer maximalen Gesamtlaufzeit beendet werden muss. Die Frist schließt Wiederholungsversuche ein und hat Vorrang vorbackoffLimit. Legen Sie keinen Stichtag fest, der kürzer als die erwartete Laufzeit plus Wiederholungs- und Wiederherstellungszeit ist. Ein fehlgeschlagener Auftrag wird nicht automatisch als neuer Auftrag neu gestartet. -
Ordnungsgemäße Beendigung: Behandeln Sie
SIGTERMdie Anwendung und legenterminationGracePeriodSecondsSie lange genug fest, um die Annahme neuer Arbeiten zu beenden, die aktuelle Einheit sicher abzuschließen oder aufzugeben, die Ausgabe zu leeren und einen Prüfpunkt zu speichern. Kubernetes sendetSIGKILL, wenn der Prozess die Schonfrist überschreitet, sodass regelmäßige Checkpoints weiterhin erforderlich bleiben. -
Bereinigung: Legen Sie
ttlSecondsAfterFinishedfest oder konfigurieren Sie CronJob-Verlaufslimits, um zu verhindern, dass sich abgeschlossene Jobs und Pods ansammeln. Bewahren Sie Job-Datensätze lange genug auf, um Protokolle zu erfassen und Vorfälle zu untersuchen.
Planen von Vertreibungen und Knotenwartung
Betrachten Sie das Blockieren von Verdrängungen nicht als wichtigste Wiederherstellungsstrategie für einen lang laufenden Auftrag. Für einen neu startbaren Batch-Job sollten Sie normalerweise kein PodDisruptionBudget (PDB) erstellen; der Job-Controller erstellt nach einer freiwilligen Unterbrechung einen Ersatz-Pod. Ein PDB schützt nur vor freiwilligen Auslagerungen und nicht vor Knotenausfall, ressourcenbedingter Auslagerung oder Präemption. Ein PDB, der null Unterbrechungen zulässt, kann auch Knotenabflüsse blockieren und AKS-Upgrades verzögern.
Verwenden Sie ein PDB nur, wenn eine parallele Batch-Workload eine Mindestanzahl gleichzeitig laufender Worker aufrechterhalten muss und Sie ihr Drain-Verhalten getestet haben. Verwenden Sie cluster-autoscaler.kubernetes.io/safe-to-evict: "false" ebenso nur für außergewöhnliche, nicht neu startbare Arbeiten. Die Anmerkung kann die Skalierung verhindern und die Kosten erhöhen, schützt jedoch nicht vor Knotenfehlern oder jedem Wartungsereignis.
Bei AKS-Upgrades werden alte Knoten vor dem Ersetzen gesperrt und entleert. Konfigurieren Sie geplante Wartungsfenster so, dass unterstützte AKS-Wartungsarbeiten auf Zeiträume mit geringeren Auswirkungen abgestimmt werden, stellen Sie jedoch sicher, dass die Workload weiterhin neu startbar bleibt, da der Zeitpunkt von Wartungen ungeplante Unterbrechungen nicht ausschließt. Führen Sie in AKS Standard Batchaufträge auf einem dedizierten Benutzerknotenpool aus, wenn sie eigene VM-Größen, Skalierungsgrenzwerte, Taints oder separate Upgradezeitpunkte benötigen. Verwenden Sie keine Spot-Knotenpools für Workloads, die sich nicht von einer Unterbrechung erholen können. Stellen Sie vor der Knotenwartung sicher, dass aktuelle Checkpoints nutzbar sind und dass ein anderer geeigneter Knotenpool über genügend Kontingent und Kapazität verfügt, um Ersatz-Pods auszuführen.
Überwachen Sie den Auftragsfortschritt und die Wiederherstellung
Verwenden Sie Kubernetes-Status, -Ereignisse und -Protokolle zusammen, wenn Sie einen lang andauernden Auftrag untersuchen:
kubectl get job checkpointed-batch --watch
kubectl describe job checkpointed-batch
kubectl get pods -l batch.kubernetes.io/job-name=checkpointed-batch
kubectl logs job/checkpointed-batch
Aktivieren Sie den verwalteten Azure Monitor-Dienst für Prometheus und Container Insights, um Protokolle aufzubewahren und den Auftragszustand mit Pod-Neustarts, Verdrängungen, Wartezeit, Knotenintegrität und Ressourcenauslastung zu korrelieren. Instrumentieren Sie die Anwendung mit Signalen für den Geschäftsfortschritt, z. B. abgeschlossene Elemente, fehlgeschlagene Elemente, letzte erfolgreiche Prüfpunktzeit, Verarbeitungsrate, Wiederholungsanzahl und geschätzte Abschlusszeit. Warnung bei einem fehlgeschlagenen Job, einem Job, der seine erwartete Dauer überschreitet, keinem Checkpoint innerhalb des Recovery Point Objective, wiederholten Pod-Ersetzungen, dauerhaft ausstehenden Pods und stagnierendem Verarbeitungsdurchsatz.
Sicherheit und Compliance
Wichtige Erkenntnis: Implementieren Sie CVE-Überprüfungen, Überwachungspfade und Compliance-Kontrollen, um Ihre Daten zu schützen und behördliche Anforderungen wie SOC 2, HIPAA und DSGVO zu erfüllen.
Sicherheit und Compliance sind für den Schutz Ihrer Daten von entscheidender Bedeutung und stellen sicher, dass Ihre KI-Pipeline gesetzliche Vorschriften erfüllt. Vorteile der Implementierung von Best Practices für Sicherheit und Compliance:
- Integrieren Sie das Scannen nach Common Vulnerabilities and Exposures (CVEs), um häufige Schwachstellen in Container-Images von Open-Source-Modellen zu erkennen.
- Verwenden Sie Microsoft Defender for Containers für Containerimages von Modellen, die in Ihrer Azure Container Registry gespeichert sind.
- Pflegen Sie einen Überwachungspfad der erfassten Daten, Modelländerungen und Metriken, um mit Ihren Organisationsrichtlinien konform zu bleiben.
- Unterstützt Compliance-Frameworks wie SOC 2 (durch die Audit-Protokollierung und Zugriffskontrollen von Azure), HIPAA (durch Verschlüsselung im Ruhezustand und bei der Übertragung sowie Netzwerkisolation) und die DSGVO (durch Optionen zur Datenresidenz und Richtlinien für die Zugriffsverwaltung).
In AKS Automatic verbessern standardmäßig vorkonfigurierte Sicherheitseinstellungen die grundlegende Sicherheitslage, jedoch bleiben Sicherheitskontrollen auf Modell-, Daten- und Pipeline-Ebene weiterhin erforderlich.
Planen von GPU-Workloads
Kernaussage: Stellen Sie GPUs über das NVIDIA-Device-Plugin bereit, fordern Sie GPUs explizit an und isolieren Sie teure GPU-Knoten mit Labels, Taints und Tolerations.
Kubernetes plant GPUs als erweiterte Ressourcen ein. Nachdem das NVIDIA-Geräte-Plug-in die GPUs auf einem Knoten registriert hat, fordert ein Pod eine GPU an, indem nvidia.com/gpu sowohl in resources.requests als auch in resources.limits festgelegt wird. Der folgende Pod fordert eine GPU an und zielt auf einen mit accelerator=nvidia gekennzeichneten Knotenpool ab:
apiVersion: v1
kind: Pod
metadata:
name: gpu-training-pod
labels:
app: gpu-training
spec:
restartPolicy: Never
nodeSelector:
accelerator: nvidia
tolerations:
- key: sku
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: trainer
image: nvcr.io/nvidia/cuda:12.4.1-runtime-ubuntu22.04
command:
- /bin/bash
- -c
- |
set -e
nvidia-smi
echo "GPU is available to the training container."
resources:
requests:
cpu: "1"
memory: 2Gi
nvidia.com/gpu: 1
limits:
cpu: "1"
memory: 2Gi
nvidia.com/gpu: 1
Erweiterte Ressourcen sind nicht überbelegt. Kubernetes behandelt einen GPU-Grenzwert als GPU-Anforderung, wenn nur der Grenzwert angegeben wird, das Festlegen beider Felder macht die Workloadabsicht jedoch explizit und hilft bei der Richtlinienüberprüfung.
Bereitstellen eines AKS GPU-Knotenpools
Erstellen Sie für AKS Standard einen dedizierten Benutzerknotenpool mit einer unterstützten GPU-VM-Größe von NVIDIA. Im folgenden Azure CLI-Beispiel wird ein automatisch skalierter Standard_NC4as_T4_v3-Knotenpool erstellt, das vom vorherigen Pod verwendete Label angewendet und die Knoten mit Taints versehen, um Workloads abzuhalten, die GPU-Knoten nicht ausdrücklich tolerieren:
RESOURCE_GROUP=myResourceGroup
AKS_CLUSTER=myAKSCluster
az aks nodepool add \
--resource-group "$RESOURCE_GROUP" \
--cluster-name "$AKS_CLUSTER" \
--name gpunp \
--mode User \
--node-vm-size Standard_NC4as_T4_v3 \
--node-count 0 \
--enable-cluster-autoscaler \
--min-count 0 \
--max-count 4 \
--labels accelerator=nvidia workload=training \
--node-taints sku=gpu:NoSchedule
Stellen Sie vor dem Erstellen des Knotenpools sicher, dass die VM-SKU in der Clusterregion verfügbar ist und dass das Abonnement über ein ausreichendes regionales und VM-Familienkontingent verfügt. Wählen Sie eine NC-Reihengröße basierend auf GPU-Speicher, GPU-Anzahl, CPU-zu-GPU-Verhältnis, lokalem Speicher, Netzwerk und den vom Schulungsframework benötigten CUDA-Funktionen aus. Beispielsweise eignen sich NCas T4 v3-Größen für viele Einzel-GPU- und kleinere Schulungsarbeitslasten, während NC A100 v4-Größen größere Modelle und GPU-Konfigurationen mit mehreren Instanzen unterstützen.
AKS Automatic kann berechtigte GPU-Kapazität als Reaktion auf ausstehende Pods bereitstellen. Die Arbeitslast muss weiterhin nvidia.com/gpu anfordern, und alle Knotenselektoren, Affinitäten, Tolerationen, Topologieeinschränkungen, Abonnementkontingente und die regionale SKU-Verfügbarkeit müssen erfüllbar sein. Verwenden Sie AKS Standard, wenn Sie eine feste VM-SKU, einen benutzerdefinierten Knotenpoollebenszyklus oder eine detaillierte Kontrolle über die SKALIERUNG und Topologie des GPU-Pools benötigen.
Überprüfen oder Installieren des NVIDIA-Geräte-Plug-Ins
AKS GPU-Konfigurationen können verwaltete GPU-Treiber und Geräte-Plug-In-Integration bereitstellen. Überprüfen Sie die effektive Konfiguration, bevor Sie ein anderes Plug-In installieren:
kubectl get nodes -L accelerator,kubernetes.azure.com/agentpool
kubectl get daemonsets --all-namespaces | grep -i nvidia
kubectl describe node | grep -A5 -E "Capacity:|Allocatable:|nvidia.com/gpu"
Führen Sie nicht mehrere NVIDIA-Geräte-Plug-In DaemonSets auf denselben Knoten aus. Wenn Ihre AKS-Konfiguration das Plug-In nicht verwaltet, registriert das folgende eigenständige DaemonSet NVIDIA GPUs mit dem Kubelet. Installieren Sie eine Geräte-Plug-In-Version, die von Ihrem NVIDIA-Treiber und Kubernetes-Versionen unterstützt wird:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nvidia-device-plugin
namespace: kube-system
labels:
app.kubernetes.io/name: nvidia-device-plugin
spec:
selector:
matchLabels:
app.kubernetes.io/name: nvidia-device-plugin
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
app.kubernetes.io/name: nvidia-device-plugin
spec:
priorityClassName: system-node-critical
nodeSelector:
accelerator: nvidia
tolerations:
- operator: Exists
containers:
- name: nvidia-device-plugin
image: nvcr.io/nvidia/k8s-device-plugin:v0.17.1
args:
- --fail-on-init-error=false
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-plugins
type: Directory
Vergewissern Sie sich, dass nvidia.com/gpu bei jedem GPU-Knoten unter den zuweisbaren Ressourcen angezeigt wird, bevor Sie Trainingsaufträge übermitteln.
Partition A100- und H100-GPUs mit MIG
NVIDIA Multi-Instance GPU (MIG) kann eine unterstützte A100- oder H100-GPU in isolierte GPU-Instanzen partitionieren. MIG ist nützlich für die Hyperparameteroptimierung und kleinere Feinabstimmungsaufträge, für die keine gesamte physische GPU erforderlich ist. Verwenden Sie vollständige GPUs für Workloads, für die alle GPU-Speicher, maximale Verbindungsbandbreite oder ein Profil erforderlich sind, das von der installierten GPU nicht unterstützt wird.
Verwenden Sie den NVIDIA GPU-Operator und den MIG-Manager, wenn Sie deklarative MIG-Lebenszyklusverwaltung benötigen. Der Betreiber sollte das Geräte-Plug-In und die MIG-Konfiguration für die betroffenen Knoten besitzen; kombinieren Sie es nicht mit einem zweiten eigenständigen Geräte-Plug-In. Die genauen Profilnamen und die Anzahl der Instanzen hängen vom GPU-Modell und der Speicherkapazität ab. Die folgende Konfiguration erstellt sieben 1g.10gb Instanzen für unterstützte 80-GB A100- oder H100-Konfigurationen:
apiVersion: v1
kind: Namespace
metadata:
name: gpu-operator
---
apiVersion: v1
kind: ConfigMap
metadata:
name: mig-parted-config
namespace: gpu-operator
data:
config.yaml: |
version: v1
mig-configs:
all-disabled:
- devices: all
mig-enabled: false
hptuning-1g10gb:
- devices: all
mig-enabled: true
mig-devices:
"1g.10gb": 7
---
apiVersion: v1
kind: Namespace
metadata:
name: ml-training
---
apiVersion: batch/v1
kind: Job
metadata:
name: mig-hyperparameter-trial
namespace: ml-training
labels:
workload: hyperparameter-tuning
spec:
backoffLimit: 2
template:
metadata:
labels:
workload: hyperparameter-tuning
spec:
restartPolicy: Never
nodeSelector:
accelerator: nvidia
nvidia.com/mig.config: hptuning-1g10gb
nvidia.com/mig.config.state: success
tolerations:
- key: sku
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: trial
image: nvcr.io/nvidia/cuda:12.4.1-runtime-ubuntu22.04
command:
- /bin/bash
- -c
- |
set -e
nvidia-smi
echo "Starting one hyperparameter trial on a MIG instance."
sleep 30
resources:
requests:
cpu: "2"
memory: 8Gi
nvidia.com/mig-1g.10gb: 1
limits:
cpu: "2"
memory: 8Gi
nvidia.com/mig-1g.10gb: 1
Konfigurieren Sie den MIG-Manager des GPU-Operators für die Nutzung der mig-parted-config ConfigMap, verwenden Sie die mixed MIG-Strategie, wenn Workloads benannte MIG-Profile anfordern, und bezeichnen Sie dann die Zielknoten:
kubectl label nodes \
-l accelerator=nvidia \
nvidia.com/mig.config=hptuning-1g10gb \
--overwrite
Das Ändern eines MIG-Layouts unterbricht Workloads, die bereits die GPU verwenden. Sperren Sie den Zielknoten und leeren Sie ihn, wenden Sie die Konfiguration während eines Wartungsfensters an, und vergewissern Sie sich, dass das angeforderte Profil in den zuweisbaren Ressourcen des Knotens vorhanden ist, bevor Sie Jobs einreichen.
Isolieren von GPU-Workloads mit Taints und Tolerationen
Ein NoSchedule Taint hält gewöhnliche Anwendungspods von teuren GPU-Knoten fern. Im Beispiel zum Erstellen des Knotenpools wird sku=gpu:NoSchedule angewendet. Der folgende vollständige Job enthält die passende Toleration und einen Node-Selector:
apiVersion: batch/v1
kind: Job
metadata:
name: isolated-gpu-training
spec:
backoffLimit: 3
template:
metadata:
labels:
app: isolated-gpu-training
spec:
restartPolicy: Never
nodeSelector:
accelerator: nvidia
workload: training
tolerations:
- key: sku
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: trainer
image: nvcr.io/nvidia/cuda:12.4.1-runtime-ubuntu22.04
command:
- /bin/bash
- -c
- |
set -e
nvidia-smi
sleep 60
resources:
requests:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
limits:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
Eine Toleration erlaubt die Einplanung, erzwingt jedoch nicht, dass der Pod auf einem GPU-Knoten eingeplant wird. Kombinieren Sie Tolerierungen mit einer GPU-Ressourcenanforderung und einem Knotenselektor oder einer Knotenaffinität. Stellen Sie sicher, dass erforderliche Plattformdaemonsets wie Netzwerk, Überwachung, Speicher und das Geräte-Plug-In den GPU-Taint tolerieren.
Verteilte Trainingsworkloads ausführen
Kernaussage: Verwenden Sie einen Trainingsoperator, um Worker-Identitäten und den Joblebenszyklus zu verwalten, die Netzwerkkommunikation zwischen mehreren Knoten zu validieren und Gang Admission zu verwenden, wenn alle Worker gemeinsam starten müssen.
Verteilte Schulungen verwenden mehrere Prozesse, um Daten, Modellstatus oder Pipelinephasen aufzuteilen. In Kubernetes kann ein Operator Worker-Pods erstellen, die Rendezvous-Konfiguration einfügen, den Status der Replikate überwachen, fehlgeschlagene Worker neu starten und den Job bereinigen. Installieren und versionieren Sie Schulungsoperatoren über die IaC- und Release-Prozesse Ihrer Plattform, anstatt einzelnen Teams zu erlauben, unkontrollierte clusterweite CRDs zu installieren.
Erstellen eines tragbaren CUDA-Schulungsimages
Das folgende Dockerfile erweitert das im Abschnitt zur Containerisierung beschriebene Dockerfile-Muster. Das Bild enthält die CUDA-Laufzeit- und PyTorch-Bibliotheken, während der kompatible NVIDIA-Treiber auf dem AKS GPU-Knoten verbleibt:
FROM pytorch/pytorch:2.4.1-cuda12.4-cudnn9-runtime
WORKDIR /workspace
COPY requirements.txt .
RUN python -m pip install --no-cache-dir -r requirements.txt
COPY train.py .
ENTRYPOINT ["python", "/workspace/train.py"]
Legen Sie das Basis-Image in Produktionsumgebungen über einen unveränderlichen Digest fest. Behalten Sie Datasets bei und ändern Sie häufig Prüfpunkte außerhalb des Bilds, und scannen Sie das resultierende Bild, bevor Sie es an Azure Container Registry verschieben.
Einen PyTorchJob ausführen
Der Kubeflow Training Operator stellt die CRD PyTorchJob bereit. Installieren Sie eine Schulungsoperator-Version, die mit Ihrer Kubernetes-Version kompatibel ist, bevor Sie dieses Manifest anwenden. Im folgenden Beispiel mit zwei Replikaten wird eine NCCL-All-Reduce-Operation über einen Master und einen Worker hinweg ausgeführt:
apiVersion: v1
kind: Namespace
metadata:
name: ml-training
labels:
purpose: ml-training
---
apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
name: pytorch-nccl-example
namespace: ml-training
spec:
runPolicy:
cleanPodPolicy: None
pytorchReplicaSpecs:
Master:
replicas: 1
restartPolicy: OnFailure
template:
metadata:
labels:
training-job: pytorch-nccl-example
spec:
nodeSelector:
accelerator: nvidia
tolerations:
- key: sku
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: pytorch
image: pytorch/pytorch:2.4.1-cuda12.4-cudnn9-runtime
command:
- python
- -c
- |
import os
import torch
import torch.distributed as dist
torch.cuda.set_device(0)
dist.init_process_group(backend="nccl")
value = torch.tensor(
[float(dist.get_rank() + 1)],
device="cuda"
)
dist.all_reduce(value)
print(
f"rank={dist.get_rank()} "
f"world_size={dist.get_world_size()} "
f"all_reduce_sum={value.item()}"
)
dist.destroy_process_group()
env:
- name: NCCL_DEBUG
value: INFO
- name: NCCL_SOCKET_IFNAME
value: eth0
- name: NCCL_IB_DISABLE
value: "1"
- name: TORCH_NCCL_ASYNC_ERROR_HANDLING
value: "1"
resources:
requests:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
limits:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
Worker:
replicas: 1
restartPolicy: OnFailure
template:
metadata:
labels:
training-job: pytorch-nccl-example
spec:
nodeSelector:
accelerator: nvidia
tolerations:
- key: sku
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: pytorch
image: pytorch/pytorch:2.4.1-cuda12.4-cudnn9-runtime
command:
- python
- -c
- |
import os
import torch
import torch.distributed as dist
torch.cuda.set_device(0)
dist.init_process_group(backend="nccl")
value = torch.tensor(
[float(dist.get_rank() + 1)],
device="cuda"
)
dist.all_reduce(value)
print(
f"rank={dist.get_rank()} "
f"world_size={dist.get_world_size()} "
f"all_reduce_sum={value.item()}"
)
dist.destroy_process_group()
env:
- name: NCCL_DEBUG
value: INFO
- name: NCCL_SOCKET_IFNAME
value: eth0
- name: NCCL_IB_DISABLE
value: "1"
- name: TORCH_NCCL_ASYNC_ERROR_HANDLING
value: "1"
resources:
requests:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
limits:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
Ersetzen Sie für die Produktionsschulung den Inlinetest durch Ihr Versionsschulungsbild und -skript. Richten Sie die Anzahl der Replikate an die Anzahl der GPUs und Prozesse aus, die vom Trainings-Framework benötigt werden.
Führen Sie einen TFJob aus.
Der Schulungsoperator stellt auch die TFJob CRD bereit. Im folgenden Beispiel werden synchrone TensorFlow-Schulungen über zwei GPU-Mitarbeiter hinweg ausgeführt, indem Sie Folgendes verwenden MultiWorkerMirroredStrategy:
apiVersion: v1
kind: Namespace
metadata:
name: ml-training
labels:
purpose: ml-training
---
apiVersion: kubeflow.org/v1
kind: TFJob
metadata:
name: tensorflow-multiworker-example
namespace: ml-training
spec:
runPolicy:
cleanPodPolicy: None
tfReplicaSpecs:
Worker:
replicas: 2
restartPolicy: OnFailure
template:
metadata:
labels:
training-job: tensorflow-multiworker-example
spec:
nodeSelector:
accelerator: nvidia
tolerations:
- key: sku
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: tensorflow
image: tensorflow/tensorflow:2.16.1-gpu
command:
- python
- -c
- |
import tensorflow as tf
strategy = tf.distribute.MultiWorkerMirroredStrategy()
print("workers:", strategy.num_replicas_in_sync)
with strategy.scope():
model = tf.keras.Sequential([
tf.keras.layers.Input(shape=(32,)),
tf.keras.layers.Dense(64, activation="relu"),
tf.keras.layers.Dense(1)
])
model.compile(
optimizer="adam",
loss="mean_squared_error"
)
features = tf.random.normal([4096, 32])
labels = tf.random.normal([4096, 1])
dataset = (
tf.data.Dataset.from_tensor_slices((features, labels))
.shuffle(4096)
.repeat()
.batch(64)
)
model.fit(dataset, epochs=2, steps_per_epoch=32)
resources:
requests:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
limits:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
Definieren Sie für das Parameter-Server-Training die Replikattypen Chief, Worker und PS gemäß der TensorFlow-Verteilungsstrategie. Messen Sie die resultierenden Netzwerk- und Parameterserverengpässe, bevor Sie die Replikatanzahl erhöhen.
Optimieren eines Modells mit KAITO
KAITO bietet eine auf AKS ausgerichtete Workspace-Abstraktion für Modellbereitstellung und Feinabstimmung. Aktivieren Sie das KAITO-Add-on oder installieren Sie eine kompatible KAITO-Version, bevor Sie ein Workspace anwenden. Stellen Sie sicher, dass die ausgewählte Voreinstellung, VM-SKU und Feinabstimmungsmethode von der installierten KAITO-Version unterstützt werden.
Der folgende Arbeitsbereich fordert eine A100-GPU-VM an und startet die QLoRA-Feinabstimmung für eine unterstützte Phi-3-Voreinstellung mithilfe eines öffentlich zugänglichen Datensatzes:
apiVersion: kaito.sh/v1alpha1
kind: Workspace
metadata:
name: workspace-tuning-phi-3-mini
resource:
instanceType: Standard_NC24ads_A100_v4
labelSelector:
matchLabels:
apps: phi-3-mini-tuning
tuning:
preset:
name: phi-3-mini-4k-instruct
method: qlora
input:
urls:
- https://huggingface.co/datasets/yahma/alpaca-cleaned/resolve/main/alpaca_data_cleaned.json
KAITO kann modellvoreingestellte Konfiguration und die GPU-Infrastruktur koordinieren, die vom Arbeitsbereich benötigt wird. Speichern Sie für den Produktionseinsatz das Trainingsdataset in einem genehmigten Azure-Speicherkonto, verwenden Sie privaten Zugriff und, sofern unterstützt, Workload Identity, und speichern Sie das resultierende Modell in einer verwalteten Modellregistry oder der Azure Container Registry. Behandeln Sie das Arbeitsbereichmanifest, die Eingabedatensatzversion, die voreingestellte Version, die Adapterkonfiguration und den Ausgabeimagedigest als einen versionsierten Schulungsdatensatz.
Konfigurieren der NCCL-Kommunikation mit AKS CNI
NVIDIA Collective Communications Library (NCCL) verarbeitet kollektive Vorgänge wie all-reduce. Verwenden Sie für einen tragbaren TCP-Basisplan auf AKS CNI die Pod-Netzwerkschnittstelle, normalerweise eth0und beginnen Sie mit NCCL_IB_DISABLE=1. Verwenden Sie auf unterstützten RDMA-fähigen VM-Größenklassen die dokumentierten RDMA-Konfigurationen von NVIDIA und Azure, und validieren Sie diese, bevor Sie NCCL_IB_DISABLE=0 festlegen.
Verwenden Sie diese Basisumgebungsvariablen:
-
NCCL_SOCKET_IFNAME=eth0wählt die Pod-Netzwerkschnittstelle aus. -
NCCL_DEBUG=INFObietet während der Validierung Diagnoseinformationen. Reduzieren Sie die Protokollebene nach der Optimierung. -
NCCL_IB_DISABLE=1wählt TCP-Sockets aus, wenn RDMA nicht konfiguriert ist. -
TORCH_NCCL_ASYNC_ERROR_HANDLING=1sorgt dafür, dass PyTorch beendet wird, anstatt nach asynchronen Kommunikationsfehlern unbegrenzt hängen zu bleiben.
Wenn die Netzwerkrichtlinie aktiviert ist, lassen Sie alle erforderlichen Rendezvous und NCCL-Datenverkehr zwischen Replikaten zu. NCCL kann dynamische Ports aushandeln, sodass eine schmale Richtlinie für feste Ports dazu führen kann, dass Schulungsaufträge hängen bleiben. Die folgende Richtlinie erlaubt die uneingeschränkte Pod-zu-Pod-Kommunikation nur zwischen Replikaten des PyTorch-Auftrags und ermöglicht die DNS-Auflösung:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-pytorch-nccl
namespace: ml-training
spec:
podSelector:
matchLabels:
training-job: pytorch-nccl-example
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
training-job: pytorch-nccl-example
egress:
- to:
- podSelector:
matchLabels:
training-job: pytorch-nccl-example
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
Benchmarken Sie NCCL unabhängig vom Modelltraining, bevor Sie hochskalieren. Vergleichen Sie die All-Reduce-Bandbreite, die Latenz, die GPU-Auslastung und den Trainingsdurchsatz bei jeder Anzahl von Workern. Mehr Worker können die Leistung beeinträchtigen, wenn die Kommunikation oder das Laden von Daten zum Engpass wird.
Verwenden Sie Gang-Scheduling und Workload-Warteschlangen
Wichtige Erkenntnis: Lassen Sie verteilte Mitarbeiter als Gruppe zu, und erzwingen Sie Mandanten-GPU-Kontingente, sodass teilweise geplante Aufträge keine GPUs reservieren, während sie auf verbleibende Mitarbeiter warten.
Der Standardmäßige Kubernetes-Scheduler platziert Pods einzeln. Bei einem verteilten Auftrag, der keine Fortschritte machen kann, solange nicht alle Worker laufen, kann eine teilweise Platzierung GPU-Kapazität verschwenden. Kueue stellt die Steuerung und Kontingentverwaltung bereit, bevor Pods mit der Ausführung beginnen. Volcano bietet einen Scheduler und ein auf PodGroups basierendes All-or-Nothing-Planungsmodell.
AKS Automatic stellt den Standardmäßigen Kubernetes-Scheduler und die automatische Knotenbereitstellung als Ausgangspunkt bereit. Übermitteln Sie gewöhnliche Jobs oder vom Operator verwaltete Trainings-Jobs mit präzisen Ressourcenanforderungen und lassen Sie die Plattform geeignete Kapazitäten bereitstellen. Dieses Verhalten garantiert keine atomare Zulassung für jeden Worker. Installieren Sie Kueue oder Volcano, wenn ein Workload Gang-Scheduling, Warteschlangen, Teamkontingente, faire Ressourcenverteilung oder benutzerdefiniertes Präemptionsverhalten erfordert.
Zuweisen eines GPU-Kontingents mit mehreren Mandanten mit Kueue
Installieren Sie eine Kueue-Version, die mit der Kubernetes-Version kompatibel ist, und aktivieren Sie Integrationen für die von Ihnen verwendeten Workloadtypen. Das folgende Manifest erstellt Folgendes:
- Eine GPU
ResourceFlavor, die Knoten mit der Bezeichnungaccelerator=nvidiazugeordnet ist. - Eine Vier-GPU
ClusterQueuefür Team A. - Eine ZWEI-GPU
ClusterQueuefür Team B. - Ein auf einen Namespace beschränktes
LocalQueuefür jedes Team. - Ein Zwei-Mitarbeiter-Job, den Kueue nur zulässt, wenn seine angeforderten Ressourcen verfügbar sind.
apiVersion: v1
kind: Namespace
metadata:
name: team-a
---
apiVersion: v1
kind: Namespace
metadata:
name: team-b
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
name: nvidia-gpu
spec:
nodeLabels:
accelerator: nvidia
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
name: team-a-gpu
spec:
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: team-a
queueingStrategy: BestEffortFIFO
resourceGroups:
- flavors:
- name: nvidia-gpu
resources:
- name: cpu
nominalQuota: "64"
- name: memory
nominalQuota: 256Gi
- name: nvidia.com/gpu
nominalQuota: "4"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
name: team-b-gpu
spec:
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: team-b
queueingStrategy: BestEffortFIFO
resourceGroups:
- flavors:
- name: nvidia-gpu
resources:
- name: cpu
nominalQuota: "32"
- name: memory
nominalQuota: 128Gi
- name: nvidia.com/gpu
nominalQuota: "2"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
name: gpu-queue
namespace: team-a
spec:
clusterQueue: team-a-gpu
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
name: gpu-queue
namespace: team-b
spec:
clusterQueue: team-b-gpu
---
apiVersion: batch/v1
kind: Job
metadata:
name: team-a-two-gpu-training
namespace: team-a
labels:
kueue.x-k8s.io/queue-name: gpu-queue
spec:
suspend: true
completions: 2
parallelism: 2
backoffLimit: 2
template:
metadata:
labels:
app: team-a-two-gpu-training
spec:
restartPolicy: Never
tolerations:
- key: sku
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: worker
image: nvcr.io/nvidia/cuda:12.4.1-runtime-ubuntu22.04
command:
- /bin/bash
- -c
- |
set -e
nvidia-smi
echo "Kueue admitted this worker."
sleep 120
resources:
requests:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
limits:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
Ein ClusterQueue Kontingent ist ein Planungskontingent, kein Azure Abonnementkontingent. Stellen Sie sicher, dass der AKS-Cluster die zugrunde liegende VM-Kapazität bereitstellen kann und dass Azure GPU-Kontingent für die aggregierte zugelassene Workload ausreicht. Verwenden Sie Kohorten und Kueue Fair-Sharing-Funktionen, wenn Teams sich gegenseitig ungenutzte Kontingente ausleihen können.
Verwenden Sie Vulkan als Alternative
Volcano ist eine Alternative, wenn Sie einen dedizierten Batchplaner mit Gang-Scheduling, Warteschlangen und Richtlinien für den Joblebenszyklus benötigen. Installieren Sie ein mit dem Cluster kompatibles Volcano-Release, bevor Sie dessen CRDs installieren. Der folgende Vulkanauftrag erfordert, dass beide GPU-Worker verfügbar sein müssen, bevor der Auftrag ausgeführt wird:
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: volcano-gpu-training
namespace: default
spec:
minAvailable: 2
schedulerName: volcano
policies:
- event: PodEvicted
action: RestartJob
- event: PodFailed
action: RestartJob
tasks:
- replicas: 2
name: worker
template:
metadata:
labels:
app: volcano-gpu-training
spec:
restartPolicy: OnFailure
nodeSelector:
accelerator: nvidia
tolerations:
- key: sku
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: worker
image: nvcr.io/nvidia/cuda:12.4.1-runtime-ubuntu22.04
command:
- /bin/bash
- -c
- |
set -e
nvidia-smi
echo "All Volcano workers were admitted."
sleep 120
resources:
requests:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
limits:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
Standardisieren Sie auf ein einziges primäres Warteschlangen- und Gang-Scheduling-System, es sei denn, Sie verfügen über ein getestetes Interoperabilitätsdesign. Mehrere Admission Controller oder Scheduler können es andernfalls erschweren, ausstehendes und Präemptionsverhalten nachzuvollziehen.
Konfigurieren von Schulungs- und Ableitungsprioritäten
Latenzkritische Inferenz erfordert häufig eine höhere Priorität als unterbrechbares Batch-Training. Die folgenden PriorityClass Ressourcen ermöglichen es Inference-Pods, Pods mit niedrigerer Priorität zu verdrängen, und verhindern gleichzeitig, dass Batch-Trainings-Pods andere Workloads verdrängen:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: training-batch
value: 10000
globalDefault: false
preemptionPolicy: Never
description: Batch training can wait and can be preempted by higher-priority workloads.
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: inference-critical
value: 100000
globalDefault: false
preemptionPolicy: PreemptLowerPriority
description: Latency-sensitive production inference can preempt lower-priority workloads.
Weisen Sie die Klasse über spec.priorityClassName in der Podvorlage zu. Die Pod-Priorität in Kubernetes und die Workload-Priorität in Kueue wirken sich auf unterschiedliche Phasen aus: Kueue steuert die Aufnahme in die Warteschlange, während die Kubernetes-Priorität nach der Zulassung die Planung und Verdrängung von Pods beeinflusst. Koordinieren Sie beide Richtlinien, sodass sie dieselbe Geschäftliche Priorität ausdrücken.
Präemption beendet Pods mit niedrigerer Priorität. Trainings-Workloads, die unterbrochen werden können, müssen Checkpoints in persistenten Speicher schreiben, doppelt ausgeführte Arbeit tolerieren und ohne auf knotenlokale Dateien angewiesen zu sein wieder anlaufen können.
Konfigurieren des freigegebenen Speichers und der Ressourcenverwaltung
Wichtige Erkenntnis: Ersetzen Sie die kleine Standardeinstellung /dev/shmder Containerlaufzeit, legen Sie Ressourcenanforderungen aus der beobachteten Auslastung fest, und konfigurieren Sie die Knotenskalierung um vollständige GPU-Workloadanforderungen.
Erhöhen /dev/shm für ML-Datenlader
PyTorch-Datenladeprogramme, TensorFlow-Eingabepipelines, NCCL und Python Multiprocessing können POSIX shared memory verwenden. Die Standardgröße des Containers für /dev/shm ist für das Training mit mehreren Prozessen häufig zu klein, was zu Abstürzen von Worker-Prozessen, Busfehlern oder einem scheinbaren Stillstand des Trainings führen kann.
Binden Sie ein arbeitsspeichergestütztes emptyDir unter /dev/shm ein und legen Sie ein explizites sizeLimit fest:
apiVersion: batch/v1
kind: Job
metadata:
name: shared-memory-training
spec:
backoffLimit: 2
template:
metadata:
labels:
app: shared-memory-training
spec:
restartPolicy: Never
nodeSelector:
accelerator: nvidia
tolerations:
- key: sku
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: trainer
image: pytorch/pytorch:2.4.1-cuda12.4-cudnn9-runtime
command:
- /bin/bash
- -c
- |
set -e
df -h /dev/shm
python -c '
import multiprocessing as mp
import torch
def worker(index):
value = torch.ones(1024, 1024)
print(f"worker={index}, sum={value.sum().item()}")
if __name__ == "__main__":
processes = [mp.Process(target=worker, args=(i,)) for i in range(4)]
for process in processes:
process.start()
for process in processes:
process.join()
if process.exitcode != 0:
raise SystemExit(process.exitcode)
'
volumeMounts:
- name: shared-memory
mountPath: /dev/shm
resources:
requests:
cpu: "8"
memory: 16Gi
nvidia.com/gpu: 1
limits:
cpu: "8"
memory: 16Gi
nvidia.com/gpu: 1
volumes:
- name: shared-memory
emptyDir:
medium: Memory
sizeLimit: 8Gi
Die speichergestützte emptyDir Nutzung zählt zur Speicherauslastung des Pods. Schließen Sie die maximale erwartete Nutzung des gemeinsam genutzten Speichers beim Festlegen des Grenzwerts für den Containerspeicher ein. Wenn /dev/shm über das effektive Speicherbudget hinaus anwächst, kann der Pod wegen Überschreitung seines Speicherlimits entfernt oder beendet werden.
Größe der CPU und des Arbeitsspeichers aus beobachteter Auslastung
Beginnen Sie mit einem Benchmark basierend auf repräsentativem Modell, Batchgröße, Sequenzlänge, Datenladeprogramm-Parallelität, Augmentation und Prüfpunktverhalten. Verwenden Sie dann Überwachungsdaten, um Folgendes anzupassen:
- Legen Sie CPU-Anforderungen hoch genug fest, um gpu-Eingabepipelines bereitgestellt zu halten. Beständige GPU-Leerlaufperioden können auf CPU- oder Speicherhunger hinweisen.
- Legen Sie Speicheranforderungen in der Nähe der stabilen Arbeitssatznutzung sowie einen Sicherheitsrand fest. Berücksichtigen Sie
/dev/shm, das Verhalten des Seiten-Caches, den Overhead des Framework-Allocators und Spitzen bei der Prüfpunktserialisierung. - Legen Sie Speichergrenzwerte oberhalb des beobachteten Höchstwerts fest. Untersuchen Sie
OOMKilledEreignisse, anstatt immer mehr Grenzwerte zu erhöhen, ohne die Ursache zu finden. - Prüfen Sie die CPU-Drosselung, bevor Sie restriktive CPU-Limits verwenden. CPU-Grenzwerte, die zu niedrig sind, können die GPU-Auslastung auch dann verringern, wenn die durchschnittliche CPU-Auslastung akzeptabel erscheint.
- Legen Sie Anforderungen und Grenzwerte für vorhersehbare, hochwertige Schulungsaufträge fest, wenn garantierte Servicequalität wichtiger ist als Knotenverpackung.
- Profilieren Sie jede signifikante Änderung der Modellgröße, Genauigkeit, Batchgröße, Arbeitsanzahl und Datenpipeline.
Verwenden Sie Perzentile über vollständige Trainingsläufe anstelle eines kurzfristigen Durchschnitts. Start-, Validierungs-, Prüfpunkt- und Daten-Shuffle-Phasen weisen häufig unterschiedliche Ressourcenspitzen auf.
Konfigurieren der automatischen Clusterkalierung für einen GPU-Knotenpool
Aktivieren Sie für AKS Standard die Cluster-Autoskaler im GPU-Benutzerknotenpool, und definieren Sie mindeste und maximale Kapazität:
RESOURCE_GROUP=myResourceGroup
AKS_CLUSTER=myAKSCluster
GPU_NODE_POOL=gpunp
az aks nodepool update \
--resource-group "$RESOURCE_GROUP" \
--cluster-name "$AKS_CLUSTER" \
--name "$GPU_NODE_POOL" \
--enable-cluster-autoscaler \
--min-count 0 \
--max-count 8
Sie können unterstützte Profileinstellungen des Cluster-Autoscalers auf Clusterebene anpassen. Testen Sie Profiländerungen sowohl mit Trainings- als auch mit Serving-Workloads:
az aks update \
--resource-group "$RESOURCE_GROUP" \
--name "$AKS_CLUSTER" \
--cluster-autoscaler-profile \
scan-interval=20s \
scale-down-unneeded-time=10m \
scale-down-delay-after-add=15m \
max-graceful-termination-sec=120
Ein ausstehender GPU-Pod löst die Skalierung nur aus, wenn die vollständigen Planungsanforderungen einer Knotenpoolvorlage entsprechen. Überprüfen Sie die GPU-Ressourcenanforderung, VM-Kapazität, Bezeichnungen, Taints, Tolerationen, Affinität, Topologieeinschränkungen, persistente Volumetopologie, maximale Knotenanzahl und Azure Kontingent, wenn die Skalierung nicht auftritt.
Scale-to-Zero eignet sich für unterbrechbare Trainingspools, führt jedoch zu zusätzlicher Latenz bei der VM-Bereitstellung, beim Abrufen von Images, beim Einbinden von Datensätzen und bei der Modellinitialisierung. Behalten Sie einen Mindestwert ungleich null bei, wenn sich die Startlatenz wesentlich auf die Serviceziele auswirkt. Pod-Disruption-Budgets, nicht evakuierbare Pods, lokaler Speicher und lange Kulanzfristen für die Beendigung können das Herunterskalieren verzögern.
AKS Automatic verwaltet die Bereitstellung und Skalierung von Knoten als Teil der Dienstbasispläne. Konzentrieren Sie sich auf genaue Podanforderungen und unterstützte Einschränkungen, anstatt eine manuelle GPU-Knotenpool-Autoskalierung zu konfigurieren.
Speichern von Datasets und Prüfpunkten
Kernaussage: Wählen Sie den Speicher anhand von Zugriffsmuster, Durchsatz, gemeinsamer Nutzung und Wiederherstellungsanforderungen aus, und speichern Sie Checkpoints dauerhaft außerhalb des Knotens, damit das Training nach Verdrängung oder Präemption wieder aufgenommen werden kann.
Halten Sie große Datensätze, Modellartefakte und Checkpoints aus Container-Images heraus. Wählen Sie eine Speicherschnittstelle basierend auf der Workload aus:
- Verwenden Sie Azure Blob Storage für große Objektdatensets, Modellartefakte und Hochkapazitätsdatenrepositorys.
- Verwenden Sie Azure Files, wenn mehrere Arbeitsknoten ein gemeinsam genutztes POSIX-Dateisystem erfordern.
- Verwenden Sie Azure-Datenträger für leistungsstarke Lese-/Schreib-Checkpoint- oder Cacheworkloads mit einem einzelnen Knoten, bei denen
ReadWriteOnceausreicht. - Verwenden Sie node-local ephemeral Speicher nur für rekonstruierbare Caches und temporäre Dateien.
Zugreifen auf große Datasets mit dem Azure Blob-CSI-Treiber
Aktivieren Sie den Azure Blob CSI-Treiber auf AKS Standard, wenn er noch nicht aktiviert ist:
RESOURCE_GROUP=myResourceGroup
AKS_CLUSTER=myAKSCluster
az aks update \
--resource-group "$RESOURCE_GROUP" \
--name "$AKS_CLUSTER" \
--enable-blob-driver
Das folgende Beispiel erstellt dynamisch einen Premium-Azure Blob-Container, der über NFS verfügbar gemacht wird, und stellt ihn in einem Schulungs pod bereit. Verwenden Sie für ein vorhandenes gesteuertes Dataset ein statisch definiertes Volume oder eine BlobFuse-Konfiguration mit den entsprechenden Identitäts- und privaten Netzwerksteuerelementen, anstatt einen leeren dynamischen Container zu erstellen:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ml-azureblob-nfs
provisioner: blob.csi.azure.com
parameters:
protocol: nfs
skuName: Premium_LRS
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: Immediate
mountOptions:
- -o attr_timeout=120
- -o entry_timeout=120
- -o negative_timeout=120
- -o actimeo=120
- -o noresvport
- -o nconnect=4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: blob-training-dataset
namespace: default
spec:
accessModes:
- ReadWriteMany
storageClassName: ml-azureblob-nfs
resources:
requests:
storage: 1Ti
---
apiVersion: batch/v1
kind: Job
metadata:
name: inspect-blob-dataset
namespace: default
spec:
backoffLimit: 2
template:
metadata:
labels:
app: inspect-blob-dataset
spec:
restartPolicy: Never
containers:
- name: dataset-reader
image: ubuntu:24.04
command:
- /bin/bash
- -c
- |
set -e
echo "Mounted dataset path:"
df -h /mnt/dataset
find /mnt/dataset -maxdepth 2 -type f | head -100
volumeMounts:
- name: dataset
mountPath: /mnt/dataset
volumes:
- name: dataset
persistentVolumeClaim:
claimName: blob-training-dataset
Vergleichen Sie die Protokoll- und Bereitstellungsoptionen mit repräsentativen Shardgrößen und Zugriffsmustern. Viele Mitarbeiter, die viele kleine Dateien lesen, können unterschiedliche Ergebnisse von sequenziellem Streaming großer Shards erzeugen. Erwägen Sie, Datensätze in Shards geeigneter Größe vorzuverarbeiten und knotenlokalen Cache-Speicher zu verwenden, wenn bei wiederholten Epochen andernfalls dieselben Objekte erneut heruntergeladen würden.
Teilen von Schulungsdaten mit Azure Files
Azure Files unterstützt ReadWriteMany, sodass verteilte Worker auf verschiedenen Knoten dieselbe Freigabe einbinden können. Premium-Azure Files ist geeignet, wenn die Workload vorhersehbare Dateisystemleistung erfordert und die ausgewählte Region die erforderliche Redundanzoption unterstützt.
Das folgende Manifest erstellt eine Premium-Azure-Files-Freigabe und bindet sie in zwei parallele Worker-Pods ein:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ml-azurefile-premium
provisioner: file.csi.azure.com
parameters:
skuName: Premium_LRS
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: Immediate
mountOptions:
- dir_mode=0770
- file_mode=0660
- uid=1000
- gid=1000
- mfsymlinks
- cache=strict
- actimeo=30
- nosharesock
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: shared-training-data
namespace: default
spec:
accessModes:
- ReadWriteMany
storageClassName: ml-azurefile-premium
resources:
requests:
storage: 100Gi
---
apiVersion: batch/v1
kind: Job
metadata:
name: shared-data-workers
namespace: default
spec:
completions: 2
parallelism: 2
completionMode: Indexed
backoffLimitPerIndex: 2
template:
metadata:
labels:
app: shared-data-workers
spec:
restartPolicy: Never
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: worker
image: ubuntu:24.04
command:
- /bin/bash
- -c
- |
set -e
WORKER_INDEX="${JOB_COMPLETION_INDEX:-0}"
echo "worker=${WORKER_INDEX}" \
> "/mnt/shared/worker-${WORKER_INDEX}.txt"
ls -la /mnt/shared
volumeMounts:
- name: shared-data
mountPath: /mnt/shared
volumes:
- name: shared-data
persistentVolumeClaim:
claimName: shared-training-data
Vermeiden Sie, dass jeder Mitarbeiter wiederholt ein Verzeichnis aufzählt, das Millionen von Dateien enthält. Verwenden Sie ein Manifest oder eine deterministische Shard-Zuweisung, damit jeder Worker weiß, welche Objekte er lesen soll.
Prüfpunkt für beständigen Speicher
Ein Prüfpunkt sollte genügend Zustand enthalten, um ordnungsgemäß fortzusetzen, z. B. Modellgewichtungen, Optimierzustand, Zeitplanzustand, Skalierungszustand, Epoche oder Schrittzahl, Zufallszahlengeneratorstatus und Datenladeposition, wenn unterstützt. Schreiben Sie Prüfpunkte regelmäßig und vor der ordnungsgemäßen Beendigung.
Der folgende Job schreibt atomare PyTorch-Checkpoints in Azure Files, stellt den neuesten Checkpoint nach einem Containerneustart oder einer Pod-Ersetzung wieder her und behandelt SIGTERM so, dass Präemption jüngste Fortschritte bewahren kann:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ml-checkpoints-azurefile
provisioner: file.csi.azure.com
parameters:
skuName: Premium_LRS
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: Immediate
mountOptions:
- dir_mode=0770
- file_mode=0660
- uid=1000
- gid=1000
- mfsymlinks
- cache=strict
- actimeo=30
- nosharesock
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: model-checkpoints
namespace: default
spec:
accessModes:
- ReadWriteMany
storageClassName: ml-checkpoints-azurefile
resources:
requests:
storage: 100Gi
---
apiVersion: batch/v1
kind: Job
metadata:
name: checkpointed-pytorch-training
namespace: default
spec:
backoffLimit: 6
template:
metadata:
labels:
app: checkpointed-pytorch-training
spec:
restartPolicy: OnFailure
terminationGracePeriodSeconds: 120
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: trainer
image: pytorch/pytorch:2.4.1-cuda12.4-cudnn9-runtime
command:
- python
- -c
- |
import os
import signal
import sys
import time
import torch
checkpoint_path = "/checkpoints/latest.pt"
temporary_path = "/checkpoints/latest.pt.tmp"
state = {"epoch": 0, "value": torch.tensor([0.0])}
if os.path.exists(checkpoint_path):
state = torch.load(checkpoint_path, map_location="cpu")
print(f"Restored epoch {state['epoch']}", flush=True)
def save_checkpoint():
torch.save(state, temporary_path)
os.replace(temporary_path, checkpoint_path)
print(f"Saved epoch {state['epoch']}", flush=True)
def terminate(signum, frame):
print(f"Received signal {signum}", flush=True)
save_checkpoint()
sys.exit(143)
signal.signal(signal.SIGTERM, terminate)
signal.signal(signal.SIGINT, terminate)
for epoch in range(state["epoch"] + 1, 21):
state["epoch"] = epoch
state["value"] += 1
time.sleep(10)
if epoch % 2 == 0:
save_checkpoint()
save_checkpoint()
print("Training completed.", flush=True)
volumeMounts:
- name: checkpoints
mountPath: /checkpoints
resources:
requests:
cpu: "1"
memory: 2Gi
limits:
cpu: "1"
memory: 2Gi
volumes:
- name: checkpoints
persistentVolumeClaim:
claimName: model-checkpoints
Verwenden Sie eine Retain Rückforderungsrichtlinie oder ein unabhängig verwaltetes Speicherkonto für Produktionsprüfpunkte, sodass das Löschen eines PVC den einzigen Wiederherstellungspunkt nicht unbeabsichtigt löscht. Für verteiltes datenparalleles Training sollten normalerweise Rang 0 den globalen Checkpoint schreiben, oder Sie verwenden ein vom Framework unterstütztes Sharded-Checkpoint-Format. Verhindern, dass mehrere Rangfolgen gleichzeitig dieselbe Datei schreiben.
Testen Sie die Wiederherstellung, indem Sie während eines Testlaufs außerhalb der Produktion absichtlich einen Worker-Pod löschen. Stellen Sie sicher, dass der Controller die Arbeitsauslastung neu erstellt, der neue Pod das gleiche persistente Volume einhält, und die Schulung wird aus dem erwarteten Schritt fortgesetzt.
Überwachen der GPU-Auslastung und des Schulungsdurchsatzes
Wichtige Erkenntnis: Überwachen Sie GPU-Compute, GPU-Speicher, Datenpipelinedurchsatz, Schrittdauer und Prüfpunktaktivität zusammen, sodass Sie die Berechnungssättigung von CPU, Netzwerk oder Speicherengpässen unterscheiden können.
Aktivieren Sie Azure Monitor verwalteten Dienst für Prometheus und Containereinblicke, um Kubernetes-Status, Containerprotokolle, Knotenintegrität und Prometheus-Metriken zu korrelieren. Verwenden Sie bewährte Methoden für die Überwachung von AKS, wenn Sie Alarmierung, Datenaufbewahrung und operative Dashboards entwerfen.
NVIDIA-GPU-Metriken erfassen
NVIDIA Data Center GPU Manager (DCGM) Exporter macht Prometheus-Metriken für NVIDIA GPUs verfügbar. Wenn der NVIDIA GPU-Operator bereits DCGM-Exporter bereitstellt, stellen Sie keinen doppelten Exporter bereit. Konfigurieren Sie Azure Monitor verwalteten Prometheus, um den vorhandenen Exporter zu verschrotten.
Das folgende PodMonitor verwendet die von Azure Monitor verwaltete Prometheus-CRD und zielt auf DCGM-Exporter-Pods im gpu-operator-Namespace ab. Passen Sie die Bezeichnungsauswahl an die Bezeichnungen an, die von Ihrem installierten Exporter verwendet werden:
apiVersion: azmonitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: nvidia-dcgm-exporter
namespace: gpu-operator
spec:
selector:
matchLabels:
app: nvidia-dcgm-exporter
podMetricsEndpoints:
- port: metrics
interval: 30s
scrapeTimeout: 10s
Überprüfen Sie den Portnamen des Exporter-Dienstes oder Pods, bevor Sie den Monitor anwenden. Zu den allgemeinen DCGM-Metriken gehören:
| Metric | Purpose |
|---|---|
DCGM_FI_DEV_GPU_UTIL |
Prozentsatz der Zeit, in der die GPU aktiv ist |
DCGM_FI_DEV_FB_USED |
Verwendeter Framepufferspeicher |
DCGM_FI_DEV_FB_FREE |
Freier Framepufferspeicher |
DCGM_FI_DEV_MEM_COPY_UTIL |
Auslastung der Speicherkopier-Engine |
DCGM_FI_DEV_POWER_USAGE |
GPU-Stromverbrauch |
DCGM_FI_DEV_GPU_TEMP |
GPU-Temperatur |
DCGM_FI_DEV_XID_ERRORS |
NVIDIA XID-Fehlerereignisse |
Die Metrikverfügbarkeit hängt von der GPU, dem Treiber, dcGM und den Exporteurversionen ab.
Exportieren von Trainingsdurchsatzmetriken
Statten Sie die Trainingsanwendung mit Metriken auf Workload-Ebene aus. Zu den nützlichen Metriken gehören:
-
ml_training_samples_totalfür kumulativ verarbeitete Proben oder Token. -
ml_training_steps_totalfür abgeschlossene Optimizer-Schritte. -
ml_training_step_duration_secondsfür schrittlatenz. -
ml_training_checkpoint_duration_secondsfür prüfpunktlatenz. -
ml_training_data_wait_secondsfür die Wartezeit auf Eingabedaten. - Modellspezifische Verlustwerte, Lernrate, Gradientennorm und Validierungsmetriken.
Das folgende ausführbare Beispiel stellt synthetische Trainingsmetriken am Port 8000 bereit. Ersetzen Sie die Simulation durch Metriken, die von der realen Trainingsschleife ausgegeben werden:
apiVersion: v1
kind: Namespace
metadata:
name: ml-observability
---
apiVersion: v1
kind: ConfigMap
metadata:
name: training-metrics-server
namespace: ml-observability
data:
server.py: |
import http.server
import threading
import time
state = {
"samples": 0,
"steps": 0,
"last_step_duration": 0.0,
}
def train():
while True:
started = time.time()
time.sleep(1)
state["samples"] += 256
state["steps"] += 1
state["last_step_duration"] = time.time() - started
class MetricsHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
if self.path != "/metrics":
self.send_response(404)
self.end_headers()
return
body = (
"# HELP ml_training_samples_total Samples processed.\n"
"# TYPE ml_training_samples_total counter\n"
f"ml_training_samples_total{{job_name=\"metrics-demo\"}} "
f"{state['samples']}\n"
"# HELP ml_training_steps_total Training steps completed.\n"
"# TYPE ml_training_steps_total counter\n"
f"ml_training_steps_total{{job_name=\"metrics-demo\"}} "
f"{state['steps']}\n"
"# HELP ml_training_step_duration_seconds "
"Duration of the most recent training step.\n"
"# TYPE ml_training_step_duration_seconds gauge\n"
f"ml_training_step_duration_seconds"
f"{{job_name=\"metrics-demo\"}} "
f"{state['last_step_duration']}\n"
).encode("utf-8")
self.send_response(200)
self.send_header("Content-Type", "text/plain; version=0.0.4")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def log_message(self, format, *args):
return
threading.Thread(target=train, daemon=True).start()
http.server.ThreadingHTTPServer(("0.0.0.0", 8000), MetricsHandler).serve_forever()
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: training-metrics-demo
namespace: ml-observability
spec:
replicas: 1
selector:
matchLabels:
app: training-metrics-demo
template:
metadata:
labels:
app: training-metrics-demo
spec:
containers:
- name: metrics
image: python:3.12-slim
command:
- python
- /app/server.py
ports:
- name: metrics
containerPort: 8000
readinessProbe:
httpGet:
path: /metrics
port: metrics
initialDelaySeconds: 2
periodSeconds: 10
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
volumeMounts:
- name: application
mountPath: /app
readOnly: true
volumes:
- name: application
configMap:
name: training-metrics-server
---
apiVersion: azmonitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: training-metrics-demo
namespace: ml-observability
spec:
selector:
matchLabels:
app: training-metrics-demo
podMetricsEndpoints:
- port: metrics
path: /metrics
interval: 30s
scrapeTimeout: 10s
Fügen Sie für einen echten verteilten Auftrag stabile Bezeichnungen wie Modellname, Modellversion, Auftragsname, Ausführungs-ID, Replikatrolle und Team ein. Verwenden Sie keine unbegrenzten Labels wie Beispiel-IDs, Anfrage-IDs oder Pfade zu Rohdatensätzen, da Labels mit hoher Kardinalität die Überwachungskosten und die Abfragelatenz erhöhen.
Erstellen von GPU- und Durchsatzdashboards
Verwenden Sie PromQL-Abfragen wie die folgenden als Ausgangspunkte, und überprüfen Sie die Metrik-Labels anhand Ihres Exporters:
avg by (namespace, pod, gpu) (
avg_over_time(DCGM_FI_DEV_GPU_UTIL[5m])
)
Die folgende Abfrage berechnet die Auslastung des Framebuffer-Speichers als Prozentsatz:
100 *
DCGM_FI_DEV_FB_USED
/
(DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE)
Die folgende Abfrage berechnet Schulungsbeispiele pro Sekunde:
sum by (job_name) (
rate(ml_training_samples_total[5m])
)
Die folgende Abfrage zeigt die durchschnittliche Schrittdauer an:
avg by (job_name) (
ml_training_step_duration_seconds
)
Interpretieren Sie diese Signale zusammen:
- Niedrige GPU-Auslastung und hohe Datenwartezeit geben in der Regel Speicher, Netzwerk, Vorverarbeitung oder CPU-Hunger an.
- Hohe GPU-Auslastung mit erwartetem Durchsatz gibt an, dass der Accelerator effektiv verwendet wird.
- Eine hohe GPU-Speicherauslastung und wiederholte Out-of-Memory-Fehler deuten darauf hin, dass Batchgröße, Sequenzlänge, Aktivierungsspeicher, Optimiererzustand oder Fragmentierung angepasst werden müssen.
- Ein sinkender Durchsatz bei stabiler GPU-Auslastung kann auf längere Sequenzen, Kommunikationsaufwand, thermisches Verhalten oder eine Änderung der Modellberechnung hindeuten.
- Eine niedrige GPU-Auslastung bei zugewiesenen GPUs weist auf ungenutzte Kapazität hin, die möglicherweise verringert, anders in die Warteschlange eingeordnet oder mit MIG partitioniert werden kann.
- Lange Prüfpunktdauer kann die Vorbehebung teuer machen und die Menge der wiederholten Arbeit nach der Wiederherstellung erhöhen.
Erstellen Sie Warnungen für dauerhafte GPU-Unterverwendung, GPU-Speicher in der Nähe von Kapazität, XID-Fehler, verzögerten Schulungsdurchsatz, fehlgeschlagene Mitarbeiter, ausstehende arbeitsgangplanmäßige Workloads und Prüfpunkte, die nicht innerhalb des erwarteten Wiederherstellungspunktziels abgeschlossen wurden.
Häufig gestellte Fragen (FAQ)
Was ist der Unterschied zwischen AKS Automatic und AKS Standard for MLOps?
AKS Automatic stellt vorkonfigurierte Standardwerte für Knotenpools, Netzwerke, Sicherheit und Upgrades bereit, sodass MLOps-Teams sich auf Workloaddefinitionen und Governance konzentrieren können. AKS Standard erfordert eine manuelle Konfiguration dieser Plattformkomponenten, bietet jedoch eine tiefere Kontrolle über benutzerdefinierte Architekturen und Skalierungsanforderungen.
Wie kann ich ML-Modelle in AKS versionieren?
Versionieren Sie Ihre Modelle, indem Sie Modellgewichte, Metadaten und Konfigurationen in Container-Images mit semantischen Versions-Tags verpacken. Speichern Sie diese Images in Azure Container Registry, und verweisen Sie auf bestimmte Versionen in Ihren Kubernetes-Bereitstellungsmanifesten, um die Konsistenz in allen Umgebungen sicherzustellen.
Wie kann ich GPU-Workloads auf AKS planen?
Stellen Sie sicher, dass das NVIDIA-Device-Plugin verfügbar ist, damit GPU-Knoten nvidia.com/gpu ankündigen. Stellen Sie in AKS Standard einen dedizierten GPU-Benutzerknotenpool mit einer unterstützten VM-Größe bereit, z. B. eine SKU der Standard_NC-Serie, und konfigurieren Sie Knotenbeschriftungen, einen NoSchedule Taint- und Cluster-Autoscaler-Grenzwert. Fordern Sie in jedem Training-Pod nvidia.com/gpu an, wählen Sie einen dafür geeigneten GPU-Knoten aus und fügen Sie die passende Toleration hinzu. AKS Automatic kann anhand von Pod-Anforderungen geeignete GPU-Kapazität bereitstellen, abhängig von unterstützten SKUs, der regionalen Verfügbarkeit, Schedulingeinschränkungen und dem Kontingent des Azure-Abonnements.
Wie kann ich verteilte Schulungsaufträge auf AKS ausführen?
Installieren Sie den Kubeflow Training Operator und übermitteln Sie ein PyTorchJob oder TFJob, um verteilte Replikate, die Rendezvous-Konfiguration, das Neustartverhalten und den Jobstatus zu verwalten. KAITO bietet eine auf AKS ausgerichtete Arbeitsbereichsabstraktion für unterstützte Workflows zur Modell-Feinabstimmung und kann die GPU-Infrastruktur mit Modellvorgaben koordinieren. Konfigurieren Sie für das PyTorch-Training mit mehreren Knoten NCCL über das AKS CNI-Podnetzwerk und testen Sie dessen Leistung, erlauben Sie den Datenverkehr zwischen den Workern durch entsprechende Netzwerkrichtlinien, und verwenden Sie eine unterstützte RDMA-Konfiguration, wenn die ausgewählte VM-SKU und die Workload dies erfordern.
Wie verwalte ich das GPU-Kontingent für mehrere Teams?
Installieren Sie Kueue und definieren Sie ClusterQueue Ressourcen mit CPU-, Arbeitsspeicher- und nvidia.com/gpu Quoten. Weisen Sie dann den Namespace jedes Teams über ein LocalQueue der jeweils zugewiesenen Quote zu. Verwenden Sie Kueue-Kohorten oder faire Ressourcenteilung, wenn Teams ungenutzte Kapazitäten nutzen können. Vulkan ist eine Alternative, wenn Sie einen Batchplaner mit all-oder-nichts-Arbeiter-Zulassung benötigen. Koordinieren Sie die Priorität der Warteschlange mit Kubernetes-PriorityClassRessourcen, sodass latenzempfindliche Inferenz unterbrechbares Training verdrängen kann, und stellen Sie sicher, dass verdrängbare Trainingsjobs anhand von Checkpoints im persistenten Speicher wiederhergestellt werden.
Was sind die bewährten Methoden zum Ausführen lang laufender Batchaufträge auf AKS?
Verwenden Sie ein Kubernetes Job für endliche Arbeit und eine CronJob für geplante Arbeit. Speichern Sie Prüfpunkte und bestätigte Ausgaben außerhalb des Pods, gestalten Sie die Verarbeitung idempotent, behandeln Sie SIGTERM, und legen Sie explizite Ressourcenanforderungen, Wiederholungsgrenzen, Fristen und Bereinigungsrichtlinien fest. Gehen Sie davon aus, dass Knotenwartung oder -ausfall zum Ersetzen des Pods führen können, und testen Sie, ob der Ersatz-Pod seinen Checkpoint ordnungsgemäß wiederherstellt. Überwachen Sie den Auftragsstatus, Pod-Ereignisse, Protokolle, das Alter des Prüfpunkts, den Durchsatz und das Wiederholungsverhalten. Normale neustartbare Jobs erfordern weder Gang-Scheduling noch ein PDB. Verwenden Sie diese Steuerelemente nur, wenn parallel laufende Worker gleichzeitig starten oder eine getestete Mindestparallelität aufrechterhalten müssen.
Verwandte Inhalte
Erfahren Sie mehr über Best Practices in anderen Bereichen Ihrer Anwendungsbereitstellung und -vorgänge in AKS: