Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Si applica a: ✔️ Servizio Azure Kubernetes Standard automatico ✔️ Servizio Azure Kubernetes standard
MLOps è un set di procedure per la distribuzione, il monitoraggio e la gestione di modelli di Machine Learning negli ambienti di produzione.
Procedure consigliate principali di MLOps descritte in questo articolo:
- Infrastruttura distribuita come codice (IaC)
- Containerizzazione
- Gestione e controllo delle versioni dei modelli
- Automazione
- Scalabilità e gestione delle risorse
- Affidabilità dei processi batch a esecuzione prolungata
- Sicurezza e conformità
Questo articolo descrive le procedure consigliate e le considerazioni da tenere presenti quando si usa MLOps nel servizio Azure Kubernetes. Per altre informazioni su MLOps, vedere Operazioni di Machine Learning (MLOps) per i flussi di lavoro di Intelligenza artificiale e Machine Learning.
Scegli la modalità AKS per MLOps
AKS supporta due modalità del cluster: AKS Automatico e AKS Standard. Scegliere AKS Automatic quando si vuole una configurazione di base pronta per la produzione con meno attività di gestione della piattaforma successive alla distribuzione. Scegliere AKS Standard quando è necessario un controllo più approfondito sull'infrastruttura del cluster e sulla configurazione della piattaforma.
Le procedure MLOps descritte in questo articolo si applicano a entrambe le modalità. Tuttavia, la responsabilità dell'implementazione varia in base alla modalità: Il servizio Azure Kubernetes automatico fornisce impostazioni predefinite più preconfigurate, mentre il servizio Azure Kubernetes Standard richiede in genere una configurazione della piattaforma e una proprietà del ciclo di vita più espliciti.
| Area | AKS Automatico | Servizio Azure Kubernetes Standard |
|---|---|---|
| Configurazione del cluster di base | Pool di nodi preconfigurati, rete e monitoraggio pronti all’uso | Richiede la configurazione manuale di pool di nodi, CNI e stack di osservabilità |
| Operazioni del pool di nodi di sistema | Provisioning e ridimensionamento automatici dei nodi gestiti dal servizio | L'operatore deve configurare il ridimensionamento del pool di nodi, le regole di ridimensionamento e le finestre di manutenzione |
| Controlli di sicurezza di base | Criteri di rete, standard di sicurezza dei pod e identità del carico di lavoro abilitati per impostazione predefinita | Gli operatori devono abilitare e configurare in modo esplicito i criteri di rete, la sicurezza dei pod e le impostazioni di identità |
| Baseline di rete | Azure CNI Overlay preconfigurato con gli schemi di ingresso predefiniti | Flessibilità completa per scegliere il plug-in CNI, configurare controller di ingresso personalizzati e definire la topologia di rete |
| Operazioni e aggiornamenti | Aggiornamenti automatici dell'immagine del nodo e della versione di Kubernetes | Gli operatori pianificano e gestiscono le tempistiche degli aggiornamenti e la strategia di distribuzione |
| Focus sull'implementazione di MLOps | Convalidare, gestire e ottimizzare le impostazioni predefinite | Progettare e configurare i controlli della piattaforma |
| Capacità gpu e pianificazione | La capacità GPU idonea può essere sottoposta automaticamente a provisioning in base alle richieste di risorse del carico di lavoro e ai vincoli di pianificazione, in funzione della disponibilità regionale degli SKU e della quota della sottoscrizione | Gli operatori creano e gestiscono pool di nodi GPU, etichette, taint, limiti della scalabilità automatica, driver e configurazione del plug-in del dispositivo |
| Training distribuito | La pianificazione Kubernetes predefinita e il provisioning automatico dei nodi offrono un punto di partenza; gli operatori di training, le unità di pianificazione e l'ottimizzazione della topologia restano scelte a livello di carico di lavoro | Gli operatori installano esplicitamente operatori di training e scheduler e progettano pool di nodi con GPU, configurazione di rete, scalabilità e collocazione per i job distribuiti |
Infrastruttura come codice (IaC)
Considerazioni chiave: definire e modificare i modelli IaC per ogni fase della pipeline di intelligenza artificiale per garantire coerenza, efficienza dei costi e distribuzioni più veloci.
IaC consente il provisioning e la gestione coerenti e riproducibili dell'infrastruttura per una gamma di tipi di applicazioni. Con distribuzioni di applicazioni diverse, l'implementazione IaC potrebbe cambiare in tutta la pipeline di intelligenza artificiale, perché la potenza di calcolo e le risorse necessarie per l'inferenza, la gestione, il training e l'ottimizzazione dei modelli possono variare. La definizione e il controllo delle versioni dei modelli IaC per i team di sviluppo di intelligenza artificiale possono contribuire a garantire coerenza e efficienza tra i tipi di processi, chiarire i requisiti hardware e accelerare il processo di distribuzione.
In AKS Automatic, IaC può concentrarsi maggiormente sulle definizioni dei carichi di lavoro, sui vincoli di protezione dei criteri e sulla coerenza dell'ambiente, più che sui valori predefiniti della piattaforma. In AKS Standard, IaC include comunemente impostazioni della piattaforma del cluster più specifiche, come la rete, la scalabilità e le scelte di configurazione operativa.
Containerizzazione
Considerazioni chiave: peso del modello di pacchetto, metadati e configurazioni nelle immagini del contenitore per abilitare la portabilità, il controllo delle versioni semplificate e ridurre i costi di archiviazione.
La gestione dei pesi, dei metadati e delle configurazioni del modello nelle immagini container consente una maggiore portabilità, una gestione delle versioni semplificata e costi di archiviazione inferiori nel tempo. Con la containerizzazione, è possibile:
- Utilizza immagini di container esistenti, in particolare per modelli linguistici di grandi dimensioni (LLM) con un numero di parametri che va da milioni a miliardi e per modelli Stable Diffusion, archiviati in registri di container sicuri.
- Evitare un singolo punto di errore nella pipeline usando più contenitori leggeri che contengono le dipendenze univoche per ogni attività anziché mantenere un'immagine di grandi dimensioni.
- Archiviare set di dati di testo e immagine di grandi dimensioni all'esterno dell'immagine del contenitore di base e farvi riferimento quando necessario in fase di esecuzione. Inizia a usare Kubernetes AI Toolchain Operator (KAITO) per distribuire un LLM su AKS.
I controlli della supply chain dei contenitori rimangono essenziali in entrambe le modalità. Anche con le configurazioni predefinite della piattaforma in AKS Automatic, la provenienza delle immagini, la scansione e la protezione avanzata in fase di esecuzione restano responsabilità fondamentali dell’MLOps.
Modello Dockerfile per carichi di lavoro ml:
Usare un tag esplicito dell'immagine di base con supporto CUDA per i carichi di lavoro di training su GPU (ad esempio, pytorch/pytorch:2.4.1-cuda12.4-cudnn9-runtime) anziché un riferimento a un'immagine di base senza tag. In produzione, fissare l'immagine a un digest per garantire build riproducibili e un comportamento prevedibile di CUDA/cuDNN. Mantenere separate le varianti dell'immagine per CPU e GPU, in modo che l'allocazione dello scheduler e le dipendenze di runtime restino esplicite.
Gestione e controllo delle versioni dei modelli
Considerazioni chiave: versione dei modelli sistematicamente per mantenere la coerenza tra gli ambienti e abilitare un'iterazione più veloce con metodi di ottimizzazione efficiente dei parametri.
La gestione e il controllo delle versioni dei modelli sono essenziali per tenere traccia delle modifiche apportate ai modelli nel tempo. Versionando i modelli, è possibile:
- Mantenere la coerenza tra i contenitori del modello per semplificare la distribuzione in ambienti diversi.
- Impiegare metodi PEFT (Parameter-Efficient Fine-Tuning) per iterare più rapidamente su un sottoinsieme dei pesi del modello e mantenere nuove versioni in contenitori leggeri.
In AKS Automatic, le baseline della piattaforma preconfigurate possono semplificare l'uniformità tra ambienti. In AKS Standard, i team spesso devono applicare la parità in modo più esplicito tramite la configurazione della piattaforma e della distribuzione.
Automazione
Considerazioni chiave: automatizzare l'inserimento dei dati, il monitoraggio delle prestazioni del modello e ripetere il training delle pipeline per ridurre gli errori manuali e garantire la coerenza nel ciclo di vita di Machine Learning.
L'automazione consente di ridurre gli errori manuali, aumentare l'efficienza e garantire la coerenza nel ciclo di vita di Machine Learning. Automatizzando le attività, è possibile:
- Integra gli strumenti di allerta per attivare un flusso di acquisizione di vettori man mano che nuovi dati confluiscono nella tua applicazione.
- Impostare le soglie di prestazione del modello per monitorare i degradi delle prestazioni e attivare le pipeline di riaddestramento.
In entrambe le modalità AKS, includere l'automazione per la convalida dei criteri, il rilevamento della deriva della configurazione e la governance delle versioni, oltre ai trigger relativi alla qualità del modello.
Scalabilità e gestione delle risorse
Considerazioni chiave: ottimizzare l'utilizzo delle risorse tramite il calcolo distribuito, la scalabilità automatica e la pianificazione del ripristino di emergenza per gestire le diverse richieste di pipeline di intelligenza artificiale in modo conveniente.
La scalabilità e la gestione delle risorse sono fondamentali per garantire che la pipeline di intelligenza artificiale possa gestire le esigenze dell'applicazione. Ottimizzando l'utilizzo delle risorse, è possibile:
- Integrare gli strumenti che usano in modo efficiente le risorse di CPU, GPU e memoria allocate tramite il calcolo distribuito e più livelli di parallelismo, ad esempio dati, modelli e parallelismo della pipeline.
- Abilitare la scalabilità automatica nelle risorse di calcolo per supportare volumi di richieste di modelli elevati nei momenti di picco e ridurre le ore di minore attività.
- Pianifica il ripristino di emergenza seguendo le procedure consigliate di resilienza e affidabilità per AKS.
AKS Automatic può ridurre il sovraccarico di configurazione per scenari comuni di scalabilità e operatività, mentre AKS Standard offre un controllo più granulare per architetture di scalabilità personalizzate.
Eseguire processi batch a esecuzione prolungata
Concetto chiave: eseguire il lavoro finito come Kubernetes Job, rendere persistente lo stato di avanzamento all'esterno del pod, gestire i segnali di terminazione e presupporre che il Job possa essere avviato più di una volta.
Gli aggiornamenti dei nodi, i riavvii, gli eventi di riduzione delle prestazioni, la pressione delle risorse, la precedenza e gli errori dell'infrastruttura possono interrompere i processi batch a esecuzione prolungata. Un kubernetes Job sostituisce un pod non riuscito o eliminato, ma la sostituzione viene avviata in un altro nodo senza i file locali o la memoria del processo del pod precedente. Progettare l'applicazione in modo che possa riprendere da uno stato persistente e rieseguire le operazioni in sicurezza.
Usa queste pratiche per processi batch normali a uso intensivo di CPU, memoria o I/O. Le linee guida sulla pianificazione di gruppo e sulla coda dei carichi di lavoro si applicano nei casi in cui un carico di lavoro distribuito richiede che più worker si avviino contemporaneamente o in cui i team necessitano di quote condivise. Un processo batch con un singolo lavoratore o parallelizzato in modo indipendente normalmente non richiede gang scheduling.
Configurare la creazione di checkpoint, i nuovi tentativi e la terminazione
L'esempio seguente elabora una sequenza di elementi di lavoro e registra l'elemento successivo in un volume permanente File di Azure. Ripristina il checkpoint dopo la sostituzione di un pod e salva lo stato di avanzamento quando il processo riceve SIGTERM:
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
Sostituisci il ciclo di esempio con la tua applicazione batch e seleziona una soluzione di archiviazione che soddisfi i requisiti di throughput e ripristino. Usare l'identità del carico di lavoro anziché credenziali incorporate quando l'applicazione salva i checkpoint direttamente in Archiviazione BLOB di Azure o in un altro servizio Azure.
Applicare questi controlli di affidabilità deliberatamente:
-
Creazione di checkpoint e idempotenza: salvare lo stato di avanzamento a un intervallo conforme all'obiettivo del punto di ripristino. Archiviare i checkpoint e l'output di cui è stato eseguito il commit in un'archiviazione persistente, non nel file system del contenitore, in
emptyDiro nell'archiviazione locale del nodo. Usare scritture atomiche, chiavi di idempotenza, output transazionale o deduplicazione perché lo stesso programma Job può talvolta essere avviato più di una volta. -
Comportamento al riavvio: un Job consente
restartPolicy: NeveroOnFailure. ConNever, un contenitore con esito negativo genera un pod con esito negativo e il controller Job crea un sostituto. ConOnFailure, il kubelet può riavviare il container nello stesso pod. UsareNeverquando pod con esito negativo e log separati semplificano la diagnosi e assicurarsi che entrambi i percorsi possano riprendere in modo sicuro. -
Limiti di ripetizione dei tentativi: impostare
backoffLimitin base al numero di errori temporanei che il carico di lavoro può tollerare. UsarepodFailurePolicyper terminare immediatamente con esito negativo in caso di codici di uscita noti non ritentabili oppure, come nell'esempio, per impedire che le interruzioni volontarie consumino il budget dei nuovi tentativi. Un'interruzione può comunque arrestare il pod; il criterio modifica solo il modo in cui il Job conteggia tale errore. -
Scadenze: impostare
activeDeadlineSecondsquando il processo deve essere arrestato dopo un runtime totale massimo. La scadenza include i nuovi tentativi e ha la precedenza subackoffLimit. Non impostare una scadenza più breve del runtime previsto, oltre al tempo di ripetizione e ripristino. Un processo non riuscito non viene riavviato automaticamente come nuovo processo. -
Terminazione normale: gestire
SIGTERMnell'applicazione e impostareterminationGracePeriodSecondssu un valore sufficientemente lungo da interrompere l'accettazione di nuovo lavoro, completare o abbandonare in sicurezza l'unità corrente, scaricare l'output e salvare un checkpoint. Kubernetes inviaSIGKILLse il processo supera il periodo di tolleranza, quindi i checkpoint periodici rimangono necessari. -
Pulizia: imposta
ttlSecondsAfterFinishedo configura i limiti della cronologia dei CronJob per evitare che i Job e i pod completati si accumulino. Conservare i record del Job abbastanza a lungo per la raccolta dei log e l'analisi degli eventi imprevisti.
Pianificare le eliminazioni e la manutenzione dei nodi
Non considerare il blocco delle rimozioni come strategia di ripristino principale per un processo a esecuzione prolungata. Per un processo batch riavviabile, normalmente non creare un PodDisruptionBudget (PDB); il controller Job crea un pod sostitutivo dopo un'interruzione volontaria. Un PDB protegge solo dalle espulsioni volontarie e non protegge dal guasto del nodo, dall'espulsione dovuta alla pressione sulle risorse o dalla preemption. Un PDB che non consente alcuna interruzione può anche bloccare il drain dei nodi e ritardare gli aggiornamenti di AKS.
Usare un PDB solo quando un carico di lavoro batch parallelo deve mantenere un numero minimo di lavoratori in esecuzione simultanea e ne è stato testato il comportamento di svuotamento. Allo stesso modo, usare cluster-autoscaler.kubernetes.io/safe-to-evict: "false" solo per operazioni eccezionali che non possono essere riavviate. L'annotazione può impedire la riduzione delle prestazioni e aumentare i costi, ma non protegge da errori del nodo o da ogni evento di manutenzione.
Gli aggiornamenti di AKS eseguono il cordon e lo svuotamento dei nodi precedenti prima di sostituirli. Configura le finestre di manutenzione pianificata in modo che la manutenzione supportata di AKS coincida con periodi di minore impatto, ma assicurati che il carico di lavoro sia riavviabile perché la pianificazione della manutenzione non elimina le interruzioni non pianificate. Per AKS Standard, eseguire processi batch in un pool di nodi utente dedicato quando richiedono dimensioni di VM separate, limiti di scalabilità, vincoli (taint) o finestre di aggiornamento distinte. Evitare i pool di nodi Spot per il lavoro che non può essere ripristinato dopo una preemption. Prima della manutenzione dei nodi, verificare che i checkpoint recenti siano utilizzabili e che un altro pool di nodi idoneo disponga di quota e capacità sufficienti per eseguire i pod sostitutivi.
Monitora l'avanzamento e il ripristino dei processi
Usa insieme lo stato, gli eventi e i log di Kubernetes quando esamini un job di lunga durata:
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
Abilitare il servizio gestito di Monitoraggio di Azure per Prometheus e Container Insights per conservare i log e correlare lo stato del processo con i riavvii dei pod, le espulsioni, il tempo di attesa, l'integrità dei nodi e l'utilizzo delle risorse. Instrumentare l'applicazione con segnali di avanzamento aziendale, ad esempio elementi completati, elementi non riusciti, ora dell'ultimo checkpoint riuscito, frequenza di elaborazione, numero di tentativi e tempo di completamento stimato. Generare avvisi in caso di processo con esito negativo, processo che supera la durata prevista, assenza di checkpoint entro l'obiettivo del punto di ripristino, sostituzioni ripetute dei pod, pod in sospeso per periodi prolungati e velocità effettiva di elaborazione bloccata.
Sicurezza e conformità
Considerazioni chiave: implementare analisi CVE, audit trail e controlli di conformità per proteggere i dati e soddisfare i requisiti normativi, ad esempio SOC 2, HIPAA e GDPR.
La sicurezza e la conformità sono fondamentali per proteggere i dati e garantire che la pipeline di intelligenza artificiale soddisfi i requisiti normativi. Implementando le procedure consigliate per la sicurezza e la conformità, è possibile:
- Integrare l'analisi delle vulnerabilità comuni e delle esposizioni (CVE) per rilevare le vulnerabilità comuni nelle immagini dei contenitori di modelli open source.
- Usa Microsoft Defender for Containers per le immagini del contenitore del modello archiviate in Registro Azure Container.
- Mantenere un audit trail dei dati inseriti, delle modifiche del modello e delle metriche per rimanere conformi ai criteri dell'organizzazione.
- Supportare framework di conformità come SOC 2 (tramite la registrazione di controllo e i controlli di accesso di Azure), HIPAA (tramite crittografia dei dati inattivi e in transito, isolamento della rete) e GDPR (tramite opzioni di residenza dei dati e criteri di gestione degli accessi).
In AKS Automatic, le impostazioni predefinite di sicurezza preconfigurate migliorano il livello di protezione di base, ma i controlli di sicurezza a livello di modello, di dati e di pipeline restano comunque necessari.
Pianificare i carichi di lavoro GPU
Concetto chiave: esporre le GPU tramite il plug-in del dispositivo NVIDIA, richiedere esplicitamente le GPU e isolare i costosi nodi GPU con etichette, taint e tolleranze.
Kubernetes pianifica le GPU come risorse estese. Dopo che il plug-in del dispositivo di NVIDIA registra le GPU su un nodo, un pod richiede una GPU impostando nvidia.com/gpu sia in resources.requests che in resources.limits. Il pod seguente richiede una GPU e ha come destinazione un pool di nodi con etichetta 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
Le risorse estese non vengono sovracommesse. Kubernetes considera un limite di GPU come richiesta GPU quando viene specificato solo il limite, ma l'impostazione di entrambi i campi rende esplicita la finalità del carico di lavoro e consente la convalida dei criteri.
Effettuare il provisioning di un pool di nodi GPU di AKS
Per AKS Standard, creare un pool di nodi utente dedicato con dimensioni di VM NVIDIA GPU supportate. L'esempio seguente di interfaccia della riga di comando di Azure crea un pool di nodi con scalabilità automatica Standard_NC4as_T4_v3, applica l'etichetta utilizzata dal pod precedente e applica un taint ai nodi per respingere i carichi di lavoro che non tollerano esplicitamente i nodi GPU:
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
Prima di creare il pool di nodi, verificare che lo SKU della macchina virtuale sia disponibile nell'area del cluster e che la sottoscrizione disponga di una quota sufficiente a livello di area e famiglia di macchine virtuali. Selezionare una dimensione della serie NC in base alla memoria GPU, al numero di GPU, al rapporto CPU-GPU, all'archiviazione locale, alla rete e alle funzionalità CUDA richieste dal framework di training. Ad esempio, le dimensioni NCas T4 v3 sono adatte per molti carichi di lavoro di training a gpu singola e di dimensioni inferiori, mentre le dimensioni NC A100 v4 supportano modelli più grandi e configurazioni GPU a istanze multipla.
AKS Automatic può effettuare automaticamente il provisioning della capacità GPU idonea in risposta ai pod in sospeso. Il carico di lavoro deve comunque richiedere nvidia.com/gpue tutti i selettori di nodo, le affinità, le tolerazioni, i vincoli di topologia, le quote di sottoscrizione e la disponibilità dello SKU a livello di area devono essere soddisfacenti. Usa AKS Standard se hai bisogno di uno SKU VM fisso, un ciclo di vita del pool di nodi personalizzato o un controllo dettagliato del ridimensionamento e della topologia del pool GPU.
Verificare o installare il plug-in del dispositivo NVIDIA
Le configurazioni GPU di AKS possono fornire driver GPU gestiti e l'integrazione con il plug-in per i dispositivi. Verificare la configurazione effettiva prima di installare un altro plug-in:
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"
Non eseguire più DaemonSet di plug-in del dispositivo NVIDIA negli stessi nodi. Se la configurazione di AKS non gestisce il plugin, il seguente DaemonSet autonomo registra le GPU NVIDIA con il kubelet. Installare una versione del plug-in del dispositivo supportata dalle versioni di NVIDIA Driver e Kubernetes:
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
Prima di inviare processi di training, verificare che nvidia.com/gpu sia visualizzato tra le risorse allocabili di ogni nodo GPU.
Suddividere in partizioni le GPU A100 e H100 con MIG
NVIDIA Multi-Instance GPU (MIG) può partizionare una GPU A100 o H100 supportata in istanze GPU isolate. MIG è utile per l'ottimizzazione degli iperparametri e per i processi di ottimizzazione più piccoli che non richiedono un'intera GPU fisica. Usare GPU complete per i carichi di lavoro che richiedono tutta la memoria GPU, la larghezza di banda massima di interconnessione o un profilo non supportato dalla GPU installata.
Usare l'operatore GPU NVIDIA e MIG Manager quando è necessaria la gestione dichiarativa del ciclo di vita MIG. L'operatore deve possedere il plug-in del dispositivo e la configurazione MIG per i nodi interessati; non combinarlo con un secondo plug-in di dispositivo autonomo. I nomi e il numero di profili esatti dipendono dal modello GPU e dalla capacità di memoria. La configurazione seguente crea sette 1g.10gb istanze nelle configurazioni di 80 GB A100 o H100 supportate:
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
Configurare il gestore MIG dell'operatore GPU per utilizzare la ConfigMap mig-parted-config, usare la strategia MIG mixed quando i carichi di lavoro richiedono profili MIG con nome e quindi etichettare i nodi di destinazione:
kubectl label nodes \
-l accelerator=nvidia \
nvidia.com/mig.config=hptuning-1g10gb \
--overwrite
La modifica di un layout MIG interrompe i carichi di lavoro già usando la GPU. Eseguire Disabilitazione della pianificazione e lo svuotamento del nodo di destinazione, applicare la configurazione durante una finestra di manutenzione e verificare che il profilo richiesto sia presente nelle risorse allocabili del nodo prima di inviare i processi.
Isolare i carichi di lavoro delle GPU con taints e tolerations
Un taint NoSchedule impedisce ai normali pod dell'applicazione di essere pianificati nei costosi nodi GPU. L'esempio di creazione del pool di nodi applica sku=gpu:NoSchedule. Il processo completo seguente include la tolleranza corrispondente e un selettore di nodi:
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
Una tolleranza consente la pianificazione, ma non impone il posizionamento del pod in un nodo GPU. Associare le tolleranze a una richiesta di risorse GPU e a un selettore di nodo o all'affinità del nodo. Verificare che i DaemonSet della piattaforma necessari, ad esempio quelli per rete, monitoraggio, archiviazione e plug-in del dispositivo, tollerino il taint GPU.
Eseguire carichi di lavoro di training distribuiti
Aspetti chiave: usare un operatore di addestramento per gestire le identità dei worker e il ciclo di vita dei job, convalidare la comunicazione di rete tra nodi multipli e usare l'ammissione di gruppo quando tutti i worker devono avviarsi insieme.
Il training distribuito usa più processi per dividere i dati, lo stato del modello o le fasi della pipeline. In Kubernetes, un operatore può creare pod worker, inserire la configurazione rendezvous, tenere traccia dello stato delle repliche, riavviare i worker non riusciti e pulire il processo. Installare e gestire le versioni degli operatori di training tramite il processo IaC e di rilascio della piattaforma, anziché consentire ai singoli team di installare CRD non regolamentate a livello di cluster.
Creare un'immagine CUDA di addestramento portatile
Il Dockerfile seguente amplia il modello di Dockerfile individuato nella sezione Containerizzazione. L'immagine contiene il runtime CUDA e le librerie PyTorch, mentre il driver NVIDIA compatibile rimane sul nodo GPU di AKS:
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"]
In produzione, fissare l'immagine di base a un digest non modificabile. Mantenere i set di dati e modificare frequentemente i checkpoint all'esterno dell'immagine e analizzare l'immagine risultante prima di eseguirne il push in Registro Azure Container.
Eseguire un PyTorchJob
Kubeflow Training Operator fornisce la CRD PyTorchJob. Installare una versione di Training Operator compatibile con la versione di Kubernetes prima di applicare questo manifesto. L'esempio seguente con due repliche esegue un'operazione all-reduce NCCL tra un master e un 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
Per il training in produzione, sostituire il test inline con l'immagine e lo script di training con controllo delle versioni. Allineare i conteggi delle repliche al numero di GPU e processi richiesti dal framework di training.
Eseguire un TFJob
Training Operator fornisce anche la CRD TFJob. L'esempio seguente esegue il training sincrono di TensorFlow tra due worker GPU tramite 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
Per l'addestramento con server dei parametri, definire i tipi di replica Chief, Worker e PS in base alla strategia di distribuzione di TensorFlow. Misurare i colli di bottiglia risultanti della rete e del server dei parametri prima di aumentare il numero di repliche.
Ottimizzare un modello con KAITO
KAITO offre un'astrazione dell'area di lavoro incentrata su AKS per la distribuzione e l'ottimizzazione dei modelli. Abilitare il componente aggiuntivo KAITO o installare una versione KAITO compatibile prima di applicare un Workspace. Verificare che il set di impostazioni selezionato, lo SKU della macchina virtuale e il metodo di ottimizzazione siano supportati dalla versione di KAITO installata.
L'area di lavoro seguente richiede una macchina virtuale GPU A100 e avvia l'ottimizzazione QLoRA per un set di impostazioni Phi-3 supportato usando un set di dati accessibile pubblicamente:
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 può coordinare la configurazione predefinita del modello e l'infrastruttura GPU necessaria per l'area di lavoro. Per l’uso in produzione, archiviare il set di dati di addestramento in un account di archiviazione di Azure approvato, usare l’accesso privato e l’identità del carico di lavoro ove supportati e salvare in modo permanente il modello risultante in un registro dei modelli soggetto a governance o in Registro Azure Container. Considerare il manifesto dell'area di lavoro, la versione del set di dati di input, la versione del set predefinito, la configurazione dell'adapter e il digest dell'immagine di output come un unico record di training con controllo delle versioni.
Configurare la comunicazione NCCL con CNI di AKS
NVIDIA Collective Communications Library (NCCL) gestisce operazioni collettive come all-reduce. Per una baseline TCP trasferibile su AKS CNI, usare l'interfaccia di rete del pod, normalmente eth0, e iniziare con NCCL_IB_DISABLE=1. Per le dimensioni di VM supportate abilitate per RDMA, utilizzare la configurazione RDMA di NVIDIA e Azure documentata e convalidarla prima di impostare NCCL_IB_DISABLE=0.
Usare queste variabili di ambiente di base:
-
NCCL_SOCKET_IFNAME=eth0seleziona l'interfaccia di rete del pod. -
NCCL_DEBUG=INFOfornisce informazioni di diagnostica durante la convalida. Ridurre il livello di log dopo l'ottimizzazione. -
NCCL_IB_DISABLE=1seleziona i socket TCP quando RDMA non è configurato. -
TORCH_NCCL_ASYNC_ERROR_HANDLING=1aiuta PyTorch a terminare invece di bloccarsi a tempo indefinito dopo errori di comunicazione asincroni.
Se i criteri di rete sono abilitati, consentire tutto il traffico rendezvous e NCCL necessario tra le repliche. NCCL può negoziare porte dinamiche, quindi criteri limitati a poche porte fisse possono causare il blocco dei processi di training. I criteri seguenti consentono la comunicazione da pod a pod senza restrizioni solo tra le repliche del processo PyTorch e consente la risoluzione DNS:
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
Eseguire il benchmark di NCCL indipendentemente dal training del modello prima di eseguire lo scale-out. Confrontare la larghezza di banda all-reduce, la latenza, l'utilizzo della GPU e la capacità effettiva del training per ogni numero di worker. Un numero maggiore di worker può ridurre le prestazioni quando la comunicazione o il caricamento dei dati diventa il collo di bottiglia.
Usare la pianificazione gang e le code dei carichi di lavoro
Concetto chiave: ammettere i worker distribuiti come gruppo e applicare le quote GPU del tenant, affinché i processi pianificati solo parzialmente non riservino GPU mentre attendono i worker rimanenti.
L'unità di pianificazione Kubernetes predefinita posiziona i pod singolarmente. Per un processo distribuito che non può procedere finché non sono in esecuzione tutti i worker, il posizionamento parziale può sprecare capacità GPU. Kueue fornisce il controllo di ammissione e la gestione delle quote prima dell'avvio dei pod. Volcano fornisce uno scheduler e un modello di pianificazione all-or-nothing basato su PodGroup.
AKS Automatic fornisce l'unità di pianificazione Kubernetes predefinita e il provisioning automatico dei nodi come punto di partenza. Inviare processi normali o gestiti da operatori con richieste di risorse accurate e consentire alla piattaforma di effettuare il provisioning della capacità idonea. Questo comportamento non garantisce l'ammissione atomica di tutti i worker. Installare Kueue o Volcano quando un carico di lavoro richiede pianificazione gang, accodamento, quote dei team, condivisione equa o un comportamento di preemption personalizzato.
Allocare quote GPU multi-tenant con Kueue
Installare una versione kueue compatibile con la versione di Kubernetes e abilitare le integrazioni per i tipi di carico di lavoro usati. Il manifesto seguente crea:
- GPU
ResourceFlavorassociata ai nodi con etichettaaccelerator=nvidia. - Quattro GPU
ClusterQueueper il team A. - Una configurazione a due GPU
ClusterQueueper il team B. - Una
LocalQueuecon ambito spazio dei nomi per ogni team. - Un processo con due lavoratori che Kueue ammette solo quando sono disponibili le risorse richieste.
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
Una ClusterQueue quota è una quota di pianificazione, non una quota di sottoscrizione Azure. Assicurarsi che il cluster AKS sia in grado di eseguire il provisioning della capacità delle macchine virtuali sottostanti e che la quota GPU di Azure sia sufficiente per il carico di lavoro complessivo ammesso. Utilizzare le coorti e le funzionalità di condivisione equa delle risorse di Kueue quando i team possono prendere in prestito reciprocamente la quota inutilizzata.
Usare il vulcano come alternativa
Volcano è un'alternativa quando è necessario un'unità di pianificazione batch dedicata con pianificazione gang, code e criteri del ciclo di vita dei processi. Installare una versione di Volcano compatibile con il cluster prima di applicarne le CRD. Il processo Volcano seguente richiede che entrambi i worker GPU siano disponibili prima dell'esecuzione:
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
Adottate un unico sistema primario di accodamento e di scheduling di gruppo, a meno che non disponiate di un design di interoperabilità collaudato. In caso contrario, più controller di ammissione o unità di pianificazione possono rendere difficile comprendere il comportamento relativo agli elementi in sospeso e alla preemption.
Configurare le priorità di training e inferenza
L'inferenza sensibile alla latenza richiede in genere una priorità più alta rispetto all'addestramento in batch interrompibile. Le risorse PriorityClass seguenti consentono ai pod di inferenza di eseguire la preemption dei pod con priorità inferiore, impedendo al contempo ai pod di training batch di eseguire la preemption di altri carichi di lavoro:
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.
Assegnare la classe tramite spec.priorityClassName nel modello di pod. La priorità dei pod Kubernetes e la priorità dei carichi di lavoro Kueue influiscono su fasi diverse: Kueue controlla l'ammissione alla coda, mentre la priorità Kubernetes influisce sulla pianificazione e sulla preemption dei pod dopo l'ammissione. Coordinare entrambi i criteri in modo da esprimere la stessa priorità aziendale.
La preemption termina i pod con priorità bassa. I carichi di lavoro di training soggetti a preemption devono scrivere checkpoint nell'archiviazione persistente, tollerare il lavoro duplicato ed eseguire il ripristino senza dipendere dai file locali del nodo.
Configurare la memoria condivisa e la gestione delle risorse
Considerazioni chiave: sostituire il piccolo valore predefinito /dev/shmdel runtime del contenitore, impostare le richieste di risorse dall'utilizzo osservato e configurare il ridimensionamento dei nodi in base ai requisiti completi del carico di lavoro GPU.
Aumentare /dev/shm per i caricatori di dati di Machine Learning
I caricatori di dati PyTorch, le pipeline di input TensorFlow, NCCL e Python multiprocessore possono usare la memoria condivisa POSIX. Il valore predefinito di /dev/shm nel contenitore è spesso troppo ridotto per il training multiprocesso e può causare arresti anomali dei worker, errori del bus o apparenti blocchi del training.
Montare un oggetto emptyDir supportato dalla memoria in /dev/shm e impostare un oggetto sizeLimit esplicito:
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
L'utilizzo di un oggetto emptyDir supportato dalla memoria viene conteggiato nel consumo di memoria del pod. Includere l'utilizzo massimo previsto della memoria condivisa quando si imposta il limite di memoria del contenitore. Se /dev/shm supera il budget di memoria effettivo, il pod può essere rimosso o terminato perché ha superato il limite di memoria.
Dimensiona CPU e memoria in base all'utilizzo osservato
Inizia con un benchmark basato su un modello rappresentativo, sulla dimensione del batch, sulla lunghezza della sequenza, sulla concorrenza nel caricamento dei dati, sull'aumento dei dati e sulla gestione dei checkpoint. Usare quindi i dati di monitoraggio per modificare:
- Impostare le richieste cpu sufficientemente elevate per mantenere fornite le pipeline di input GPU. Periodi prolungati di inattività della GPU possono indicare una carenza di risorse della CPU o dello storage.
- Impostare le richieste di memoria vicino all'utilizzo stabile del working set più un margine di sicurezza. Includere
/dev/shm, il comportamento della cache delle pagine, l'overhead dell'allocatore del framework e i picchi di serializzazione dei checkpoint. - Impostare i limiti di memoria al di sopra del picco osservato. Analizzare
OOMKilledgli eventi anziché aumentare ripetutamente i limiti senza trovare la causa. - Valutare il throttling della CPU prima di utilizzare limiti restrittivi. I limiti della CPU troppo bassi possono ridurre l'utilizzo della GPU anche quando l'utilizzo medio della CPU risulta accettabile.
- Impostare richieste e limiti sullo stesso valore per processi di training prevedibili e di valore elevato, quando la qualità del servizio Guaranteed è più importante della densità dei nodi.
- Esegui il profiling di ogni modifica significativa alla dimensione del modello, alla precisione, alla dimensione del batch, al numero di worker e alla pipeline dei dati.
Usare i percentili relativi a esecuzioni di training complete anziché una media di breve durata. Le fasi di avvio, convalida, checkpoint e shuffle dei dati spesso presentano picchi di risorse diversi.
Configurare la scalabilità automatica del cluster per un pool di nodi GPU
Per AKS Standard, abilitare il ridimensionamento automatico del cluster nel pool di nodi utente GPU e definire la capacità minima e massima:
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
È possibile ottimizzare le impostazioni del profilo di scalabilità automatica del cluster supportate nell'ambito del cluster. Testare le modifiche del profilo con i carichi di lavoro di training e inferenza:
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
Un pod GPU in sospeso attiva l'aumento delle prestazioni solo quando i requisiti di pianificazione completi corrispondono a un modello di pool di nodi. Controlla la richiesta di risorse GPU, la capacità della VM, le etichette, i taint, le tolleranze, l'affinità, i vincoli di topologia, la topologia del volume persistente, il numero massimo di nodi e la quota di Azure quando non si verifica lo scale-up.
La scalabilità fino a zero è indicata per i pool di addestramento interrompibili, ma aggiunge latenza al provisioning delle macchine virtuali, al recupero delle immagini, al montaggio del set di dati e all'inizializzazione del modello. Mantenere un valore minimo diverso da zero quando la latenza di avvio ha un effetto materiale sugli obiettivi del servizio. I budget di interruzione dei pod, i pod non rimovibili, l'archiviazione locale e i periodi di tolleranza di terminazione lunghi possono ritardare lo scale-down.
AKS Automatic gestisce il provisioning e il ridimensionamento dei nodi come parte della configurazione di base del servizio. Concentrarsi sulle richieste accurate dei pod e sui vincoli supportati invece di configurare un'utilità di scalabilità automatica del pool di nodi GPU manuale.
Archiviare set di dati e checkpoint
Concetto chiave: selezionare l'archiviazione in base a modello di accesso, velocità effettiva, condivisione e requisiti di ripristino e rendere persistenti i checkpoint all'esterno del nodo, in modo che il training possa riprendere dopo una rimozione o una preemption.
Non includere set di dati di grandi dimensioni, artefatti dei modelli e checkpoint nelle immagini dei contenitori. Scegliere un'interfaccia di archiviazione in base al carico di lavoro:
- Usare Archiviazione BLOB di Azure per set di dati di oggetti di grandi dimensioni, artefatti del modello e repository di dati ad alta capacità.
- Usare File di Azure quando più nodi di lavoro richiedono un file system di tipo POSIX condiviso.
- Usare Azure Disco per carichi di lavoro a prestazioni elevate, checkpoint di lettura/scrittura a nodo singolo o cache in cui
ReadWriteOnceè sufficiente. - Usare l'archiviazione temporanea node-local solo per le cache ricostruibili e i file temporanei.
Accedere a set di dati di grandi dimensioni con il driver CSI BLOB Azure
Abilita il driver CSI di Azure Blob in AKS Standard, se non è già abilitato:
RESOURCE_GROUP=myResourceGroup
AKS_CLUSTER=myAKSCluster
az aks update \
--resource-group "$RESOURCE_GROUP" \
--name "$AKS_CLUSTER" \
--enable-blob-driver
L'esempio seguente crea dinamicamente un contenitore BLOB premium di Azure accessibile tramite NFS e lo monta in un pod di addestramento. Per un set di dati regolamentato esistente, usare un volume definito in modo statico o una configurazione BlobFuse con i controlli di rete privati e di identità appropriati anziché creare un contenitore dinamico vuoto:
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
Eseguire il benchmark delle opzioni di protocollo e montaggio in base alle dimensioni delle partizioni rappresentative e ai modelli di accesso. Molti worker che leggono numerosi file di piccole dimensioni possono produrre risultati diversi rispetto allo streaming sequenziale di shard di grandi dimensioni. Valutare la preelaborazione dei set di dati in frammenti di dimensioni appropriate e l'uso dello spazio di cache locale del nodo quando, altrimenti, epoche ripetute scaricherebbero gli stessi oggetti.
Condividere i dati di training con File di Azure
File di Azure supporta ReadWriteMany, che consente ai worker distribuiti in nodi diversi di montare la stessa condivisione. Il File di Azure Premium è appropriato quando il carico di lavoro richiede prestazioni prevedibili del file system e l'area selezionata supporta l'opzione di ridondanza necessaria.
Il manifesto seguente crea una condivisione File di Azure Premium e la monta in due pod di lavoro paralleli:
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
Evitare che ogni worker enumeri ripetutamente una directory contenente milioni di file. Usare un manifesto o un'assegnazione deterministica degli shard in modo che ogni worker sappia quali oggetti leggere.
Punto di controllo nell'archiviazione persistente
Un checkpoint deve includere uno stato sufficiente per riprendere correttamente, ad esempio pesi del modello, stato dell'ottimizzatore, stato dello scheduler, stato dello scaler, numero di epoca o passaggio, stato del generatore di numeri casuali e posizione del caricatore di dati, se supportata. Scrivere checkpoint periodicamente e prima della terminazione normale.
Il processo seguente scrive checkpoint PyTorch atomici in File di Azure, ripristina il checkpoint più recente dopo il riavvio di un contenitore o la sostituzione di un pod e gestisce SIGTERM in modo che la preemption possa mantenere i progressi recenti:
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
Usare criteri di recupero Retain o un account di archiviazione gestito in modo indipendente per i checkpoint di produzione, affinché l'eliminazione di un PVC non elimini involontariamente l'unico punto di ripristino. Per il training parallelo ai dati distribuito, in genere fare in modo che il rango zero scriva il checkpoint globale oppure usare un formato di checkpoint con partizionamento supportato dal framework. Impedire a più ranghi di scrivere contemporaneamente nello stesso file.
Testare il ripristino eliminando deliberatamente un pod worker durante un'esecuzione non di produzione. Verificare che il controller ricrei il carico di lavoro, che il nuovo pod monti lo stesso volume persistente e che il training riprenda dal passaggio previsto.
Monitorare l'utilizzo della GPU e la velocità effettiva di training
Concetto chiave: monitorare insieme il calcolo GPU, la memoria GPU, la velocità effettiva della pipeline di dati, la durata dei passaggi e l'attività dei checkpoint, in modo da distinguere la saturazione di calcolo dai colli di bottiglia di CPU, rete o archiviazione.
Abilitare il servizio gestito di Monitoraggio di Azure per Prometheus e Container Insights per correlare lo stato di Kubernetes, i log dei contenitori, l'integrità dei nodi e le metriche di Prometheus. Usa le procedure consigliate per il monitoraggio di AKS durante la progettazione di avvisi, conservazione dei dati e dashboard operative.
Raccolta delle metriche delle GPU NVIDIA
NVIDIA Data Center GPU Manager (DCGM) Exporter espone le metriche Prometheus delle GPU NVIDIA. Se l'operatore GPU NVIDIA distribuisce già DCGM Exporter, non distribuire un esportatore duplicato. Configurare Prometheus gestito di Monitoraggio di Azure per eseguire lo scraping dell'esportatore esistente.
Il seguente PodMonitor usa il CRD Prometheus gestito di Monitoraggio di Azure e ha come destinazione i pod di DCGM Exporter nel namespace gpu-operator. Modificare il selettore di etichette in modo che corrisponda alle etichette usate dall'utilità di esportazione installata:
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
Verificare il nome del servizio dell'esportatore o della porta del pod prima di applicare il monitoraggio. Le metriche DCGM comuni includono:
| Metrica | Purpose |
|---|---|
DCGM_FI_DEV_GPU_UTIL |
Percentuale di tempo in cui la GPU è attiva |
DCGM_FI_DEV_FB_USED |
Memoria frame buffer utilizzata |
DCGM_FI_DEV_FB_FREE |
Memoria libera del frame buffer |
DCGM_FI_DEV_MEM_COPY_UTIL |
Utilizzo del motore di copia della memoria |
DCGM_FI_DEV_POWER_USAGE |
Consumo di energia GPU |
DCGM_FI_DEV_GPU_TEMP |
Temperatura GPU |
DCGM_FI_DEV_XID_ERRORS |
Eventi di errore NVIDIA XID |
La disponibilità delle metriche dipende dalle versioni della GPU, del driver, di DCGM e dell'exporter.
Esportare le metriche della velocità effettiva del training
Monitorare l'applicazione di addestramento con metriche a livello di carico di lavoro. Le metriche utili includono:
-
ml_training_samples_totalper i campioni o i token elaborati cumulativi. -
ml_training_steps_totalper i passaggi dell'ottimizzatore completati. -
ml_training_step_duration_secondsper latenza dei passaggi. -
ml_training_checkpoint_duration_secondsper la latenza dei checkpoint. -
ml_training_data_wait_secondsper il tempo in attesa dei dati di input. - Perdita specifica del modello, tasso di apprendimento, norma del gradiente e metriche di validazione.
Nell'esempio eseguibile seguente vengono esposte metriche di training sintetiche sulla porta 8000. Sostituire la simulazione con le metriche generate dal ciclo di training reale:
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
Per un processo distribuito reale, includere etichette stabili, ad esempio il nome del modello, la versione del modello, il nome del processo, l'ID esecuzione, il ruolo di replica e il team. Non usare etichette non associate, ad esempio ID di esempio, ID richiesta o percorsi di set di dati non elaborati perché le etichette con cardinalità elevata aumentano i costi di monitoraggio e la latenza delle query.
Creare dashboard per GPU e velocità effettiva
Usare query PromQL come quelle seguenti come punti di partenza e convalidare le etichette delle metriche rispetto all'esportatore:
avg by (namespace, pod, gpu) (
avg_over_time(DCGM_FI_DEV_GPU_UTIL[5m])
)
La query seguente calcola l'utilizzo della memoria del buffer di frame come percentuale:
100 *
DCGM_FI_DEV_FB_USED
/
(DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE)
La seguente interrogazione calcola i campioni di addestramento elaborati al secondo:
sum by (job_name) (
rate(ml_training_samples_total[5m])
)
Nella query seguente viene visualizzata la durata media dei passaggi:
avg by (job_name) (
ml_training_step_duration_seconds
)
Interpretare questi segnali insieme:
- L'utilizzo ridotto della GPU e il tempo di attesa dei dati elevato indicano in genere archiviazione, rete, pre-elaborazione o fame della CPU.
- Un utilizzo elevato della GPU con velocità effettiva prevista indica che l'acceleratore viene usato in modo efficace.
- Un uso elevato della memoria GPU e ripetuti errori di esaurimento della memoria indicano che la dimensione del batch, la lunghezza della sequenza, la memoria di attivazione, lo stato dell’ottimizzatore o la frammentazione richiedono un aggiustamento.
- La riduzione della velocità effettiva con un utilizzo stabile della GPU può indicare sequenze più lunghe, sovraccarico di comunicazione, comportamento termico o una modifica nel calcolo del modello.
- Un utilizzo ridotto delle GPU allocate indica capacità inattiva che potrebbe essere ridotta, accodata in modo diverso o partizionata con MIG.
- Una lunga durata dei checkpoint può rendere costosa la preemption e aumentare la quantità di lavoro ripetuto dopo il ripristino.
Creare avvisi per sottoutilizzo prolungato delle GPU, memoria GPU prossima alla capacità, errori XID, velocità effettiva del training bloccata, worker non riusciti, carichi di lavoro pianificati in gang in sospeso e checkpoint che non sono stati completati entro l'obiettivo del punto di ripristino previsto.
Domande frequenti
Qual è la differenza tra AKS Automatic e AKS Standard per MLOps?
AKS Automatic fornisce configurazioni predefinite per pool di nodi, rete, sicurezza e aggiornamenti, consentendo ai team MLOps di concentrarsi sulle definizioni dei carichi di lavoro e sulla governance. AKS Standard richiede la configurazione manuale di questi componenti della piattaforma, ma offre un maggiore controllo per architetture personalizzate e requisiti di scalabilità.
Come si gestiscono le versioni dei modelli di Machine Learning in AKS?
Gestire le versioni dei modelli inserendo pesi, metadati e configurazioni dei modelli in immagini contenitore con tag di versione semantici. Archiviare queste immagini in Registro Azure Container e fare riferimento a versioni specifiche nei manifesti della distribuzione kubernetes per garantire la coerenza tra gli ambienti.
Come si pianifica i carichi di lavoro GPU in AKS?
Assicurarsi che il plug-in del dispositivo NVIDIA sia disponibile in modo che i nodi GPU pubblicizzino nvidia.com/gpu. In AKS Standard, effettuare il provisioning di un pool di nodi utente GPU dedicato con una dimensione VM supportata, ad esempio uno SKU della serie Standard_NC, e configurare etichette dei nodi, un taint NoSchedule e i limiti della scalabilità automatica del cluster. In ogni pod di addestramento, richiedete nvidia.com/gpu, selezionate un nodo GPU idoneo e aggiungete la tollerazione corrispondente. AKS Automatic può effettuare il provisioning di capacità GPU idonea in base alle richieste dei pod, in funzione delle SKU supportate, della disponibilità a livello di area geografica, dei vincoli di pianificazione e della quota della sottoscrizione Azure.
Come si eseguono processi di training distribuiti in AKS?
Installare Kubeflow Training Operator e inviare un oggetto PyTorchJob o TFJob per gestire repliche distribuite, configurazione rendezvous, comportamento di riavvio e stato del processo. KAITO fornisce un'astrazione dello spazio di lavoro incentrata su AKS per i flussi di lavoro supportati per il fine-tuning dei modelli e può coordinare l'infrastruttura GPU con le configurazioni predefinite del modello. Per il training PyTorch multinodo, configurare ed eseguire il benchmark di NCCL nella rete pod CNI di AKS, consentire il traffico tra worker tramite i criteri di rete e usare una configurazione RDMA supportata quando richiesto dallo SKU della VM e dal carico di lavoro selezionati.
Come si gestisce la quota gpu tra più team?
Installare Kueue e definire le risorse ClusterQueue con quote di CPU, memoria e nvidia.com/gpu, quindi associare il namespace di ogni team alla quota assegnata tramite LocalQueue. Usare coorti Kueue o la condivisione equa quando i team possono prendere in prestito la capacità inutilizzata. Volcano è un'alternativa quando è necessario uno scheduler batch con ammissione dei worker di tipo tutto o niente. Coordinare la priorità delle code con le risorse PriorityClass di Kubernetes, in modo che l'inferenza sensibile alla latenza possa eseguire la preemption del training interrompibile, e verificare che i processi di training soggetti a preemption possano essere ripristinati dai checkpoint nell'archiviazione persistente.
Quali sono le procedure consigliate per eseguire processi batch di lunga durata in AKS?
Usare un Kubernetes Job per attività limitate e un CronJob per attività pianificate. Rendere persistenti i checkpoint e l'output di cui è stato eseguito il commit all'esterno del pod, rendere l'elaborazione idempotente, gestire SIGTERM e impostare richieste di risorse, limiti dei nuovi tentativi, scadenze e criteri di pulizia espliciti. Presupporre che la manutenzione o un errore del nodo possano sostituire il pod e verificare che il sostituto ripristini correttamente il relativo checkpoint. Monitorare lo stato del Job, gli eventi del pod, i log, l'età dei checkpoint, la velocità effettiva e il comportamento dei nuovi tentativi. I Job riavviabili ordinari non richiedono gang scheduling o un PDB. Usare questi controlli solo quando i lavoratori paralleli devono avviarsi insieme o mantenere un livello minimo di simultaneità testato.
Contenuti correlati
Scopri le procedure consigliate per altre aree della distribuzione e delle operazioni dell'applicazione in AKS:
- Confronto tra funzionalità automatiche del servizio Azure Kubernetes e Standard del servizio Azure Kubernetes
- Procedure consigliate per la resilienza e l'affidabilità delle applicazioni
- Procedure consigliate per la gestione delle risorse
- Procedure consigliate per la sicurezza dei pod
- Applicare le procedure consigliate con le misure di sicurezza della distribuzione