Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Se aplica a: ✔️ AKS Automatic ✔️ AKS Standard
MLOps es un conjunto de procedimientos para implementar, supervisar y administrar modelos de aprendizaje automático en entornos de producción.
Mejores prácticas clave de MLOps tratadas en este artículo:
- Infraestructura como código (IaC)
- Contenerización
- Administración de modelos y control de versiones
- Automatización
- Administración de escalabilidad y recursos
- Fiabilidad de los procesos por lotes de larga duración
- Seguridad y cumplimiento
En este artículo, se describen los procedimientos recomendados y las consideraciones que deben tenerse en cuenta al usar MLOps en AKS. Para obtener más información sobre MLOps, consulte Operaciones de aprendizaje automático (MLOps) para flujos de trabajo de inteligencia artificial y aprendizaje automático.
Elige tu modo de AKS para MLOps
AKS admite dos modos de clúster: AKS Automatic y AKS Standard. Elija AKS Automatic cuando desee una configuración base lista para producción con menos gestión operativa de la plataforma. Elija AKS Standard cuando necesite un mayor control sobre la configuración de la plataforma y la infraestructura del clúster.
Las prácticas de MLOps de este artículo se aplican a ambos modos. Sin embargo, la responsabilidad de implementación difiere según el modo: AKS Automatic proporciona más valores predeterminados preconfigurados, mientras que AKS Standard normalmente requiere una configuración de plataforma más explícita y propiedad del ciclo de vida.
| Area | AKS Automatic | AKS Standard |
|---|---|---|
| Configuración del clúster de línea base | Grupos de nodos, redes y supervisión preconfigurados y listos para usar | Requiere la configuración manual de grupos de nodos, CNI y pila de observabilidad |
| Operaciones del grupo de nodos del sistema | Aprovisionamiento y escalado automático de nodos administrados por el servicio | El operador debe configurar el tamaño, las reglas de escalado y las ventanas de mantenimiento del grupo de nodos. |
| Controles de base de referencia de seguridad | Directivas de red, estándares de seguridad de los pods e identidad de carga de trabajo activados de forma predeterminada | Los operadores deben habilitar y configurar explícitamente las directivas de red, la seguridad del pod y la configuración de identidad |
| Base de referencia de red | Azure CNI Overlay preconfigurado con patrones de ingreso predeterminados | Flexibilidad total para elegir el complemento CNI, configurar controladores de entrada personalizados y definir la topología de red |
| Operaciones y actualizaciones | Actualizaciones automáticas de la imagen de nodo y de la versión de Kubernetes | Los operadores programan y gestionan el calendario de la actualización y la estrategia de despliegue |
| Enfoque de implementación de MLOps | Validar, controlar y ajustar los valores predeterminados | Diseño y configuración de controles de plataforma |
| Capacidad y programación de GPU | La capacidad de GPU apta se puede aprovisionar automáticamente a partir de solicitudes de recurso de carga de trabajo y restricciones de programación, sujeto a la disponibilidad de la SKU regional y la cuota de suscripción. | Los operadores crean y administran grupos de nodos de GPU, etiquetas, taints, límites de escalador automático, controladores y configuración del complemento de dispositivo |
| Entrenamiento distribuido | La planificación predeterminada de Kubernetes y el aprovisionamiento automático de nodos proporcionan un punto de partida; los operadores para entrenamiento, los planificadores de grupos y el ajuste de la topología siguen siendo decisiones a nivel de carga de trabajo | Los operadores instalan explícitamente operadores de entrenamiento y programadores y diseñan grupos de nodos de GPU, redes, escalado y selección de ubicación para trabajos distribuidos |
Infraestructura como código (IaC)
Conclusiones clave: defina y versione las plantillas de IaC para cada fase de la canalización de IA para garantizar la coherencia, la rentabilidad y las implementaciones más rápidas.
IaC permite el aprovisionamiento y la administración coherentes y reproducibles de la infraestructura para una variedad de tipos de aplicación. Con diferentes implementaciones de aplicaciones, la implementación de IaC puede cambiar a lo largo de la pipeline de IA, ya que la capacidad de proceso y los recursos necesarios para la inferencia, el servicio, el entrenamiento y el ajuste de modelos pueden variar. La definición y el control de versiones de las plantillas de IaC para los equipos de desarrolladores de IA pueden ayudar a garantizar la coherencia y la rentabilidad en los tipos de trabajo, a la vez que aclaran los requisitos de hardware y aceleran el proceso de implementación.
En AKS Automatic, IaC puede centrarse más en las definiciones de carga de trabajo, los mecanismos de control de políticas y la coherencia del entorno que en los valores predeterminados de la plataforma. En AKS Standard, IaC suele incluir opciones de plataforma de clúster más explícitas, como redes, escalado y opciones de configuración operativa.
Contenerización
Conclusiones clave: ponderaciones del modelo de paquetes, metadatos y configuraciones en imágenes de contenedor para permitir la portabilidad, el control de versiones simplificado y los costes de almacenamiento reducidos.
La administración de los pesos, los metadatos y las configuraciones de los modelos en imágenes de contenedor permite la portabilidad, la simplificación del control de versiones y la reducción de los costes de almacenamiento a lo largo del tiempo. Con la contenerización, puedes:
- Utilice imágenes de contenedor existentes, especialmente para modelos lingüísticos de gran tamaño (LLM) con entre millones y miles de millones de parámetros y modelos de difusión estable, almacenados en registros de contenedores seguros.
- Evite un único punto de error en la canalización mediante el uso de varios contenedores ligeros que contengan las dependencias únicas de cada tarea en lugar de mantener una imagen grande.
- Almacene grandes conjuntos de datos de texto e imagen fuera de la imagen de contenedor base y haga referencia a ellos cuando sea necesario en tiempo de ejecución. Empiece con el Operador de cadena de herramientas de IA de Kubernetes (KAITO) para implementar un LLM en AKS.
Los controles de la cadena de suministro de contenedores siguen siendo esenciales en ambos modos. Incluso con la configuración predeterminada preconfigurada de la plataforma en AKS Automatic, la procedencia de las imágenes, el análisis y el refuerzo del entorno de ejecución siguen siendo responsabilidades fundamentales de MLOps.
Patrón dockerfile para cargas de trabajo de ML:
Use una etiqueta de imagen base explícita habilitada para CUDA para cargas de trabajo de entrenamiento de GPU (por ejemplo, pytorch/pytorch:2.4.1-cuda12.4-cudnn9-runtime) en lugar de una referencia de imagen base no etiquetada. Fije la imagen por hash en producción para garantizar compilaciones reproducibles y un comportamiento predecible de CUDA/cuDNN. Mantenga variantes de imagen de CPU y GPU independientes para que la asignación del planificador y las dependencias de tiempo de ejecución sigan siendo explícitas.
Administración de modelos y control de versiones
Conclusiones clave: gestione las versiones de sus modelos de forma sistemática para mantener la consistencia en todos los ambientes y permitir iterar más rápido con métodos de ajuste fino eficientes en cuanto a parámetros.
La administración de modelos y el control de versiones son esenciales para realizar un seguimiento de los cambios en los modelos a lo largo del tiempo. Al versionar sus modelos, puede:
- Mantener la coherencia entre los contenedores de modelos para facilitar la implementación en distintos entornos.
- Usar métodos de ajuste eficaz de parámetros (PEFT) para iterar más rápido en un subconjunto de pesos de modelo y mantener las nuevas versiones en contenedores ligeros.
En AKS Automatic, las líneas base de la plataforma preconfiguradas pueden simplificar la paridad del entorno. En AKS Standard, los equipos suelen necesitar aplicar la paridad de forma más explícita a través de la configuración de la plataforma y la implementación.
Automatización
Conclusiones clave: automatice la ingesta de datos, la supervisión del rendimiento del modelo y las canalizaciones de reentrenamiento para reducir los errores manuales y garantizar la coherencia en todo el ciclo de vida del aprendizaje automático.
La automatización ayuda a reducir los errores manuales, aumentar la eficacia y garantizar la coherencia en el ciclo de vida de ML. Al automatizar las tareas, puede:
- Integre las herramientas de alertas para desencadenar un flujo de ingesta de vectores a medida que fluyen nuevos datos en la aplicación.
- Establecer umbrales de rendimiento del modelo para realizar un seguimiento de las degradaciones y desencadenar canalizaciones de reentrenamiento.
En ambos modos de AKS, incluya la automatización para la validación de directivas, la detección de desfases de configuración y la gobernanza de versiones, además de los desencadenadores de calidad del modelo.
Administración de escalabilidad y recursos
Conclusiones clave: optimice el uso de recursos a través de la informática distribuida, el escalado automático y la planeación de la recuperación ante desastres para controlar las distintas demandas de canalización de IA de forma rentable.
La escalabilidad y la gestión de recursos son fundamentales para garantizar que su pipeline de IA pueda satisfacer las exigencias de su aplicación. Mediante la optimización del uso de los recursos, puede:
- Integre herramientas que usen eficazmente los recursos de CPU, GPU y memoria asignados a través de la computación distribuida y varios niveles de paralelismo, como los datos, el modelo y el paralelismo de canalización.
- Habilite el escalado automático en sus recursos de computación para admitir grandes volúmenes de solicitudes al modelo en horas punta y reducir la capacidad en horas de poca actividad.
- Planee la recuperación ante desastres siguiendo los procedimientos recomendados de resistencia y confiabilidad de AKS.
AKS Automatic puede reducir la sobrecarga de configuración para patrones comunes de escalado y operaciones, mientras que AKS Standard proporciona un control más profundo para las arquitecturas de escalado personalizadas.
Ejecutar trabajos por lotes de larga duración
Conclusión clave: Ejecute el trabajo finito como un JobKubernetes, conserve el progreso fuera del pod, administre las señales de terminación y asuma que el trabajo podría iniciarse más de una vez.
Las actualizaciones de nodos, los reinicios, los eventos de reducción de escala, la presión sobre los recursos, la preempción y los fallos de infraestructura pueden interrumpir los trabajos por lotes de larga duración. Un Kubernetes Job reemplaza un pod que ha fallado o se ha eliminado, pero el sustituto se inicia en otro nodo sin los archivos locales ni la memoria de proceso del pod anterior. Diseña la aplicación para que se reanude a partir de un estado duradero y repita el trabajo de forma segura.
Utilice estas prácticas para tareas por lotes normales que consumen mucha CPU, memoria o E/S. La guía sobre planificación por grupos y cola de cargas de trabajo se aplica cuando una carga de trabajo distribuida requiere que varios trabajadores se inicien juntos o cuando los equipos necesitan cuotas compartidas. Un trabajo por lotes con un único trabajador o en paralelo de forma independiente normalmente no necesita programación en grupo.
Configura puntos de control, reintentos y finalización
En el ejemplo siguiente se procesa una secuencia de elementos de trabajo y se registra el siguiente elemento en un volumen persistente Azure Files. Restaura el punto de control tras la sustitución de un pod y guarda el progreso cuando el proceso recibe 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
Reemplace el bucle de ejemplo por la aplicación por lotes y seleccione almacenamiento que cumpla sus requisitos de rendimiento y recuperación. Use la identidad de carga de trabajo en lugar de las credenciales incrustadas cuando los puntos de control de la aplicación se realicen directamente en Azure Blob Storage u otro servicio de Azure.
Aplique estos controles de confiabilidad deliberadamente:
-
Puntos de control e idempotencia: Guarda el progreso a un intervalo que se ajuste a tu objetivo de punto de recuperación. Almacene los puntos de control y la salida confirmada en el almacenamiento persistente, no en el sistema de archivos de contenedor,
emptyDiro en el almacenamiento local del nodo. Utiliza escrituras atómicas, claves de idempotencia, salida transaccional o deduplicación, ya que el mismo programa de trabajo puede iniciarse en ocasiones más de una vez. -
Comportamiento de reinicio: una tarea admite
restartPolicy: NeveroOnFailure. ConNever, un contenedor que falla genera un pod fallido y el controlador de trabajos crea uno de sustitución. ConOnFailure, el kubelet puede reiniciar el contenedor en el mismo pod. UtilizaNevercuando los pods y registros fallidos independientes faciliten el diagnóstico y garanticen que cualquiera de las dos rutas sea segura para reanudar. -
Límites de reintento: se establece
backoffLimiten función del número de errores transitorios que la carga de trabajo puede tolerar. UtilizapodFailurePolicypara que se produzca un fallo inmediato ante códigos de salida conocidos que no admiten reintentos o, como en el ejemplo, para evitar que las interrupciones voluntarias agoten el presupuesto de reintentos. Una interrupción puede seguir deteniendo el pod; la directiva solo cambia la forma en que el Job contabiliza ese fallo. -
Fechas límite: establezca
activeDeadlineSecondscuándo el trabajo debe detenerse después de un tiempo de ejecución total máximo. El plazo incluye los reintentos y tiene prioridad sobrebackoffLimit. No establezca una fecha límite más corta que el tiempo de ejecución esperado más el tiempo de reintento y recuperación. Un trabajo con error no se reinicia automáticamente como un nuevo trabajo. -
Terminación correcta: controle
SIGTERMen la aplicación y establezcaterminationGracePeriodSecondsel tiempo suficiente para dejar de aceptar el nuevo trabajo, finalizar o abandonar la unidad actual de forma segura, vaciar la salida y guardar un punto de control. Kubernetes envíaSIGKILLsi el proceso supera el período de gracia, por lo que los puntos de control periódicos siguen siendo necesarios. -
Limpieza: Establece
ttlSecondsAfterFinishedo configura los límites del historial de CronJob para evitar que se acumulen trabajos y pods completados. Conserve los registros de trabajo lo suficiente para la recopilación de registros y la investigación de incidentes.
Planear las expulsiones y el mantenimiento de nodos
No considere el bloqueo del desalojo como la estrategia principal de recuperación para una tarea de larga duración. Para un trabajo por lotes reiniciable, normalmente no se debe crear un PodDisruptionBudget (PDB); el controlador de trabajos crea un pod de sustitución tras una interrupción voluntaria. Una PDB solo protege contra los desalojos voluntarios y no protege contra fallos de nodo, desalojos por presión de recursos ni desalojos preventivos. Una PDB que permite cero interrupciones también puede bloquear las purgas de nodos y retrasar las actualizaciones de AKS.
Utiliza un PDB solo cuando una carga de trabajo por lotes en paralelo deba conservar un número mínimo de trabajadores ejecutándose simultáneamente y hayas probado su comportamiento de drenaje. Del mismo modo, use cluster-autoscaler.kubernetes.io/safe-to-evict: "false" solo para trabajos excepcionales que no se puedan reiniciar. La anotación puede evitar la reducción de escala y aumentar el coste, pero no protege contra fallos de nodo ni contra todos los eventos de mantenimiento.
Las actualizaciones de AKS aíslan y vacían los nodos antiguos antes de sustituirlos. Configura las ventanas de mantenimiento planificadas para ajustar el mantenimiento de AKS compatible con los periodos de menor impacto, pero mantén la posibilidad de reiniciar la carga de trabajo, ya que la programación del mantenimiento no elimina las interrupciones imprevistas. Para AKS Standard, ejecute trabajos por lotes en un grupo de nodos de usuario dedicado cuando necesite tamaños de máquina virtual independientes, límites de escalado, taints o intervalos de actualización. Evita los grupos de nodos Spot para tareas que no puedan recuperarse de la preemptión. Antes del mantenimiento de los nodos, comprueba que los puntos de control recientes sean utilizables y que otro grupo de nodos apto disponga de suficiente cuota y capacidad para ejecutar los pods de sustitución.
Supervisión del progreso y recuperación del trabajo
Use el estado, los eventos y los registros de Kubernetes juntos al investigar un trabajo de ejecución prolongada:
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
Habilite el servicio administrado de Azure Monitor para Prometheus y Container Insights para conservar los registros y correlacionar el estado de la tarea con los reinicios del pod, las expulsiones, el tiempo en espera, el estado del nodo y el uso de recursos. Instrumente la aplicación con señales de progreso empresarial, como los elementos completados, los elementos con errores, la hora del último punto de control correcto, la velocidad de procesamiento, el recuento de reintentos y el tiempo de finalización estimado. Genera alertas ante un trabajo fallido, un trabajo que supere su duración prevista, la ausencia de puntos de control dentro del objetivo de punto de recuperación, sustituciones repetidas de pods, pods pendientes de forma prolongada y un rendimiento de procesamiento estancado.
Seguridad y cumplimiento
Conclusiones clave: implemente el examen de CVE, los seguimientos de auditoría y los controles de cumplimiento para proteger los datos y cumplir los requisitos normativos, como SOC 2, HIPAA y RGPD.
La seguridad y el cumplimiento son críticos para proteger los datos y garantizar que la canalización de IA cumpla los requisitos normativos. Con la implementación de procedimientos recomendados de seguridad y cumplimiento, puede:
- Integre el examen de vulnerabilidades comunes y exposiciones (CVE) para detectar vulnerabilidades comunes en imágenes de contenedor de modelos de código abierto.
- Use Microsoft Defender para contenedores para las imágenes de contenedor de modelos almacenadas en Azure Container Registry.
- Mantener una pista de auditoría de los datos ingeridos, los cambios del modelo y las métricas para mantener el cumplimiento de las directivas de la organización.
- Compatibilidad con marcos de cumplimiento como SOC 2 (mediante el registro de auditoría y los controles de acceso de Azure), HIPAA (mediante cifrado en reposo y en tránsito, aislamiento de red) y RGPD (a través de opciones de residencia de datos y directivas de administración de acceso).
En AKS Automatic, los valores predeterminados de seguridad preconfigurados mejoran la posición de línea de base, pero los controles de seguridad de nivel de modelo, de nivel de datos y de canalización siguen siendo necesarios.
Programación de cargas de trabajo de GPU
Conclusiones clave: exponga las GPU mediante el complemento de dispositivos de NVIDIA, solicite las GPU explícitamente y aísle los nodos con GPU costosas con etiquetas, marcas y tolerancias.
Kubernetes planifica las GPUs como recursos extendidos. Una vez que el complemento de dispositivos de NVIDIA registra las GPU en un nodo, un pod solicita una GPU estableciendo nvidia.com/gpu tanto en resources.requests como en resources.limits. El siguiente pod solicita una GPU y tiene como destino un grupo de nodos con accelerator=nvidiala etiqueta :
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
Los recursos extendidos no están sobreasignados. Kubernetes trata un límite de GPU como una solicitud de GPU cuando solo se especifica el límite, pero al establecer ambos campos, la intención de carga de trabajo es explícita y ayuda a la validación de directivas.
Aprovisionamiento de un grupo de nodos de GPU de AKS
Para AKS Standard, cree un grupo de nodos de usuario dedicado con un tamaño de máquina virtual de GPU nvidia compatible. En el siguiente ejemplo de CLI de Azure, se crea un grupo de nodos con escalado automático Standard_NC4as_T4_v3, se aplica la etiqueta utilizada por el pod precedente y se aplican restricciones a los nodos para repeler las cargas de trabajo que no toleren explícitamente los nodos con 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
Antes de crear el grupo de nodos, compruebe que la SKU de máquina virtual está disponible en la región del clúster y que la suscripción tenga suficiente cuota regional y de familia de máquinas virtuales. Seleccione un tamaño de la serie NC en función de la memoria de GPU, el recuento de GPU, la relación de CPU a GPU, el almacenamiento local, las redes y las funcionalidades de CUDA necesarias para el marco de entrenamiento. Por ejemplo, los tamaños NCas T4 v3 son adecuados para muchas cargas de trabajo de entrenamiento con una sola GPU y de menor tamaño, mientras que los tamaños NC A100 v4 son compatibles con modelos más grandes y configuraciones de GPU multiinstancia.
AKS Automatic puede aprovisionar capacidad de GPU admisible en respuesta a pods en espera. La carga de trabajo debe seguir solicitando nvidia.com/gpu, y los selectores de nodos, las afinidades, las tolerancias, las restricciones de topología, las cuotas de suscripción y la disponibilidad regional de SKU deben poder cumplirse. Use AKS Standard cuando necesite una SKU de máquina virtual fija, un ciclo de vida del grupo de nodos personalizado o un control detallado sobre el escalado y la topología del grupo de GPU.
Comprobación o instalación del complemento de dispositivo NVIDIA
Las configuraciones de GPU de AKS pueden proporcionar controladores de GPU administrados e integración del complemento de dispositivo. Compruebe la configuración efectiva antes de instalar otro complemento:
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"
No ejecute varios daemonSets del complemento de dispositivo NVIDIA en los mismos nodos. Si la configuración de AKS no gestiona el complemento, el siguiente DaemonSet independiente registra las GPU de NVIDIA con el kubelet. Instale una versión del complemento de dispositivo compatible con el controlador nvidia y las versiones de 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
Confirme que nvidia.com/gpu aparece entre los recursos asignables de cada nodo de GPU antes de enviar trabajos de entrenamiento.
Partición de GPU A100 y H100 con MIG
NVIDIA Multi-Instance GPU (MIG) puede crear particiones de una GPU A100 o H100 compatible en instancias de GPU aisladas. MIG es útil para el ajuste de hiperparámetros y trabajos de ajuste fino más pequeños que no requieren una GPU física completa. Use GPU completas para cargas de trabajo que requieran toda la memoria de GPU, el ancho de banda máximo de interconexión o un perfil que no sea compatible con la GPU instalada.
Use el operador de GPU de NVIDIA y el administrador de MIG cuando necesite la gestión declarativa del ciclo de vida de MIG. El operador debe poseer el complemento de dispositivo y la configuración de MIG para los nodos afectados; no lo combine con un segundo complemento de dispositivo independiente. Los nombres de perfil exactos y el número de instancias dependen del modelo de GPU y la capacidad de memoria. La siguiente configuración crea siete 1g.10gb instancias en configuraciones A100 o H100 de 80 GB compatibles:
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
Configure el gestor de MIG del operador de GPU para consumir la ConfigMap mig-parted-config, use la estrategia de MIG mixed cuando las cargas de trabajo soliciten perfiles MIG con nombre específico y, a continuación, etiquete los nodos de destino:
kubectl label nodes \
-l accelerator=nvidia \
nvidia.com/mig.config=hptuning-1g10gb \
--overwrite
El cambio de un diseño de MIG interrumpe las cargas de trabajo que ya usan la GPU. Acordonar y vaciar el nodo de destino, aplicar la configuración durante una ventana de mantenimiento y confirmar que el perfil solicitado existe en los recursos asignables del nodo antes de enviar trabajos.
Aísle las cargas de trabajo de GPU con marcas y tolerancias
Una marca NoSchedule evita que los pods de aplicación normales se alejen de los nodos de GPU costosos. El ejemplo de creación del grupo de nodos usa sku=gpu:NoSchedule. El siguiente Job completo incluye la tolerancia correspondiente y un selector de nodo:
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 tolerancia permite la planificación, pero no obliga a que el pod se ejecute en un nodo con GPU. Combina las tolerancias con una solicitud de recursos de GPU y un selector de nodos o afinidad de nodo. Asegúrese de que los DaemonSets de plataforma necesarios, como conexión en red, supervisión, almacenamiento y el plugin de dispositivos, toleren la marca de la GPU.
Ejecución de cargas de trabajo de entrenamiento distribuidas
Idea clave: utilice un operador de entrenamiento para gestionar las identidades de los trabajadores y el ciclo de vida de los trabajos, valide la comunicación de red entre varios nodos y use la admisión en grupo cuando todos los trabajadores deban iniciarse a la vez.
El entrenamiento distribuido usa varios procesos para dividir los datos, el estado del modelo o las fases de canalización. En Kubernetes, un operador puede crear pods de trabajo, insertar configuración de coordinación, realizar un seguimiento del estado de la réplica, reiniciar trabajos con errores y limpiar el trabajo. Instale y gestione las versiones de los operadores de entrenamiento mediante la IaC y el proceso de lanzamiento de su plataforma, en lugar de permitir que equipos individuales instalen CRD de ámbito de clúster sin gobernanza.
Crear una imagen de entrenamiento de CUDA portátil
El siguiente Dockerfile desarrolla el patrón de Dockerfile identificado en la sección de contenedorización. La imagen contiene el entorno de ejecución de CUDA y las bibliotecas de PyTorch, mientras que el controlador NVIDIA compatible permanece en el nodo de GPU de 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"]
Ancle la imagen base mediante un hash inmutable en producción. Mantenga los conjuntos de datos y cambie con frecuencia los puntos de control fuera de la imagen y examine la imagen resultante antes de insertarla en Azure Container Registry.
Ejecutar un PyTorchJob
El operador de entrenamiento de Kubeflow proporciona el PyTorchJob CRD. Instale una versión del operador de entrenamiento compatible con la versión de Kubernetes antes de aplicar este manifiesto. El siguiente ejemplo de dos réplicas realiza una operación all-reduce de NCCL entre un maestro y un trabajador:
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
Para el entrenamiento en producción, reemplace la prueba integrada por su imagen de entrenamiento y su script versionados. Ajuste el número de réplicas al número de GPU y procesos que requiere el framework de entrenamiento.
Ejecutar un TFJob
El operador de entrenamiento también proporciona el TFJob CRD. El ejemplo siguiente ejecuta el entrenamiento sincrónico de TensorFlow en dos procesos de trabajo de GPU usando 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
Para el entrenamiento con servidor de parámetros, defina los tipos de réplica Chief, Worker y PS según la estrategia de distribución de TensorFlow. Mida los cuellos de botella resultantes de la red y del servidor de parámetros antes de aumentar el número de réplicas.
Ajustar un modelo con KAITO
KAITO proporciona una abstracción del área de trabajo centrada en AKS para la implementación de modelo y el ajuste fino. Habilite el complemento KAITO o instale una versión de KAITO compatible antes de aplicar un Workspace. Compruebe que el valor preestablecido seleccionado, la SKU de máquina virtual y el método de ajuste preciso son compatibles con la versión de KAITO instalada.
El área de trabajo siguiente solicita una máquina virtual de GPU A100 e inicia el ajuste de QLoRA para un valor preestablecido de Phi-3 compatible mediante un conjunto de datos accesible públicamente:
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 puede coordinar la configuración preestablecida del modelo y la infraestructura de GPU necesaria para el área de trabajo. En el caso de producción, almacene el conjunto de datos de entrenamiento en una cuenta de almacenamiento de Azure aprobada, use el acceso privado y la identidad de carga de trabajo donde se admita y conserve el modelo resultante en un registro de modelos regulado o Azure Container Registry. Trate el manifiesto del área de trabajo, la versión del conjunto de datos de entrada, la versión preestablecida, la configuración del adaptador y el resumen de la imagen de salida como un registro de entrenamiento con versiones.
Configuración de la comunicación NCCL con AKS CNI
NVIDIA Collective Communications Library (NCCL) controla operaciones colectivas como all-reduce. Para una configuración de referencia de TCP portátil en AKS CNI, use la interfaz de red del pod, normalmente eth0, y empiece por NCCL_IB_DISABLE=1. En los tamaños de máquina virtual compatibles con RDMA, use la configuración de RDMA documentada de NVIDIA y Azure, y valídela antes de configurar NCCL_IB_DISABLE=0.
Use estas variables de entorno de línea base:
-
NCCL_SOCKET_IFNAME=eth0selecciona la interfaz de red del pod. -
NCCL_DEBUG=INFOproporciona diagnósticos durante la validación. Reduzca el nivel de registro después del ajuste. -
NCCL_IB_DISABLE=1selecciona sockets TCP cuando RDMA no está configurado. -
TORCH_NCCL_ASYNC_ERROR_HANDLING=1ayuda a PyTorch a finalizar en lugar de quedarse colgado indefinidamente después de errores de comunicación asincrónica.
Si la directiva de red está habilitada, permita todo el tráfico de coordinación y de NCCL necesario entre las réplicas. NCCL puede negociar puertos dinámicos, por lo que una directiva restrictiva de puertos fijos puede hacer que las tareas de entrenamiento queden bloqueadas. La directiva siguiente permite la comunicación de pod a pod sin restricciones solo entre las réplicas del trabajo de PyTorch y permite la resolución 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
Evalúe el rendimiento de NCCL de forma independiente al entrenamiento del modelo antes de escalar horizontalmente. Compare el ancho de banda de all-reduce, la latencia, la utilización de la GPU y el rendimiento del entrenamiento para cada número de trabajadores. Más trabajadores pueden reducir el rendimiento cuando la comunicación o la carga de datos se convierte en un cuello de botella.
Usar la planificación por grupos y colas de carga de trabajo
Conclusiones clave: admita los trabajadores distribuidos como grupo y aplique cuotas de GPU por inquilino para que los trabajos programados parcialmente no reserven las GPU mientras esperan a los trabajadores restantes.
El planificador predeterminado de Kubernetes coloca los pods de forma individual. En un trabajo distribuido que no puede avanzar hasta que todos los trabajadores estén en ejecución, la colocación parcial puede desperdiciar la capacidad de las GPU. Kueue proporciona control de admisión y administración de cuotas antes de que los pods empiecen a ejecutarse. Volcano proporciona un planificador y un modelo de planificación de todo o nada basado en PodGroup.
AKS Automatic proporciona el programador de Kubernetes predeterminado y el aprovisionamiento automático de nodos como punto de partida. Envíe trabajos normales o trabajos de entrenamiento administrados por el operador con solicitudes de recursos precisas y permita que la plataforma aprovisione capacidad apta. Este comportamiento no garantiza la admisión atómica para cada trabajador. Instale Kueue o Volcano cuando una carga de trabajo requiera planificación por grupos, colas, cuotas de equipo, uso compartido equitativo o comportamiento de desalojo personalizado.
Asigne una cuota de GPU multiusuario con Kueue
Instale una versión de Kueue compatible con la versión de Kubernetes y habilite las integraciones para los tipos de carga de trabajo que use. El siguiente manifiesto crea:
- Una GPU
ResourceFlavorasociada a nodos etiquetados conaccelerator=nvidia. - Un
ClusterQueuede cuatro GPU para el equipo A. - Un sistema de dos GPU
ClusterQueuepara el equipo B. - Un
LocalQueuecon ámbito de espacio de nombres para cada equipo. - Un trabajo de dos trabajadores que Kueue admite solo cuando sus recursos solicitados están disponibles.
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 cuota es una cuota de programación, no una cuota de suscripción Azure. Asegúrese de que el clúster de AKS puede aprovisionar la capacidad de máquina virtual subyacente y que Azure cuota de GPU es suficiente para la carga de trabajo agregada admitida. Use cohortes y las funciones de reparto equitativo de Kueue cuando los equipos puedan prestarse entre sí la cuota no utilizada.
Usar Volcano como alternativa
Volcano es una alternativa cuando se desea un programador de lotes dedicado con directivas de programación de grupos, colas y ciclo de vida del trabajo. Instale una versión de Volcano compatible con el clúster antes de aplicar sus CRD. El siguiente trabajo de Volcano requiere que ambos trabajadores de GPU estén disponibles antes de que el trabajo se ejecute:
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
Estandarice un único sistema principal de colas y de planificación por grupos, a menos que disponga de un diseño de interoperabilidad probado. De lo contrario, varios controladores de admisión o planificadores pueden hacer que el comportamiento de los estados pendientes y de expulsión resulte difícil de comprender.
Configuración de prioridades de entrenamiento e inferencia
La inferencia sensible a la latencia normalmente requiere una prioridad más alta que el entrenamiento por lotes interrumpible. Los siguientes recursos PriorityClass permiten que los pods de inferencia desalojen a los pods de menor prioridad, al tiempo que evitan que los pods de entrenamiento por lotes desalojen otras cargas de trabajo:
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.
Asigne la clase mediante spec.priorityClassName en la plantilla del pod. La prioridad del pod de Kubernetes y la prioridad de la carga de trabajo de Kueue afectan a diferentes fases: Kueue controla la admisión de colas, mientras que la prioridad de Kubernetes influye en la programación y el desalojo del pod después de la admisión. Coordinar ambas directivas para expresar la misma prioridad empresarial.
El desalojo finaliza los pods de prioridad inferior. Las cargas de trabajo de entrenamiento que se pueden desalojar deben escribir puntos de control en el almacenamiento persistente, tolerar el trabajo duplicado y recuperarse sin depender de archivos locales de nodo.
Configuración de la administración de recursos y memoria compartida
Conclusiones clave: reemplace el pequeño valor predeterminado /dev/shmdel entorno de ejecución del contenedor, establezca las solicitudes de recursos del uso observado y configure el escalado de nodos en torno a los requisitos completos de la carga de trabajo de GPU.
Aumento /dev/shm de los cargadores de datos de ML
Los cargadores de datos de PyTorch, las canalizaciones de entrada de TensorFlow, NCCL y el multiprocesamiento de Python pueden usar memoria compartida de POSIX. El valor predeterminado del contenedor para /dev/shm suele ser demasiado pequeño para el entrenamiento de varios procesos, lo que puede provocar bloqueos de trabajo, errores de bus o bloqueos de entrenamiento aparentes.
Monte un emptyDir basado en memoria en /dev/shm y establezca un sizeLimit explícito:
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
El uso de emptyDir respaldado por memoria cuenta como parte del consumo de memoria del pod. Incluya el uso máximo esperado de memoria compartida al establecer el límite de memoria del contenedor. Si /dev/shm crece más allá del presupuesto de memoria efectivo, el pod puede ser expulsado o finalizado por superar su límite de memoria.
Dimensionar la CPU y la memoria a partir de la utilización observada
Comience con una prueba comparativa basada en el modelo representativo, el tamaño del lote, la longitud de la secuencia, la simultaneidad del cargador de datos, el aumento y el comportamiento del punto de control. A continuación, use los datos de supervisión para ajustar:
- Establezca las solicitudes de CPU lo suficientemente altas como para mantener las canalizaciones de entrada de GPU proporcionadas. Los períodos de inactividad persistentes de la GPU pueden indicar falta de recursos de la CPU o del almacenamiento.
- Establezca solicitudes de memoria cerca del uso estable del conjunto de trabajo más un margen de seguridad. Incluya
/dev/shm, comportamiento de caché de páginas, sobrecarga del asignador del marco y picos de serialización de puntos de control. - Establezca los límites de memoria por encima del pico observado. Investigue
OOMKilledeventos en lugar de aumentar repetidamente los límites sin encontrar la causa. - Evalúe la reducción del rendimiento de la CPU antes de usar límites estrictos de CPU. Los límites de CPU que son demasiado bajos pueden reducir el uso de GPU incluso cuando el uso medio de la CPU parece aceptable.
- Establezca solicitudes y límites iguales para trabajos de entrenamiento predecibles y de alto valor cuando la calidad garantizada del servicio es más importante que el empaquetado de nodos.
- Registre el perfil de cada cambio significativo en el tamaño del modelo, la precisión, el tamaño del lote, el número de trabajadores y el flujo de datos.
Utilice percentiles en ciclos completos de entrenamiento en lugar de una media de un periodo corto. Las fases de inicio, validación, punto de control y barajado de datos suelen tener diferentes picos de uso de recursos.
Configuración del escalado automático de clústeres para un grupo de nodos de GPU
Para AKS Standard, habilite el escalador automático del clúster en el grupo de nodos de usuario de GPU y defina la capacidad mínima y máxima:
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
Puede ajustar las opciones de perfil admitidas del escalador automático de clúster a nivel de clúster. Pruebe los cambios de perfil en las cargas de trabajo de entrenamiento y servicio:
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 de GPU pendiente solo activa el escalado si todos sus requisitos de planificación coinciden con la plantilla de un grupo de nodos. Compruebe la solicitud de recursos de GPU, la capacidad de máquina virtual, las etiquetas, los taints, las tolerancias, la afinidad, las restricciones de topología, la topología de volumen persistente, el número máximo de nodos y la cuota de Azure cuando no se produzca el escalado vertical.
El escalado a cero es adecuado para los grupos de entrenamiento interrumpibles, pero añade latencia por el aprovisionamiento de máquinas virtuales, la descarga de imágenes, el montaje del conjunto de datos y la inicialización del modelo. Mantenga un mínimo distinto de cero cuando la latencia de inicio tenga un efecto material en los objetivos de servicio. Los presupuestos de interrupciones de pods, los pods no expulsables, el almacenamiento local y los periodos de gracia de terminación prolongados pueden retrasar la reducción de escala.
AKS Automatic administra el aprovisionamiento y el escalado de nodos como parte de la línea de base del servicio. Céntrese en solicitudes de pod precisas y restricciones admitidas en lugar de configurar un escalador automático manual de grupos de nodos de GPU.
Almacenar conjuntos de datos y puntos de control
Conclusiones clave: seleccione almacenamiento en función del patrón de acceso, el rendimiento, el uso compartido y los requisitos de recuperación, y conserve los puntos de control fuera del nodo para que el entrenamiento pueda recuperarse de la expulsión o el adelantamiento.
No incluya grandes conjuntos de datos, artefactos del modelo ni puntos de control en las imágenes de contenedor. Elija una interfaz de almacenamiento basada en la carga de trabajo:
- Use Azure Blob Storage para conjuntos de datos de objetos grandes, artefactos de modelo y repositorios de datos de alta capacidad.
- Use Azure Files cuando varios nodos de trabajo requieran un sistema de archivos de estilo POSIX compartido.
- Use Azure Disk para cargas de trabajo de puntos de control o de caché de alto rendimiento con lectura y escritura en un solo nodo, donde
ReadWriteOnceresulte suficiente. - Use el almacenamiento efímero local de nodo solo para las memorias caché reconstruibles y los archivos temporales.
Acceso a grandes conjuntos de datos con el controlador CSI de Azure Blob
Habilite el controlador Azure Blob CSI en AKS Standard si aún no está habilitado:
RESOURCE_GROUP=myResourceGroup
AKS_CLUSTER=myAKSCluster
az aks update \
--resource-group "$RESOURCE_GROUP" \
--name "$AKS_CLUSTER" \
--enable-blob-driver
En el ejemplo siguiente, se crea dinámicamente un contenedor de blobs premium de Azure expuesto a través de NFS y se monta en un pod de entrenamiento. Para un conjunto de datos regulado existente, use un volumen definido estáticamente o una configuración de BlobFuse con los controles de identidad y redes privadas adecuados en lugar de crear un contenedor dinámico vacío:
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
Realice pruebas comparativas de las opciones de protocolo y montaje con los tamaños de partición representativos y los patrones de acceso. Muchos trabajadores que leen muchos archivos pequeños pueden producir resultados diferentes a partir de particiones grandes de streaming secuencial. Considere la posibilidad de preprocesar conjuntos de datos en particiones de tamaño adecuado y usar el espacio de caché local del nodo cuando las épocas repetidas descargarían de otro modo los mismos objetos.
Uso compartido de datos de entrenamiento con Azure Files
Azure Files admite ReadWriteMany, que permite a los trabajos distribuidos en distintos nodos montar el mismo recurso compartido. Premium Azure Files es adecuado cuando la carga de trabajo requiere un rendimiento predecible del sistema de archivos y la región seleccionada admite la opción de redundancia necesaria.
El siguiente manifiesto crea un recurso compartido prémium de Azure Files y lo monta en dos pods de trabajo en paralelo:
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
Evite que cada trabajador enumere repetidamente un directorio que contenga millones de archivos. Use un manifiesto o una asignación de particiones determinista para que cada trabajador sepa qué objetos leer.
Punto de control en almacenamiento persistente
Un punto de control debe incluir suficiente información de estado para poder reanudar correctamente, como los pesos del modelo, el estado del optimizador, el estado del planificador, el estado del escalado, el número de época o de paso, el estado del generador de números aleatorios y la posición en el cargador de datos, cuando sea compatible. Escribir puntos de control periódicamente y antes de una terminación ordenada.
El siguiente Job escribe puntos de control atómicos de PyTorch en Azure Files, restaura el punto de control más reciente tras el reinicio de un contenedor o la sustitución del pod, y administra SIGTERM para que el desalojo pueda conservar el progreso reciente:
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
Use una política de reclamación Retain o una cuenta de almacenamiento administrada de forma independiente para los puntos de control de producción, para que eliminar un PVC no elimine por error el único punto de recuperación. Para el entrenamiento distribuido con paralelismo de datos, normalmente se hace que el rango cero escriba el punto de control global o se usa un formato de punto de control fragmentado compatible con el framework. Impedir que varias clasificaciones escriban simultáneamente el mismo archivo.
Pruebe la recuperación eliminando deliberadamente un pod de trabajador durante una ejecución en un entorno no productivo. Compruebe que el controlador recrea la carga de trabajo, que el nuevo pod monta el mismo volumen persistente y que el entrenamiento se reanuda desde el paso esperado.
Supervisión del uso de GPU y el rendimiento de entrenamiento
Conclusión clave: supervise el proceso de GPU, la memoria de GPU, el rendimiento de la canalización de datos, la duración de los pasos y la actividad de punto de control, de modo que pueda distinguir la saturación de proceso de los cuellos de botella de CPU, red o almacenamiento.
Habilite Azure Monitor servicio administrado para Prometheus y Container Insights para correlacionar el estado de Kubernetes, los registros de contenedor, el estado del nodo y las métricas de Prometheus. Use los procedimientos recomendados para la supervisión de AKS al diseñar alertas, la retención de datos y los paneles operativos.
Recopilación de métricas de GPU de NVIDIA
El exportador de GPU del Centro de datos de NVIDIA (DCGM) expone métricas de Prometheus para GPU NVIDIA. Si el operador de GPU nvidia ya implementa DCGM Exporter, no implemente un exportador duplicado. Configure Prometheus administrado de Azure Monitor para que recopile métricas del exportador existente.
A continuación, el PodMonitor siguiente usa el CRD de Prometheus administrado de Azure Monitor y tiene como destino los pods de DCGM Exporter en el espacio de nombres gpu-operator. Ajuste el selector de etiquetas para que coincida con las etiquetas usadas por el exportador instalado:
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
Compruebe el nombre del puerto del pod o del servicio exportador antes de aplicar el monitor. Entre las métricas comunes de DCGM se incluyen:
| Métrica | propósito |
|---|---|
DCGM_FI_DEV_GPU_UTIL |
Porcentaje de tiempo que la GPU está activa |
DCGM_FI_DEV_FB_USED |
Memoria de búfer de fotogramas usada |
DCGM_FI_DEV_FB_FREE |
Memoria libre de búfer de fotogramas |
DCGM_FI_DEV_MEM_COPY_UTIL |
Uso del motor de copia de memoria |
DCGM_FI_DEV_POWER_USAGE |
Consumo de energía de GPU |
DCGM_FI_DEV_GPU_TEMP |
Temperatura de GPU |
DCGM_FI_DEV_XID_ERRORS |
Eventos de error de NVIDIA XID |
La disponibilidad de métricas depende de las versiones de GPU, controlador, DCGM y exportador.
Exportación de métricas de rendimiento de entrenamiento
Instrumente la aplicación de entrenamiento con métricas de nivel de carga de trabajo. Entre las métricas útiles se incluyen:
-
ml_training_samples_totalpara muestras acumulativas o tokens procesados. -
ml_training_steps_totalpara los pasos del optimizador completados. -
ml_training_step_duration_secondspara la latencia por paso. -
ml_training_checkpoint_duration_secondspara la latencia del punto de comprobación. -
ml_training_data_wait_secondspara el tiempo de espera de los datos de entrada. - Pérdida específica del modelo, velocidad de aprendizaje, norma de degradado y métricas de validación.
En el siguiente ejemplo ejecutable se exponen métricas de entrenamiento sintéticas en el puerto 8000. Reemplace la simulación por las métricas emitidas por el bucle de entrenamiento real:
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
Para un trabajo distribuido real, incluya etiquetas estables, como el nombre del modelo, la versión del modelo, el nombre del trabajo, el identificador de ejecución, el rol de réplica y el equipo. No utilice etiquetas no acotadas, como ID de muestra, ID de solicitud o rutas a conjuntos de datos sin procesar, porque las etiquetas de alta cardinalidad aumentan el coste de supervisión y la latencia de las consultas.
Creación de paneles de GPU y rendimiento
Utilice consultas de PromQL como las siguientes como punto de partida y valide las etiquetas de las métricas con respecto a su exportador:
avg by (namespace, pod, gpu) (
avg_over_time(DCGM_FI_DEV_GPU_UTIL[5m])
)
La consulta siguiente calcula el uso de memoria del búfer de fotogramas como porcentaje:
100 *
DCGM_FI_DEV_FB_USED
/
(DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE)
La consulta siguiente calcula los ejemplos de entrenamiento procesados por segundo:
sum by (job_name) (
rate(ml_training_samples_total[5m])
)
La consulta siguiente muestra la duración media del paso:
avg by (job_name) (
ml_training_step_duration_seconds
)
Interprete estas señales juntas:
- El uso bajo de GPU y el tiempo de espera de datos elevado suelen indicar el almacenamiento, la red, el preprocesamiento o el colapso de la CPU.
- Un uso elevado de GPU con el rendimiento esperado indica que el acelerador se usa de forma eficaz.
- Un uso elevado de memoria de la GPU y los errores repetidos de falta de memoria indican que deben ajustarse el tamaño del lote, la longitud de la secuencia, la memoria de activación, el estado del optimizador o la fragmentación.
- La caída del rendimiento con un uso estable de GPU puede indicar secuencias más largas, sobrecarga de comunicación, comportamiento térmico o un cambio en el cálculo del modelo.
- La baja utilización de las GPU asignadas indica que hay capacidad ociosa que podría reducirse, gestionarse de otro modo en la cola o particionarse mediante MIG.
- La larga duración de un punto de control puede hacer que la interrupción preventiva resulte costosa y aumentar la cantidad de trabajo que debe repetirse tras la recuperación.
Cree alertas para la infrautilización sostenida de la GPU, la memoria de la GPU casi al límite de su capacidad, los errores XID, el rendimiento del entrenamiento estancado, los procesos de trabajo fallidos, las cargas de trabajo con planificación en grupo pendientes y los puntos de control que no se hayan completado dentro del objetivo de punto de recuperación esperado.
Preguntas más frecuentes (FAQ)
¿Cuál es la diferencia entre AKS Automatic y AKS Standard para MLOps?
AKS Automatic proporciona valores predeterminados preconfigurados para grupos de nodos, redes, seguridad y actualizaciones, lo que permite a los equipos de MLOps centrarse en las definiciones de carga de trabajo y la gobernanza. AKS Standard requiere la configuración manual de estos componentes de plataforma, pero ofrece un control más profundo para arquitecturas personalizadas y requisitos de escalado.
¿Cómo puedo versionar modelos de ML en AKS?
Versione sus modelos empaquetando los pesos, los metadatos y las configuraciones del modelo en imágenes de contenedores con etiquetas de versionado semántico. Almacene estas imágenes en Azure Container Registry y haga referencia a versiones específicas en los manifiestos de implementación de Kubernetes para garantizar la coherencia entre entornos.
¿Cómo se programan las cargas de trabajo de GPU en AKS?
Asegúrese de que el complemento de dispositivo NVIDIA esté disponible para que los nodos de GPU anuncien nvidia.com/gpu. En AKS Standard, aprovisione un grupo de nodos de usuario dedicado para GPU con un tamaño de máquina virtual admitido, como una SKU de la serie Standard_NC, y configure etiquetas de nodo, una restricción NoSchedule y los límites del escalador automático de clúster. En cada pod de entrenamiento, solicite nvidia.com/gpu, seleccione un nodo de GPU apto y agregue la tolerancia coincidente. AKS Automatic puede aprovisionar capacidad de GPU elegible a partir de las solicitudes de pod, en función de las SKU compatibles, la disponibilidad regional, las restricciones de planificación y la cuota de la suscripción de Azure.
¿Cómo puedo ejecutar trabajos de entrenamiento distribuido en AKS?
Instale el operador de entrenamiento de Kubeflow y envíe un PyTorchJob o TFJob para gestionar las réplicas distribuidas, la configuración de coordinación, el comportamiento de reinicio y el estado del trabajo. KAITO proporciona una abstracción de área de trabajo orientada a AKS para flujos de trabajo compatibles de ajuste fino de modelos y puede coordinar la infraestructura de GPU con configuraciones predefinidas de modelos. Para el entrenamiento multinodo de PyTorch, configure y evalúe el rendimiento de NCCL en la red de pods de AKS CNI, permita el tráfico entre nodos de trabajo a través de la directiva de red y use la configuración de RDMA admitida cuando la carga de trabajo y la SKU de máquina virtual seleccionada lo requieran.
¿Cómo se administra la cuota de GPU en varios equipos?
Instalar Kueue y definir recursos ClusterQueue con cuotas de CPU, memoria y nvidia.com/gpu, y luego asignar el espacio de nombres de cada equipo a la cuota que tenga asignada mediante un LocalQueue. Utilice cohortes de Kueue o reparto equitativo cuando los equipos puedan tomar prestada la capacidad no utilizada. Volcano es una alternativa cuando se requiere un programador por lotes con admisión de trabajo de todo o nada. Coordinar la prioridad de la cola con recursos de Kubernetes PriorityClass para que la inferencia sensible a la latencia pueda expulsar el entrenamiento interrumpible y garantizar que los trabajos de entrenamiento expulsables se recuperen de los puntos de control en el almacenamiento persistente.
¿Cuáles son las prácticas recomendadas para ejecutar trabajos por lotes de larga duración en AKS?
Use un kubernetes Job para el trabajo finito y un CronJob para el trabajo programado. Persiste los puntos de control y la salida confirmada fuera del pod, haz que el procesamiento sea idempotente, administra SIGTERM y establece solicitudes de recursos explícitas, límites de reintentos, plazos y directivas de limpieza. Asumir que el mantenimiento o el fallo de un nodo puede sustituir al pod, y comprobar que la sustitución restaura correctamente su punto de control. Supervisar el estado de los trabajos, los eventos de los pods, los registros, la antigüedad de los puntos de control, el rendimiento y el comportamiento de los reintentos. Los trabajos reiniciables ordinarios no requieren programación en grupo ni un PDB. Use esos controles solo cuando los trabajos paralelos deben iniciarse juntos o mantener una simultaneidad mínima probada.
Contenido relacionado
Obtenga información sobre los procedimientos recomendados en otras áreas de implementación de la aplicación y las operaciones en AKS:
- Comparación de características automáticas de AKS y AKS Estándar
- Procedimientos recomendados de resistencia y confiabilidad de aplicaciones
- Procedimientos recomendados de administración de recursos
- Prácticas recomendadas de seguridad para pods
- Aplicación de procedimientos recomendados con medidas de seguridad para implementación