Aanbevolen procedures voor machine learning-bewerkingen (MLOps) in Azure Kubernetes Service (AKS)

Van toepassing op: ✔️ AKS Automatic ✔️ AKS Standard

MLOps is een set procedures voor het implementeren, bewaken en beheren van machine learning-modellen in productieomgevingen.

Belangrijke aanbevolen procedures voor MLOps die in dit artikel worden behandeld:

  • Infrastructuur als Code (IaC)
  • Containerisatie
  • Modelbeheer en versiebeheer
  • Automatisering
  • Schaalbaarheid en resourcebeheer
  • Betrouwbaarheid van langlopende batchtaken
  • Beveiliging en naleving

In dit artikel worden aanbevolen procedures en overwegingen beschreven waarmee u rekening moet houden bij het gebruik van MLOps in AKS. Zie Machine Learning-bewerkingen (MLOps) voor AI- en machine learning-werkstromen voor meer informatie over MLOps.

Uw AKS-modus voor MLOps kiezen

AKS ondersteunt twee clustermodi: AKS Automatic en AKS Standard. Kies AKS Automatisch als u een basislijn wilt die gereed is voor productie met minder dag-2-platformbeheer. Kies AKS Standard als u meer controle nodig hebt over de clusterinfrastructuur en platformconfiguratie.

De MLOps-procedures in dit artikel zijn van toepassing op beide modi. De verantwoordelijkheid voor de implementatie verschilt echter per modus: AKS Automatic biedt meer vooraf geconfigureerde standaardwaarden, terwijl AKS Standard doorgaans explicieter platformconfiguratie en levenscycluseigendom vereist.

Area AKS Automatisch AKS Standard
Basisconfiguratie van het cluster Voorgeconfigureerde knooppuntgroepen, netwerkfunctionaliteit en monitoring, standaard beschikbaar Vereist handmatige configuratie van knooppuntgroepen, CNI en waarneembaarheidsstack
Bewerkingen van systeemknooppuntgroepen Automatisch inrichten en schalen van knooppunten die worden beheerd door de service Operator moet de grootte, schaalregels en onderhoudsvensters van de knooppuntgroep configureren
Maatregelen voor de beveiligingsbasislijn Netwerkbeleid, beveiligingsstandaarden voor pods en workloadidentiteit standaard ingeschakeld Operators moeten netwerkbeleid, podbeveiliging en identiteitsinstellingen expliciet inschakelen en configureren
Netwerkbasislijn Vooraf geconfigureerde Azure CNI-overlay met standaardingresspatronen Volledige flexibiliteit om de CNI-invoegtoepassing te kiezen, aangepaste ingangscontrollers te configureren en netwerktopologie te definiëren
Bewerkingen en upgrades Automatische knooppuntinstallatiekopieën en Kubernetes-versie-upgrades Operators plannen en beheren de timing en implementatiestrategie van de upgrade
Focus op MLOps-implementatie Standaardwaarden valideren, beheren en afstemmen Platformbesturingselementen ontwerpen en configureren
GPU-capaciteit en -planning In aanmerking komende GPU-capaciteit kan automatisch beschikbaar worden gesteld op basis van resourceaanvragen van workloads en planningsbeperkingen, afhankelijk van regionale SKU-beschikbaarheid en abonnementsquota Operators maken en beheren GPU-knooppuntgroepen, labels, taints, limieten voor automatische schaalaanpassing, stuurprogramma's en configuratie van apparaatinvoegtoepassingen
Gedistribueerde training Standaard-Kubernetes-planning en automatische inrichting van knooppunten bieden een startpunt; trainingsoperators, gangplanners en topologieafstemming blijven keuzes op workloadniveau Operators installeren expliciet trainingsoperators en schedulers en ontwerpen GPU-knooppuntgroepen, netwerkconfiguratie, schaalbaarheid en plaatsing voor gedistribueerde workloads

Infrastructuur als code (IaC)

Belangrijke punten: Definieer en versie IaC-sjablonen voor elke fase van uw AI-pijplijn om consistentie, kosteneffectiviteit en snellere implementaties te garanderen.

IaC maakt consistente en reproduceerbare infrastructuurinrichting en -beheer mogelijk voor een reeks toepassingstypen. Bij verschillende toepassingsimplementaties kan uw IaC-implementatie in de AI-pijplijn veranderen, omdat de rekenkracht en resources die nodig zijn voor deductie, het leveren, trainen en verfijnen van modellen kunnen variëren. Het definiëren en versiebeheer van IaC-sjablonen voor uw AI-ontwikkelaarsteams kan helpen bij het garanderen van consistentie en kosteneffectiviteit in verschillende taaktypen, terwijl de hardwarevereisten worden verduidelijkt en het implementatieproces wordt versneld.

In AKS Automatic kan IaC zich meer richten op workloaddefinities, beleidsconsistentie en omgevingsconsistentie ten opzichte van de standaardinstellingen van het platform. In AKS Standard bevat IaC doorgaans meer expliciete clusterplatforminstellingen, zoals netwerken, schalen en operationele configuratieopties.

Containerisatie

Belangrijkste conclusie: Verpak modelgewichten, metagegevens en configuraties in containerimages om draagbaarheid, vereenvoudigd versiebeheer en lagere opslagkosten mogelijk te maken.

Door uw modelgewichten, metagegevens en configuraties in containerinstallatiekopieën te beheren, zijn draagbaarheid, vereenvoudigde versiebeheer en lagere opslagkosten in de loop van de tijd mogelijk. Met containerisatie kunt u het volgende doen:

  • Gebruik bestaande containerinstallatiekopieën, met name voor grote taalmodellen (LLM's), variërend van miljoenen tot miljarden parameters in grootte en stabiele diffusiemodellen, opgeslagen in beveiligde containerregisters.
  • Vermijd een enkel storingspunt in uw pijplijn door meerdere lichtgewicht containers te gebruiken die de unieke afhankelijkheden voor elke taak bevatten, in plaats van één grote image te onderhouden.
  • Sla grote tekst- en beelddatasets buiten uw basiscontainerimage op en verwijs ernaar wanneer dat tijdens runtime nodig is. Ga aan de slag met de Kubernetes AI Toolchain Operator (KAITO) om een LLM in AKS te implementeren.

Besturingselementen voor de toeleveringsketen van containers blijven essentieel in beide modi. Zelfs met vooraf geconfigureerde platformstandaarden in AKS Automatic zijn de herkomst van afbeeldingen, scannen en runtimebeveiliging nog steeds de belangrijkste MLOps-verantwoordelijkheden.

Dockerfile-patroon voor ML-workloads:

Gebruik voor GPU-trainingsworkloads een expliciete tag van een CUDA-ingeschakelde basisimage (bijvoorbeeld pytorch/pytorch:2.4.1-cuda12.4-cudnn9-runtime) in plaats van een verwijzing naar een basisimage zonder tag. Maak de afbeelding vast aan digest in productie om reproduceerbare builds en voorspelbaar CUDA/cuDNN-gedrag te garanderen. Behoud afzonderlijke CPU- en GPU-installatiekopieën, zodat scheduler-plaatsing en runtimeafhankelijkheden expliciet blijven.

Modelbeheer en versiebeheer

Belangrijkste leerpunt: Uw modellen systematisch versien om consistentie tussen omgevingen te behouden en snellere iteratie mogelijk te maken met parametersefficiënte afstemmingsmethoden.

Modelbeheer en versiebeheer zijn essentieel voor het bijhouden van wijzigingen in uw modellen in de loop van de tijd. Door uw modellen te versieren, kunt u het volgende doen:

  • Behoud consistentie in uw modelcontainers voor een eenvoudige implementatie in verschillende omgevingen.
  • Gebruik parameter-efficiënte fine-tuningmethoden (PEFT) om sneller te itereren met een subset van de modelgewichten en nieuwe versies te beheren in lichtgewicht containers.

In AKS Automatic kunnen vooraf geconfigureerde platformbasislijnen de omgevingspariteit vereenvoudigen. In AKS Standard moeten teams vaak pariteit explicieter afdwingen via platform- en implementatieconfiguratie.

Automatisering

Belangrijke punten: Automatiseer gegevensopname, modelprestaties bewaken en pijplijnen opnieuw trainen om handmatige fouten te verminderen en consistentie in de ML-levenscyclus te garanderen.

Automatisering helpt handmatige fouten te verminderen, efficiëntie te verhogen en consistentie in de ML-levenscyclus te garanderen. Door taken te automatiseren, kunt u het volgende doen:

  • Integreer waarschuwingstools om een vector-innameflow te activeren wanneer nieuwe gegevens uw toepassing binnenstromen.
  • Stel modelprestatiedrempels in om degradaties bij te houden en hertrainingspijplijnen te activeren.

Neem in beide AKS-modi automatisering op voor beleidsvalidatie, detectie van configuratiedrift en releasebeheer, naast triggers voor modelkwaliteit.

Schaalbaarheid en resourcebeheer

Belangrijkste conclusie: Optimaliseer het resourcegebruik via gedistribueerde verwerking, automatisch schalen en herstelplanning bij calamiteiten om wisselende eisen van AI-pijplijnen kosteneffectief op te vangen.

Schaalbaarheid en resourcebeheer zijn essentieel om ervoor te zorgen dat uw AI-pijplijn de vereisten van uw toepassing kan afhandelen. Door uw resourcegebruik te optimaliseren, kunt u het volgende doen:

  • Integreer hulpprogramma's die efficiënt gebruikmaken van uw toegewezen CPU-, GPU- en geheugenresources via gedistribueerde computing en meerdere niveaus van parallelle uitvoering, zoals gegevens, modellen en pijplijnparallellisme.
  • Schakel automatisch schalen in op uw rekenresources om hoge modelaanvraagvolumes te ondersteunen op piekmomenten en omlaag te schalen in daluren.
  • Plan herstel na noodgevallen door de best practices voor AKS-tolerantie en betrouwbaarheid te volgen.

AKS Automatic kan de overhead voor installatie verminderen voor algemene schaal- en bewerkingspatronen, terwijl AKS Standard uitgebreidere controle biedt voor aangepaste schaalarchitecturen.

Langlopende batchtaken uitvoeren

Belangrijkste conclusie: voer eindige taken uit als een Kubernetes Job, sla de voortgang buiten de pod op, verwerk beëindigingssignalen en ga ervan uit dat de Job meer dan één keer kan worden gestart.

Knooppuntupgrades, opnieuw opstarten, uitschalen van gebeurtenissen, resourcedruk, preemption en infrastructuurfouten kunnen langdurige batchtaken onderbreken. Een Kubernetes Job vervangt een mislukte of verwijderde pod, maar de vervanging begint op een ander knooppunt zonder de lokale bestanden of het procesgeheugen van de vorige pod. Ontwerp de toepassing zo dat deze kan hervatten vanuit een persistente toestand en werk veilig opnieuw kan uitvoeren.

Gebruik deze procedures voor gewone CPU-, geheugen- of I/O-intensieve batchtaken. De richtlijnen voor gang-scheduling en workloadwachtrijen zijn van toepassing wanneer een gedistribueerde workload vereist dat meerdere workers tegelijk starten of wanneer teams gedeelde quota nodig hebben. Een taak met één werkrol of onafhankelijk parallelle batchtaak heeft normaal gesproken geen gangplanning nodig.

Controlepunten, nieuwe pogingen en beëindiging configureren

In het volgende voorbeeld wordt een reeks werkitems verwerkt en wordt het volgende item op een Azure Files permanent volume vastgelegd. Het herstelt het controlepunt na de vervanging van een pod en slaat de voortgang op wanneer het proces SIGTERM ontvangt:

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

Vervang de voorbeeldloop door uw batchtoepassing en selecteer opslag die voldoet aan de vereisten voor doorvoer en herstel. Gebruik de workloadidentiteit in plaats van ingesloten referenties wanneer de toepassingscontrolepunten rechtstreeks naar Azure Blob Storage of een andere Azure-service gaan.

Pas deze betrouwbaarheidscontroles opzettelijk toe:

  • Controlepunten en idempotentie: Sla de voortgang op met een interval dat voldoet aan uw herstelpuntdoelstelling. Sla controlepunten en vastgelegde uitvoer op voor permanente opslag, niet het containerbestandssysteem of emptyDirde lokale opslag van knooppunten. Gebruik atomische schrijfbewerkingen, idempotentiesleutels, transactionele uitvoer of ontdubbeling omdat hetzelfde taakprogramma soms meerdere keren kan starten.
  • Gedrag voor opnieuw opstarten: een taak toestaat restartPolicy: Never of OnFailure. Met Never leidt een mislukte container tot een mislukte pod en maakt de Job-controller een vervangende pod. Met OnFailure kan de kubelet de container opnieuw opstarten in dezelfde pod. Gebruik Never wanneer afzonderlijke mislukte pods en logs de diagnose vergemakkelijken, en zorg ervoor dat beide opties veilig kunnen worden hervat.
  • Limieten voor opnieuw proberen: ingesteld backoffLimit op basis van het aantal tijdelijke fouten dat de workload kan tolereren. Gebruik podFailurePolicy om direct te stoppen bij bekende niet-herhaalbare exitcodes of, zoals in het voorbeeld, te voorkomen dat vrijwillige verstoringen het retrybudget verbruiken. Een verstoring kan de pod nog steeds stoppen; het beleid verandert alleen hoe de Job die mislukking meetelt.
  • Deadlines: Stel activeDeadlineSeconds in wanneer de taak moet stoppen na een maximale totale runtime. De deadline omvat nieuwe pogingen en heeft voorrang op backoffLimit. Stel geen deadline in die korter is dan de verwachte runtime plus nieuwe pogingen en hersteltijd. Een mislukte taak wordt niet automatisch opnieuw opgestart als een nieuwe taak.
  • Gecontroleerde beëindiging: handel SIGTERM af in de toepassing en stel terminationGracePeriodSeconds lang genoeg in om geen nieuw werk meer te accepteren, de huidige taak veilig af te ronden of af te breken, uitvoer weg te schrijven en een controlepunt op te slaan. Kubernetes verzendt SIGKILL als het proces de respijtperiode overschrijdt, zodat periodieke controlepunten nodig blijven.
  • Opschonen: Stel ttlSecondsAfterFinished cronJob-geschiedenislimieten in of configureer deze om te voorkomen dat voltooide taken en pods worden opgestapeld. Bewaar taakrecords lang genoeg voor logboekverzameling en incidentonderzoek.

Plannen voor verwijderingen en knooppuntonderhoud

Beschouw het blokkeren van ontruiming niet als de belangrijkste herstelstrategie voor een langlopende taak. Maak voor een herstartbare batchtaak normaal gesproken geen PodDisruptionBudget Pod Disruption Budget (PDB) aan; de jobcontroller maakt na een vrijwillige verstoring een vervangende pod. Een PDB beschermt alleen tegen vrijwillige uitzettingen en beschermt niet tegen uitval van knooppunten, uitzetting door resourcegebrek of preëmptie. Een PDB die nul onderbrekingen toestaat, kan ook het leeglopen van knooppunten blokkeren en AKS-upgrades vertragen.

Gebruik een PDB alleen wanneer een parallelle batchtaak een minimaal aantal gelijktijdig draaiende werkprocessen moet behouden en u het drain-gedrag ervan hebt getest. Gebruik op dezelfde manier cluster-autoscaler.kubernetes.io/safe-to-evict: "false" alleen voor uitzonderlijk, niet-startbaar werk. De annotatie kan voorkomen dat er wordt teruggeschaald en de kosten verhogen, maar beschermt niet tegen node-uitval of alle onderhoudsgebeurtenissen.

AKS werkt cordon bij en leeg oude knooppunten voordat deze worden vervangen. Configureer geplande onderhoudsvensters om ondersteund AKS-onderhoud uit te lijnen met perioden met een lagere impact, maar zorg ervoor dat de workload opnieuw kan worden opgestart omdat de onderhoudstijd niet ongeplande onderbrekingen elimineert. Voer voor AKS Standard batchtaken uit op een toegewezen gebruikersknooppuntgroep wanneer ze afzonderlijke VM-grootten, schaallimieten, taints of tijdsinstellingen voor upgrades nodig hebben. Vermijd Spot-nodepools voor workloads die niet kunnen herstellen van preëmptie. Controleer vóór het onderhoud van knooppunten of recente controlepunten bruikbaar zijn en of een andere in aanmerking komende knooppuntgroep voldoende quota en capaciteit heeft om vervangende pods uit te voeren.

Voortgang en herstel van taken bewaken

Gebruik de Kubernetes-status, -gebeurtenissen en -logboeken samen wanneer u een langlopende taak onderzoekt:

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

Schakel de beheerde Azure Monitor-service voor Prometheus en Container Insights in om logboeken te bewaren en de taakstatus te correleren aan het opnieuw opstarten van pods, evicties, wachttijd, knooppuntstatus en resourcebenutting. Instrumenteer de toepassing met signalen voor bedrijfsvoortgang, zoals voltooide items, mislukte items, laatste geslaagde controlepunttijd, verwerkingssnelheid, aantal nieuwe pogingen en geschatte voltooiingstijd. Waarschuwing voor een mislukte taak, een taak die de verwachte duur overschrijdt, geen controlepunt binnen de beoogde herstelpunt, herhaalde podvervangingen, aanhoudende wachtende pods en vastgelopen verwerkingsdoorvoer.

Beveiliging en naleving

Belangrijke leerpunten: CVE-scan, audittrails en nalevingscontroles implementeren om uw gegevens te beschermen en te voldoen aan wettelijke vereisten zoals SOC 2, HIPAA en AVG.

Beveiliging en naleving zijn essentieel voor het beveiligen van uw gegevens en ervoor zorgen dat uw AI-pijplijn voldoet aan wettelijke vereisten. Door best practices voor beveiliging en naleving te implementeren, kunt u het volgende doen:

  • Integreer scannen op veelvoorkomende beveiligingsproblemen en blootstellingen (CVE's) om veelvoorkomende beveiligingsproblemen op opensource-modelcontainerinstallatiekopieën te detecteren.
  • Gebruik Microsoft Defender voor containers voor modelcontainerinstallatiekopieën die zijn opgeslagen in uw Azure Container Registry.
  • Behoud een audittrail van de opgenomen gegevens, modelwijzigingen en metrische gegevens om te voldoen aan uw organisatiebeleid.
  • Ondersteuning voor nalevingsframeworks zoals SOC 2 (via auditlogboekregistratie en toegangsbeheer van Azure), HIPAA (via versleuteling at rest en in transit, netwerkisolatie) en AVG (via opties voor gegevenslocatie en toegangsbeheerbeleid).

In AKS Automatic verbeteren vooraf geconfigureerde standaardinstellingen voor beveiliging de basislijnpostuur, maar beveiligingsmaatregelen op modelniveau, gegevensniveau en beveiliging op pijplijnniveau blijven vereist.

GPU-workloads plannen

Belangrijke leerpunten: GPU's beschikbaar maken via de NVIDIA-apparaatinvoegtoepassing, GPU's expliciet aanvragen en dure GPU-knooppunten isoleren met labels, taints en toleranties.

Kubernetes plant GPU’s in als uitgebreide resources. Nadat de NVIDIA-device-plug-in de GPU's op een knooppunt heeft geregistreerd, vraagt een pod een GPU aan door nvidia.com/gpu in zowel resources.requests als resources.limits in te stellen. De volgende pod vraagt één GPU aan en is gericht op een nodepool met label accelerator=nvidia:

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

Uitgebreide hulpbronnen zijn niet overbelast. Kubernetes behandelt een GPU-limiet als een GPU-aanvraag wanneer alleen de limiet is opgegeven, maar als u beide velden instelt, wordt de intentie van de werkbelasting expliciet en wordt beleidsvalidatie mogelijk.

Een AKS GPU-knooppuntgroep inrichten

Maak voor AKS Standard een toegewezen gebruikersknooppuntgroep met een ondersteunde VM-grootte van NVIDIA GPU. Met het volgende Azure CLI-voorbeeld wordt een automatisch schalende Standard_NC4as_T4_v3 nodegroep gemaakt, wordt het label toegepast dat door de voorgaande pod wordt gebruikt en worden de knooppunten voorzien van taints om workloads te weren die GPU-knooppunten niet expliciet tolereren:

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

Controleer voordat u de knooppuntgroep maakt of de VM-SKU beschikbaar is in de clusterregio en of het abonnement voldoende regionale en VM-familiequota heeft. Selecteer een NC-seriegrootte op basis van GPU-geheugen, GPU-telling, CPU-naar-GPU-verhouding, lokale opslag, netwerken en de CUDA-mogelijkheden die vereist zijn voor het trainingsframework. NCas T4 v3-grootten zijn bijvoorbeeld geschikt voor veel enkele GPU- en kleinere trainingsworkloads, terwijl NC A100 v4-grootten grotere modellen en GPU-configuraties met meerdere exemplaren ondersteunen.

AKS Automatic kan geschikte GPU-capaciteit voorzien als er wachtende pods zijn. De workload moet nog steeds nvidia.com/gpu aanvragen, en alle knooppuntselectoren, affiniteiten, toleranties, topologiebeperkingen, abonnementsquota en regionale SKU-beschikbaarheid moeten haalbaar zijn. Gebruik AKS Standard wanneer u een vaste VM-SKU, de levenscyclus van aangepaste knooppuntgroepen of gedetailleerde controle over schalen en topologie van GPU-pools nodig hebt.

De NVIDIA-apparaatinvoegtoepassing controleren of installeren

AKS GPU-configuraties kunnen beheerde GPU-stuurprogramma's en integratie van apparaatinvoegtoepassingen bieden. Controleer de effectieve configuratie voordat u een andere invoegtoepassing installeert:

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"

Voer niet meerdere NVIDIA-apparaatinvoegtoepassing DaemonSets uit op dezelfde knooppunten. Als uw AKS-configuratie de invoegtoepassing niet beheert, registreert de volgende zelfstandige DaemonSet NVIDIA-GPU's bij de kubelet. Installeer een versie van de apparaatinvoegtoepassing die wordt ondersteund door uw NVIDIA-stuurprogramma en Kubernetes-versies:

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

Controleer of nvidia.com/gpu onder de toewijsbare resources van elk GPU-knooppunt verschijnt voordat u trainingstaken indient.

Partitioneer A100- en H100-GPU’s met MIG

NVIDIA Multi-Instance GPU (MIG) kan een ondersteunde A100- of H100 GPU partitioneren in geïsoleerde GPU-exemplaren. MIG is handig voor het afstemmen van hyperparameters en kleinere fine-tuning-taken waarvoor geen volledige fysieke GPU is vereist. Gebruik volledige GPU’s voor workloads die het volledige GPU-geheugen, de maximale interconnect-bandbreedte vereisen, of een profiel vereisen dat niet wordt ondersteund door de geïnstalleerde GPU.

Gebruik de NVIDIA GPU Operator en MIG Manager wanneer u declaratief beheer van de MIG-levenscyclus nodig hebt. De operator moet eigenaar zijn van de apparaatinvoegtoepassing en MIG-configuratie voor de betrokken knooppunten; combineer het niet met een tweede zelfstandige apparaatinvoegtoepassing. De exacte profielnamen en het aantal exemplaren zijn afhankelijk van het GPU-model en de geheugencapaciteit. Met de volgende configuratie worden zeven 1g.10gb exemplaren gemaakt voor ondersteunde configuraties van 80 GB A100 of H100:

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

Configureer de MIG Manager van de GPU Operator om de mig-parted-config ConfigMap te gebruiken, gebruik de mixed MIG-strategie wanneer workloads benoemde MIG-profielen aanvragen, en label vervolgens de doelknooppunten:

kubectl label nodes \
  -l accelerator=nvidia \
  nvidia.com/mig.config=hptuning-1g10gb \
  --overwrite

Als u een MIG-indeling wijzigt, worden workloads die al gebruikmaken van de GPU onderbroken. Cordon de doelnode en drain deze, pas de configuratie toe tijdens een onderhoudsvenster en bevestig dat het aangevraagde profiel aanwezig is in de toewijsbare resources van de node voordat u jobs indient.

GPU-workloads isoleren met taints en toleranties

Een NoSchedule taint houdt reguliere applicatiepods uit de buurt van dure GPU-knooppunten. Het voorbeeld van het maken van een knooppuntgroep is van toepassing sku=gpu:NoSchedule. De volgende volledige taak bevat de overeenkomende tolerantie en een knooppuntkiezer:

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

Een toleration maakt scheduling mogelijk, maar forceert de pod niet naar een GPU-knooppunt. Koppel toleranties met een GPU-resourceaanvraag en een knooppuntkiezer of knooppuntaffiniteit. Zorg ervoor dat vereiste platform DaemonSets, zoals netwerken, bewaking, opslag en de apparaatinvoegtoepassing, de GPU taint tolereren.

Gedistribueerde trainingsworkloads uitvoeren

Belangrijk leerpunt: Gebruik een trainingsoperator om werkrolidentiteiten en de levenscyclus van taken te beheren, netwerkcommunicatie met meerdere knooppunten te valideren en gangtoegang te gebruiken wanneer alle werknemers samen moeten beginnen.

Gedistribueerde training maakt gebruik van meerdere processen om gegevens, modelstatus of pijplijnfasen te verdelen. In Kubernetes kan een operator workerpods maken, rendezvous-configuratie injecteren, de status van replica's bijhouden, gefaalde workerpods opnieuw opstarten en de job opschonen. Installeer en versioneer trainingsoperators via het IaC- en releaseproces van uw platform, in plaats van individuele teams toe te staan niet-beheerde clusterbrede CRD's te installeren.

Een draagbare CUDA-trainingsinstallatiekopie bouwen

Het volgende Dockerfile bouwt voort op het Dockerfile-patroon dat wordt beschreven in de sectie Containerization. De installatiekopie bevat de CUDA-runtime en PyTorch-bibliotheken, terwijl het compatibele NVIDIA-stuurprogramma op het AKS GPU-knooppunt blijft staan:

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"]

Zet de basisimage in productie vast op een onveranderlijke digest. Bewaar gegevenssets en wijzig regelmatig controlepunten buiten de afbeelding en scan de resulterende afbeelding voordat u deze naar Azure Container Registry pusht.

Een PyTorchJob uitvoeren

De Kubeflow Training Operator biedt de PyTorchJob CRD. Installeer een trainingsoperatorrelease die compatibel is met uw Kubernetes-versie voordat u dit manifest toepast. In het volgende voorbeeld met twee replica’s wordt een NCCL-all-reducebewerking uitgevoerd over één master en één worker:

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

Voor training in productie vervangt u de inline-test door uw versiebeheerde trainingsimage en script. Lijn het aantal replica's uit met het aantal GPU's en processen dat is vereist voor het trainingsframework.

Een TFJob uitvoeren

De Training Operator levert ook de TFJob CRD. In het volgende voorbeeld wordt synchrone TensorFlow-training uitgevoerd over twee GPU-workers met 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

Definieer voor parameter-servertraining de replicatypen Chief, Worker en PS volgens de TensorFlow-distributiestrategie. Meet de resulterende knelpunten in het netwerk en de parameterserver voordat u het aantal replica's verhoogt.

Een model verfijnen met KAITO

KAITO biedt een AKS-gerichte werkruimteabstractie voor modelimplementatie en afstemming. Schakel de KAITO-invoegtoepassing in of installeer een compatibele KAITO-release voordat u een Workspace. Controleer of de geselecteerde voorinstelling, VM-SKU en fine-tuningmethode worden ondersteund door de geïnstalleerde versie van KAITO.

De volgende werkruimte vraagt een A100 GPU-VM aan en start QLoRA-afstemming voor een ondersteunde Phi-3-voorinstelling met behulp van een openbaar toegankelijke gegevensset:

apiVersion: kaito.sh/v1beta1
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 kan vooraf ingestelde modelconfiguratie en de GPU-infrastructuur coördineren die nodig is voor de werkruimte. Sla voor productie de trainingsgegevensset op in een goedgekeurd Azure opslagaccount, gebruik privétoegang en workloadidentiteit indien ondersteund en bewaar het resulterende model in een beheerd modelregister of Azure Container Registry. Behandelt het werkruimtemanifest, de versie van de invoergegevensset, de vooraf ingestelde versie, de configuratie van de adapter en de samenvatting van uitvoerafbeeldingen als één trainingsrecord met versiebeheer.

NCCL-communicatie configureren met AKS CNI

NVIDIA Collective Communications Library (NCCL) verwerkt collectieve bewerkingen zoals all-reduce. Gebruik voor een overdraagbare TCP-basislijn op AKS CNI de podnetwerkinterface, normaal eth0, en begin met NCCL_IB_DISABLE=1. Gebruik op ondersteunde VM-grootten die geschikt zijn voor RDMA de gedocumenteerde NVIDIA- en Azure RDMA-configuratie en valideer deze voordat u deze insteltNCCL_IB_DISABLE=0.

Gebruik deze omgevingsvariabelen voor de basislijn:

  • NCCL_SOCKET_IFNAME=eth0 selecteert de netwerkinterface van de pod.
  • NCCL_DEBUG=INFO biedt diagnostische gegevens tijdens de validatie. Verlaag het logniveau na het afstellen.
  • NCCL_IB_DISABLE=1 selecteert TCP-sockets wanneer RDMA niet is geconfigureerd.
  • TORCH_NCCL_ASYNC_ERROR_HANDLING=1 zorgt ervoor dat PyTorch wordt beëindigd in plaats van voor onbepaalde tijd te blijven hangen bij asynchrone communicatiefouten.

Als netwerkbeleid is ingeschakeld, sta al het vereiste rendezvous- en NCCL-verkeer tussen de replica's toe. NCCL kan dynamische poorten afspreken, dus een strikt beleid met een beperkt aantal vaste poorten kan ertoe leiden dat trainingsjobs vastlopen. Het volgende beleid staat onbeperkte pod-naar-pod-communicatie alleen toe tussen replica's van de PyTorch-taak en staat DNS-omzetting toe:

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

Benchmark NCCL onafhankelijk van modeltraining voordat u gaat opschalen. Vergelijk de all-reduce-bandbreedte, latentie, GPU-gebruik en trainingsthroughput bij elk aantal workers. Meer werknemers kunnen de prestaties verminderen wanneer communicatie of het laden van gegevens het knelpunt wordt.

Gangplanning en werkbelastingwachtrijen gebruiken

Belangrijk leerpunt: Gedistribueerde werknemers als groep toelaten en GPU-quota voor tenants afdwingen, zodat gedeeltelijk geplande taken geen GPU's reserveren terwijl ze wachten op resterende werknemers.

De standaard Kubernetes-scheduler plaatst pods afzonderlijk. Voor een gedistribueerde taak die pas voortgang kan boeken als elke worker actief is, kan gedeeltelijke plaatsing GPU-capaciteit verspillen. Kueue biedt toelatingsbeheer en quotumbeheer voordat pods gaan draaien. Volcano biedt een scheduler en een op PodGroup gebaseerd all-or-nothing planningsmodel.

AKS Automatic biedt de standaard-Kubernetes-planner en automatische inrichting van knooppunten als uitgangspunt. Verzend gewone taken of door operator beheerde trainingstaken met nauwkeurige resourceaanvragen en laat het platform in aanmerking komende capaciteit inrichten. Dit gedrag garandeert geen atomische toegang voor elke werknemer. Installeer Kueue of Volcano wanneer een workload gang-scheduling, wachtrijbeheer, teamquota, eerlijke verdeling of aangepast preëmptiegedrag vereist.

Gpu-quotum voor meerdere tenants toewijzen met Kueue

Installeer een Kueue-versie die compatibel is met de Kubernetes-versie en schakel integraties in voor de workloadtypen die u gebruikt. Het volgende manifest maakt het volgende:

  • Een GPU ResourceFlavor gekoppeld aan knooppunten met het label accelerator=nvidia.
  • Een systeem met vier GPU's ClusterQueue voor team A.
  • Een dual-GPU ClusterQueue voor team B.
  • Een naamruimtebereik LocalQueue voor elk team.
  • Een taak met twee werknemers die Kueue alleen toegeeft wanneer de aangevraagde resources beschikbaar zijn.
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

Een ClusterQueue quotum is een planningsquotum, geen Azure abonnementsquotum. Zorg ervoor dat het AKS-cluster de onderliggende VM-capaciteit kan inrichten en dat Azure GPU-quotum voldoende is voor de geaggregeerde toegelaten workload. Gebruik cohorten en de fair-sharingfuncties van Kueue wanneer teams elkaars ongebruikte quota kunnen lenen.

Volcano gebruiken als alternatief

Volcano is een alternatief als u een toegewezen batchplanner wilt met gangplanning, wachtrijen en levenscyclusbeleid voor taken. Installeer een Volcano-release die compatibel is met het cluster voordat u de CRD's toepast. Voor de volgende Volcano Job is vereist dat beide GPU-workers beschikbaar zijn voordat de job wordt uitgevoerd:

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

Standaardiseren op één primair systeem voor wachtrijen en gangplanning, tenzij u een getest interoperabiliteitsontwerp hebt. Meerdere toegangscontrollers of planners kunnen anders het gedrag in behandeling en voorbeëindiging moeilijk maken om over te redeneren.

Trainings- en deductieprioriteiten configureren

Latentiegevoelige deductie vereist doorgaans een hogere prioriteit dan onderbroken batchtraining. Met de volgende PriorityClass resources kunnen inferentiepods pods met een lagere prioriteit verdringen, terwijl wordt voorkomen dat batchtrainingspods andere workloads verdringen:

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.

Wijs de klasse toe via spec.priorityClassName in de podsjabloon. De prioriteit van Kubernetes-pods en de prioriteit van Kueue-workloads zijn van invloed op verschillende fasen: Kueue bepaalt de toelating tot de wachtrij, terwijl de Kubernetes-prioriteit van invloed is op scheduling en preëmptie van pods na toelating. Coördineer beide beleidsregels zodat ze dezelfde bedrijfsprioriteit uitdrukken.

Met preemption worden pods met een lagere prioriteit beëindigd. Trainingsworkloads die kunnen worden onderbroken, moeten checkpoints wegschrijven naar persistente opslag, dubbel werk kunnen tolereren en kunnen herstellen zonder afhankelijk te zijn van bestanden die lokaal op het knooppunt zijn opgeslagen.

Gedeeld geheugen en resourcebeheer configureren

Belangrijke aandachtspunt: vervang de kleine standaardinstelling /dev/shmvan de containerruntime, stel resourceaanvragen in op basis van waargenomen gebruik en configureer knooppuntschalen rond de volledige GPU-workloadvereisten.

Verhogen /dev/shm voor ML-gegevensladers

PyTorch-gegevensladers, TensorFlow-invoerpijplijnen, NCCL en Python multiprocessing kunnen gebruikmaken van gedeeld POSIX-geheugen. De standaardcontainer voor /dev/shm is vaak te klein voor training met meerdere processen, wat kan leiden tot workercrashes, busfouten of schijnbaar vastlopen van de training.

Koppel een op geheugen gebaseerd emptyDir aan /dev/shm en stel sizeLimit expliciet in:

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

Door geheugen ondersteund emptyDir gebruik telt mee voor het geheugenverbruik van de pod. Neem het maximale verwachte gebruik van gedeeld geheugen op bij het instellen van de geheugenlimiet van de container. Als /dev/shm groter wordt dan het effectieve geheugenbudget, kan de pod worden uitgezet of beëindigd omdat deze de geheugenlimiet overschrijdt.

CPU- en geheugengrootte van waargenomen gebruik

Begin met een benchmark op basis van een representatief model, batchgrootte, reekslengte, gelijktijdigheid van gegevenslaadprogramma's, augmentatie en controlepuntgedrag. Gebruik vervolgens bewakingsgegevens om het volgende aan te passen:

  • Stel CPU-verzoeken hoog genoeg in om de invoerpijplijnen voor de GPU van voldoende input te voorzien. Permanente niet-actieve GPU-perioden kunnen duiden op CPU- of opslaghongering.
  • Stel geheugenaanvragen in bij stabiel werksetgebruik plus een veiligheidsmarge. Neem /dev/shm, het gedrag van de paginacache, de overhead van de framework-allocator en pieken in de serialisatie van checkpoints op.
  • Stel geheugenlimieten in boven de waargenomen piek. Onderzoek OOMKilled gebeurtenissen in plaats van herhaaldelijk limieten te verhogen zonder de oorzaak te vinden.
  • Beoordeel CPU-throttling voordat u beperkende CPU-limieten gebruikt. CPU-limieten die te laag zijn, kunnen het GPU-gebruik verminderen, zelfs wanneer het gemiddelde CPU-gebruik acceptabel lijkt.
  • Stel aanvragen en limieten in die gelijk zijn aan voorspelbare, hoogwaardige trainingstaken wanneer gegarandeerde kwaliteit van de service belangrijker is dan het verpakken van knooppunten.
  • Profileer elke belangrijke wijziging in modelgrootte, precisie, batchgrootte, aantal werkrollen en gegevenspijplijn.

Gebruik percentielen voor volledige trainingsuitvoeringen in plaats van een kort gemiddelde. Opstart-, validatie-, controlepunt- en gegevensverloopfasen hebben vaak verschillende resourcepieken.

Automatische schaalaanpassing van clusters configureren voor een GPU-knooppuntgroep

Voor AKS Standard schakelt u de automatische schaalaanpassing van clusters in op de GPU-gebruikersknooppuntgroep en definieert u de minimale en maximale capaciteit:

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

U kunt ondersteunde profielinstellingen voor automatische schaalaanpassing van clusters afstemmen op clusterbereik. Test profielwijzigingen voor zowel trainings- als serverworkloads:

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

Een GPU-pod die in afwachting is, leidt alleen tot opschaling wanneer alle planningsvereisten overeenkomen met een nodepoolsjabloon. Controleer de GPU-resourceaanvraag, VM-capaciteit, labels, taints, toleranties, affiniteit, topologiebeperkingen, permanente volumetopologie, maximumaantal knooppunten en Azure quotum wanneer omhoog schalen niet plaatsvindt.

Opschalen naar nul is geschikt voor onderbreekbare trainingspools, maar het voegt vertraging toe door VM-provisioning, het ophalen van images, het koppelen van datasets en modelinitialisatie. Houd een niet-nul minimum wanneer opstartlatentie een materiaaleffect heeft op servicedoelstellingen. Pod disruption budgets, pods die niet kunnen worden ontruimd, lokale opslag en lange respijtperioden voor beëindiging kunnen het terugschalen vertragen.

AKS Beheert het inrichten en schalen van knooppunten automatisch als onderdeel van de servicebasislijn. Concentreer u op nauwkeurige podverzoeken en ondersteunde constraints in plaats van een handmatige autoscaler voor een GPU-nodepool te configureren.

Gegevenssets en controlepunten opslaan

Belangrijkste conclusie: Kies opslag op basis van toegangspatroon, doorvoer, vereisten voor delen en herstelvereisten, en sla controlepunten buiten het knooppunt op, zodat de training kan worden hervat na evictie of preëmptie.

Houd grote datasets, modelartefacten en checkpoints uit containerimages. Kies een opslaginterface op basis van de workload:

  • Gebruik Azure Blob Storage voor grote objectgegevenssets, modelartefacten en gegevensopslagplaatsen met hoge capaciteit.
  • Gebruik Azure Files wanneer voor meerdere werkknooppunten een gedeeld POSIX-bestandssysteem is vereist.
  • Gebruik Azure Disk voor krachtige controlepunten voor lezen/schrijven met één knooppunt of cacheworkloads, waar ReadWriteOnce voldoende is.
  • Gebruik tijdelijke knooppuntopslag alleen voor herstelbare caches en tijdelijke bestanden.

Toegang tot grote gegevenssets met het Azure Blob CSI-stuurprogramma

Schakel het Azure Blob CSI-stuurprogramma in op AKS Standard als dit nog niet is ingeschakeld:

RESOURCE_GROUP=myResourceGroup
AKS_CLUSTER=myAKSCluster

az aks update \
  --resource-group "$RESOURCE_GROUP" \
  --name "$AKS_CLUSTER" \
  --enable-blob-driver

In het volgende voorbeeld wordt dynamisch een Premium-Azure Blob-container gemaakt die wordt weergegeven via NFS en wordt deze aan een trainingspod toegevoegd. Gebruik voor een bestaande beheerde gegevensset een statisch gedefinieerd volume of een BlobFuse-configuratie met de juiste identiteits- en privénetwerkbesturingselementen in plaats van een lege dynamische container te maken:

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

Test het protocol en de aankoppelopties aan de hand van representatieve shardgroottes en toegangspatronen. Veel werknemers die veel kleine bestanden lezen, kunnen verschillende resultaten opleveren van sequentiële streaming van grote shards. Overweeg om gegevenssets vooraf te verwerken in shards van de juiste grootte en gebruik te maken van cacheruimte op knooppunten wanneer herhaalde tijdvakken anders dezelfde objecten zouden downloaden.

Trainingsgegevens delen met Azure Files

Azure Files ondersteunt ReadWriteMany, waarmee gedistribueerde workers op verschillende knooppunten dezelfde share kunnen koppelen. Premium-Azure Files is geschikt wanneer de workload voorspelbare prestaties van het bestandssysteem vereist en de geselecteerde regio de vereiste redundantieoptie ondersteunt.

In het volgende manifest wordt een Premium-Azure Files share gemaakt en gekoppeld aan twee parallelle werkpods:

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

Vermijd dat elke werknemer herhaaldelijk een map met miljoenen bestanden opsommen. Gebruik een manifest of een deterministische toewijzing van shards, zodat elke worker weet welke objecten hij moet lezen.

Controlepunt naar permanente opslag

Een controlepunt moet voldoende status bevatten om correct te worden hervat, zoals modelgewichten, optimizerstatus, schedulerstatus, schaalstatus, tijdnummer of stapnummer, status van willekeurige getallengenerator en positie van gegevenslaadprogramma wanneer dit wordt ondersteund. Schrijf regelmatig controlepunten en vóór een respijtelijke beëindiging.

De volgende taak schrijft atomische PyTorch-checkpoints naar Azure Files, herstelt het meest recente checkpoint na een herstart van een container of vervanging van een pod, en gaat om met SIGTERM, zodat preëmptie recente voortgang kan behouden:

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

Gebruik een Retain claimbeleid of een onafhankelijk beheerd opslagaccount voor productiecontrolepunten, zodat het verwijderen van een PVC niet onbedoeld het enige herstelpunt verwijdert. Voor data-parallelle training in een gedistribueerde omgeving laat u normaal gesproken rank nul het globale checkpoint wegschrijven, of gebruikt u een door het framework ondersteunde sharded checkpoint-indeling. Voorkom dat meerdere ranks tegelijkertijd naar hetzelfde bestand schrijven.

Test het herstel door tijdens een niet-productierun opzettelijk een workerpod te verwijderen. Controleer of de controller de workload opnieuw aanmaakt, de nieuwe pod hetzelfde persistente volume aankoppelt en de training wordt hervat vanaf de verwachte stap.

GPU-gebruik en trainingsdoorvoer bewaken

Belangrijkste leerpunt: Bewaak GPU-rekenkracht, GPU-geheugen, gegevenspijplijndoorvoer, stapduur en controlepuntactiviteit samen, zodat u de verzadiging van de rekenkracht, het netwerk of de opslagknelpunten kunt onderscheiden.

Schakel Azure Monitor beheerde service voor Prometheus en Container Insights in om kubernetes-status, containerlogboeken, knooppuntstatus en prometheus-metrische gegevens te correleren. Gebruik aanbevolen procedures voor bewaking voor AKS bij het ontwerpen van waarschuwingen, retentie en operationele dashboards.

Metrische gegevens van NVIDIA GPU verzamelen

NVIDIA Data Center GPU Manager (DCGM) Exporter stelt Prometheus-metrieken voor NVIDIA-GPU's beschikbaar. Als de NVIDIA GPU-operator dcGM-exporteur al implementeert, moet u geen dubbele exporteur implementeren. Configureer de door Azure Monitor beheerde Prometheus om gegevens van de bestaande exporter te verzamelen.

Het volgende PodMonitor maakt gebruik van de door Azure Monitor beheerde Prometheus-CRD en is gericht op DCGM Exporter-pods in de gpu-operator namespace. Pas de labelkiezer aan zodat deze overeenkomt met de labels die door uw geïnstalleerde exporteur worden gebruikt:

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

Controleer de poortnaam van de exporter-service of -pod voordat u de monitor toepast. Veelvoorkomende dcGM-metrische gegevens zijn:

Metric Purpose
DCGM_FI_DEV_GPU_UTIL Percentage tijd dat de GPU actief is
DCGM_FI_DEV_FB_USED Gebruikt framebuffergeheugen
DCGM_FI_DEV_FB_FREE Gratis framebuffergeheugen
DCGM_FI_DEV_MEM_COPY_UTIL Geheugenkopieerenginegebruik
DCGM_FI_DEV_POWER_USAGE GPU-energieverbruik
DCGM_FI_DEV_GPU_TEMP GPU-temperatuur
DCGM_FI_DEV_XID_ERRORS NVIDIA XID-foutgebeurtenissen

De beschikbaarheid van metrische gegevens is afhankelijk van de GPU-, stuurprogramma-, DCGM- en exportversies.

Metrische gegevens over trainingsdoorvoer exporteren

Instrumenteer de trainingstoepassing met metrische gegevens op workloadniveau. Nuttige metrische gegevens zijn onder andere:

  • ml_training_samples_total voor cumulatieve steekproeven of tokens verwerkt.
  • ml_training_steps_total voor voltooide optimalisatiestappen.
  • ml_training_step_duration_seconds voor latentie per stap.
  • ml_training_checkpoint_duration_seconds voor controlepuntlatentie.
  • ml_training_data_wait_seconds voor tijd besteed aan het wachten op invoergegevens.
  • Modelspecifiek verlies, leerpercentage, gradiëntnorm en validatiemetrieken.

In het volgende uitvoerbare voorbeeld worden synthetische trainingsstatistieken op de poort 8000weergegeven. Vervang de simulatie door metrische gegevens die worden verzonden door de echte trainingslus:

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

Neem voor een echte gedistribueerde taak stabiele labels op, zoals modelnaam, modelversie, taaknaam, run-id, replicarol en team. Gebruik geen niet-afhankelijke labels, zoals voorbeeld-id's, aanvraag-id's of onbewerkte gegevenssetpaden, omdat labels met hoge kardinaliteit de bewakingskosten en querylatentie verhogen.

GPU- en doorvoerdashboards bouwen

Gebruik PromQL-query's zoals de volgende als uitgangspunten en valideer metrische labels voor uw exporteur:

avg by (namespace, pod, gpu) (
  avg_over_time(DCGM_FI_DEV_GPU_UTIL[5m])
)

Met de volgende query wordt het geheugengebruik van een framebuffer berekend als percentage:

100 *
DCGM_FI_DEV_FB_USED
/
(DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE)

Met de volgende query wordt het aantal trainingsvoorbeelden berekend dat per seconde wordt verwerkt:

sum by (job_name) (
  rate(ml_training_samples_total[5m])
)

In de volgende query wordt de gemiddelde duur van de stap weergegeven:

avg by (job_name) (
  ml_training_step_duration_seconds
)

Interpreteer deze signalen samen:

  • Een laag GPU-gebruik en een hoge wachttijd voor gegevens geven meestal opslag, netwerk, voorverwerking of CPU-honger aan.
  • Hoog GPU-gebruik met verwachte doorvoer geeft aan dat de accelerator effectief wordt gebruikt.
  • Hoog GPU-geheugen en herhaalde out-of-memory-fouten geven aan dat batchgrootte, reekslengte, activeringsgeheugen, optimizerstatus of fragmentatie aanpassing nodig heeft.
  • Dalende doorvoer met stabiel GPU-gebruik kan wijzen op langere reeksen, communicatieoverhead, thermische werking of een wijziging in de modelberekening.
  • Laag GPU-gebruik op toegewezen GPU's duidt op ongebruikte capaciteit die mogelijk kan worden verminderd, anders in de wachtrij kan worden geplaatst of met MIG kan worden gepartitioneerd.
  • Een lange duur van een checkpoint kan preëmptie kostbaar maken en de hoeveelheid werk die na herstel opnieuw moet worden uitgevoerd vergroten.

Stel waarschuwingen in voor aanhoudend ondergebruik van GPU’s, GPU-geheugen dat bijna vol is, XID-fouten, stilgevallen trainingsdoorvoer, uitgevallen workers, wachtende gang-geplande workloads en checkpoints die niet binnen de verwachte herstelpuntdoelstelling zijn voltooid.

Veelgestelde vragen (FAQ)

Wat is het verschil tussen AKS Automatic en AKS Standard voor MLOps?

AKS Automatic biedt vooraf geconfigureerde standaardwaarden voor knooppuntgroepen, netwerken, beveiliging en upgrades, zodat MLOps-teams zich kunnen richten op workloaddefinities en -governance. AKS Standard vereist handmatige configuratie van deze platformonderdelen, maar biedt meer controle over aangepaste architecturen en schaalvereisten.

Hoe kan ik ML-modellen versien in AKS?

Versioneer uw modellen door modelgewichten, metadata en configuraties te verpakken in containerimages met semantische versie-tags. Sla deze installatiekopieën op in Azure Container Registry en verwijs naar specifieke versies in uw Kubernetes-implementatiemanifesten om consistentie tussen omgevingen te garanderen.

Hoe kan ik GPU-workloads plannen op AKS?

Zorg ervoor dat de NVIDIA-apparaatinvoegtoepassing beschikbaar is, zodat GPU-knooppunten adverteren nvidia.com/gpu. Richt op AKS Standard een toegewezen GPU-gebruikersknooppuntgroep in met een ondersteunde VM-grootte, zoals een Standard_NC-serie SKU, en configureer knooppuntlabels, een NoSchedule taint en limieten voor automatische schaalaanpassing van clusters. Vraag je in elke trainingspod om nvidia.com/gpu, selecteer je een geschikt GPU-knooppunt en voeg je de bijbehorende toleratie toe. AKS Automatic kan in aanmerking komende GPU-capaciteit inrichten vanuit podaanvragen, afhankelijk van ondersteunde SKU's, regionale beschikbaarheid, planningsbeperkingen en Azure abonnementsquotum.

Hoe kan ik gedistribueerde trainingstaken uitvoeren op AKS?

Installeer de Kubeflow-trainingsoperator en verzend een PyTorchJob of TFJob om gedistribueerde replica's te beheren, de configuratie van rendez-vous, het gedrag van opnieuw opstarten en de taakstatus te beheren. KAITO biedt een AKS-gerichte werkruimteabstractie voor ondersteunde werkstromen voor het verfijnen van modellen en kan gpu-infrastructuur coördineren met vooraf ingestelde modellen. Voor pyTorch-training met meerdere knooppunten configureert en benchmarkt u NCCL via het AKS CNI-podnetwerk, staat u werkrolverkeer toe via netwerkbeleid en gebruikt u ondersteunde RDMA-configuratie wanneer de geselecteerde VM-SKU en workload dit vereisen.

Hoe beheer ik het GPU-quotum voor meerdere teams?

Installeer Kueue en definieer ClusterQueue resources met CPU-, geheugen- en nvidia.com/gpu-quota, en koppel vervolgens de naamruimte van elk team aan het toegewezen quotum via een LocalQueue. Gebruik Kueue-cohorten of eerlijk delen wanneer teams ongebruikte capaciteit kunnen lenen. Volcano is een alternatief als u een batchplanner nodig hebt met een alles-of-niets-toelatingsbeleid voor workers. De prioriteit van de wachtrij afstemmen op Kubernetes-PriorityClassresources, zodat latentiegevoelige inferentie onderbreekbare training kan onderbreken en ervoor wordt gezorgd dat onderbreekbare trainingstaken worden hervat vanaf checkpoints in persistente opslag.

Wat zijn de aanbevolen procedures voor het uitvoeren van langlopende batchtaken op AKS?

Gebruik een Kubernetes Job voor eindig werk en een CronJob voor gepland werk. Behoud controlepunten en vastgelegde uitvoer buiten de pod, maak de verwerking idempotent, verwerkt SIGTERMen stel expliciete resourceaanvragen in, limieten voor opnieuw proberen, deadlines en opschoonbeleid. Stel dat knooppuntonderhoud of -fouten de pod kunnen vervangen en testen of de vervanging het controlepunt correct herstelt. Taakstatus, pod-gebeurtenissen, logboeken, leeftijd van controlepunt, doorvoer en gedrag voor opnieuw proberen bewaken. Gewone herstartbare taken vereisen geen gangplanning of een PDB. Gebruik deze besturingselementen alleen wanneer parallelle werkrollen samen moeten beginnen of een geteste minimale gelijktijdigheid moeten behouden.

Meer informatie over best practices voor andere gebieden van uw toepassingsimplementatie en -bewerkingen op AKS: