Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Aplica-se a: ✔️ AKS Automatic ✔️ AKS Standard
MLOps é um conjunto de práticas para implementar, monitorizar e gerir modelos de aprendizagem automática em ambientes de produção.
Principais boas práticas MLOps abordadas neste artigo:
- Infraestrutura como código (IaC)
- Contentorização
- Gerenciamento e controle de versão de modelos
- Automatização
- Escalabilidade e gerenciamento de recursos
- Fiabilidade de processos em lote de longa duração
- Segurança e conformidade
Este artigo descreve as melhores práticas e considerações a ter em mente ao usar MLOps no AKS. Para obter mais informações sobre MLOps, consulte Operações de aprendizado de máquina (MLOps) para fluxos de trabalho de IA e aprendizado de máquina.
Escolha o seu modo AKS para MLOps
O AKS suporta dois modos de cluster: AKS Automático e AKS Standard. Escolha o AKS Automático quando quiser uma base pronta para produção com menos gestão de plataforma no segundo dia. Escolha o AKS Standard quando precisar de um controlo mais profundo sobre a infraestrutura do cluster e a configuração da plataforma.
As práticas de MLOps deste artigo aplicam-se a ambos os modos. No entanto, a responsabilidade pela implementação difere consoante o modo: o AKS Automatic fornece mais definições predefinidas, enquanto o AKS Standard normalmente exige uma configuração mais explícita da plataforma e uma maior responsabilidade pela gestão do ciclo de vida.
| Area | AKS Automático | Padrão AKS |
|---|---|---|
| Configuração base do cluster | Conjuntos de nós pré-configurados, redes e monitorização prontos a utilizar de imediato | Requer a configuração manual de pools de nós, CNI e pilha de observabilidade |
| Operações do conjunto de nós do sistema | Provisão automática e escalonamento de nós geridos pelo serviço | O operador deve configurar o tamanho do pool de nós, regras de escalabilidade e janelas de manutenção |
| Controlos de base de segurança | Políticas de rede, normas de segurança dos pods e identidade das cargas de trabalho ativadas por predefinição | Os operadores devem ativar e configurar explicitamente as políticas de rede, a segurança dos pods e as definições de identidade |
| Linha de base de rede | Azure CNI Overlay pré-configurado com padrões de entrada predefinidos | Flexibilidade total para escolher o plugin CNI, configurar controladores de entrada personalizados e definir topologia de rede |
| Operações e melhorias | Atualizações automáticas da imagem do nó e da versão do Kubernetes | Os operadores agendam e gerem o calendário das atualizações e a estratégia de implementação |
| Foco na implementação do MLOps | Validar, gerir e ajustar as predefinições | Projetar e configurar os controlos da plataforma |
| Capacidade da GPU e agendamento | A capacidade de GPU elegível pode ser aprovisionada automaticamente com base nos pedidos de recursos da carga de trabalho e nas restrições de agendamento, sujeita à disponibilidade regional das SKUs e à quota da subscrição | Os operadores criam e gerem pools de nós da GPU, etiquetas, contaminações, limites de autoescalamento, drivers e configuração de plugins de dispositivos |
| Formação distribuída | O agendamento predefinido do Kubernetes e o aprovisionamento automático de nós fornecem um ponto de partida; operadores de treino, agendadores de gangue e ajuste da topologia continuam a ser opções ao nível da carga de trabalho | Os operadores instalam explicitamente operadores de treino e agendadores e concebem conjuntos de nós com GPU, configuração de rede, escalabilidade e colocação para tarefas distribuídas |
Infraestrutura como código (IaC)
Conclusão: Defina e versione modelos de IaC para cada etapa do seu pipeline de IA, garantindo consistência, custo-benefício e implementações mais rápidas.
O IaC permite o provisionamento e gestão de infraestruturas consistentes e reprodutíveis para uma variedade de tipos de aplicações. Com diferentes implementações de aplicações, a sua implementação de IaC pode mudar ao longo do pipeline de IA, pois o poder de computação e os recursos necessários para inferir, servir, treinar e ajustar modelos podem variar. Definir e versionar modelos IaC para as suas equipas de programadores de IA pode ajudar a garantir consistência e custo-benefício entre os tipos de trabalho, ao mesmo tempo que clarifica os requisitos de hardware e acelera o processo de implementação.
No AKS Automatic, a IaC pode centrar-se mais na definição das cargas de trabalho, nas salvaguardas de política e na consistência do ambiente, em vez das predefinições da plataforma. No AKS Standard, o IaC inclui frequentemente definições mais explícitas da plataforma do cluster, como redes, escalabilidade e escolhas de configuração operacional.
Contentorização
Conclusão principal: Empacote os pesos do modelo, os metadados e as configurações em imagens de contentores para permitir portabilidade, controlo de versões simplificado e redução dos custos de armazenamento.
O gerenciamento de pesos, metadados e configurações do modelo em imagens de contêiner permite portabilidade, controle de versão simplificado e custos de armazenamento reduzidos ao longo do tempo. Com a conteinerização, você pode:
- Utilizar imagens de contentores existentes, especialmente para grandes modelos de linguagem (LLMs) com dimensões de milhões a milhares de milhões de parâmetros e modelos de difusão estáveis, armazenados em registos seguros de contentores.
- Evite um único ponto de falha no seu pipeline usando múltiplos contentores leves que contenham as dependências únicas de cada tarefa, em vez de manter uma imagem grande única.
- Armazene grandes conjuntos de dados de texto e imagens fora da sua imagem base do contentor e referencia-os quando necessário em tempo de execução. Comece com o Kubernetes AI Toolchain Operator (KAITO) para implementar um LLM no AKS.
Os controlos da cadeia de abastecimento dos contentores continuam essenciais em ambos os modos. Mesmo com as predefinições da plataforma no AKS Automatic, a proveniência da imagem, a análise e o reforço da segurança em tempo de execução continuam a ser responsabilidades centrais de MLOps.
Um padrão Dockerfile para cargas de trabalho de ML:
Use uma etiqueta de imagem base explícita com CUDA para cargas de trabalho de treino da GPU (por exemplo, pytorch/pytorch:2.4.1-cuda12.4-cudnn9-runtime) em vez de uma referência de imagem base sem etiqueta. Fixe a imagem pelo digest em produção para garantir compilações reprodutíveis e um comportamento previsível do CUDA/cuDNN. Mantenha variantes de imagem separadas para CPU e GPU para que a alocação pelo agendador e as dependências de tempo de execução permaneçam explícitas.
Gerenciamento e controle de versão de modelos
Conclusão principal: Adapte os seus modelos de forma sistemática para manter a consistência entre ambientes e permitir iterações mais rápidas com métodos de ajuste fino eficientes em parametros.
O gerenciamento de modelos e o controle de versão são essenciais para acompanhar as alterações em seus modelos ao longo do tempo. Ao versionar os seus modelos, pode:
- Mantenha a consistência em todos os contêineres de modelo para facilitar a implantação em diferentes ambientes.
- Utilizar métodos de ajustamento fino eficiente em parâmetros (PEFT) para iterar mais rapidamente num subconjunto de pesos do modelo e armazenar novas versões em contentores leves.
No AKS Automatic, as linhas de base pré-configuradas da plataforma podem simplificar a paridade do ambiente. No AKS Standard, as equipas muitas vezes precisam de impor a paridade de forma mais explícita através da configuração da plataforma e da implementação.
Automatização
Principal conclusão: Automatizar a ingestão de dados, monitorizar o desempenho dos modelos e retreinar pipelines para reduzir erros manuais e garantir a consistência ao longo do ciclo de vida do ML.
A automação ajuda a reduzir erros manuais, aumentar a eficiência e garantir consistência ao longo do ciclo de vida do ML. Ao automatizar tarefas, você pode:
- Integre ferramentas de alerta para desencadear um fluxo de ingestão vetorial à medida que novos dados entram na sua aplicação.
- Defina limites de desempenho do modelo para rastrear degradações e acionar processos de re-treino.
Em ambos os modos do AKS, inclua a automatização da validação de políticas, da deteção de desvios de configuração e da governação de lançamentos, além dos gatilhos de qualidade do modelo.
Escalabilidade e gerenciamento de recursos
Conclusão chave: Otimize o uso de recursos através de computação distribuida, autoescalabilidade e planeamento de recuperação de desastres para lidar com as diferentes exigências do pipeline de IA de forma económica.
A escalabilidade e o gerenciamento de recursos são essenciais para garantir que seu pipeline de IA possa lidar com as demandas de seu aplicativo. Ao otimizar o uso de recursos, você pode:
- Integre ferramentas que utilizem eficientemente os seus recursos de CPU, GPU e memória atribuídos através de computação distribuída e múltiplos níveis de paralelismo, como paralelismo de dados, modelos e pipelines.
- Habilite o dimensionamento automático em seus recursos de computação para dar suporte a altos volumes de solicitação de modelo em horários de pico e reduzir a escala fora do horário de pico.
- Planeie a recuperação de desastres seguindo as melhores práticas de resiliência e fiabilidade do AKS.
O AKS Automatic pode reduzir a sobrecarga de configuração para padrões comuns de escalabilidade e operações, enquanto o AKS Standard oferece um controlo mais profundo para arquiteturas de escalabilidade personalizadas.
Executar tarefas em lote de longa duração
Conclusão: Executar trabalho finito como Kubernetes Job, persistir o progresso fora do pod, tratar dos sinais de terminação e assumir que o Job pode começar mais do que uma vez.
Atualizações de nós, reinícios, eventos de redução de escala, pressão sobre os recursos, preempção e falhas de infraestrutura podem interromper tarefas em lote de longa duração. Um Kubernetes Job substitui um pod falhado ou eliminado, mas a substituição começa noutro nó sem os ficheiros locais ou memória de processo do pod anterior. Conceba a aplicação para retomar a partir de um estado persistente e repetir o trabalho de forma segura.
Utilize estas práticas para tarefas em lote comuns com utilização intensiva de CPU, memória ou I/O. A orientação de agendamento em grupo e fila de carga de trabalho aplica-se quando uma carga distribuída exige que vários trabalhadores comecem juntos ou quando as equipas precisam de quotas partilhadas. Um trabalho com um único trabalhador ou um lote paralelo independente normalmente não precisa de agendamento em grupo.
Configurar pontos de verificação, novas tentativas e encerramento
O exemplo seguinte processa uma sequência de itens de trabalho e regista o item seguinte num volume persistente do Ficheiros do Azure. Restaura o ponto de controlo após a substituição do pod e guarda o progresso quando o processo recebe 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
Substitua o ciclo de amostra pela sua aplicação lote e selecione o armazenamento que cumpra os requisitos de throughput e recuperação. Use a identidade da carga de trabalho em vez de credenciais embutidas quando a aplicação apontar diretamente para o Armazenamento de Blobs do Azure ou outro serviço Azure.
Aplicar estes controlos de fiabilidade de forma deliberada:
-
Pontos de verificação e idempotência: Guarde o progresso a intervalos que cumpram o seu objetivo de ponto de recuperação. Armazene os checkpoints e a saída confirmada no armazenamento persistente, não no sistema de ficheiros do contentor,
emptyDir, ou no armazenamento local do nó. Utilize escritas atómicas, chaves de idempotência, saída transacional ou deduplicação, porque o mesmo programa Job pode, por vezes, ser iniciado mais do que uma vez. -
Comportamento de reinício: Uma tarefa permite
restartPolicy: NeverouOnFailure. ComNever, um contentor avariado produz um pod avariado e o controlador Job cria um substituto. ComOnFailure, o kubelet pode reiniciar o contentor no mesmo pod. UseNeverquando pods e registos separados falhados facilitam o diagnóstico e tornam qualquer um dos caminhos seguros para retomar. -
Limites de repetição: Defina
backoffLimitcom base no número de falhas transitórias que a carga de trabalho pode tolerar. UsepodFailurePolicypara falhar imediatamente com códigos de saída conhecidos que não permitem repetição ou, como no exemplo, para evitar que interrupções voluntárias consumam o orçamento de tentativas de repetição. Uma interrupção pode, ainda assim, parar o pod; a política apenas altera a forma como a tarefa contabiliza essa falha. -
Prazos: Define
activeDeadlineSecondsquando o Trabalho tem de parar após um tempo máximo de execução total. O prazo inclui novas tentativas e prevalece sobrebackoffLimit. Não definas um prazo mais curto do que o tempo de execução esperado mais o tempo de nova tentativa e de recuperação. Um trabalho falhado não é automaticamente reiniciado como um novo emprego. -
Encerramento gracioso: Trate
SIGTERMna aplicação e definaterminationGracePeriodSecondscom tempo suficiente para deixar de aceitar novo trabalho, concluir ou abandonar em segurança a unidade atual, descarregar a saída e guardar um ponto de controlo. O Kubernetes enviaSIGKILLse o processo exceder o período de tolerância, pelo que os pontos de controlo periódicos continuam a ser necessários. -
Limpeza: Defina
ttlSecondsAfterFinishedou configure limites de histórico de CronJobs para evitar o acumular de Jobs e pods concluídos. Manter os registos da tarefa durante tempo suficiente para a recolha de registos e a investigação de incidentes.
Planear remoções e manutenção de nós
Não trate o impedimento da expulsão como a principal estratégia de recuperação para uma tarefa de longa duração. Para uma tarefa em lote reiniciável, normalmente, não crie um PodDisruptionBudget (PDB); o controlador da tarefa cria um pod de substituição após uma interrupção voluntária. Um PDB protege apenas contra expulsões voluntárias e não protege contra falhas nos nós, expulsões por pressão de recursos ou preempção. Um PDB que não permita quaisquer interrupções também pode bloquear o esvaziamento de nós e atrasar atualizações do AKS.
Use um PDB apenas quando uma carga de trabalho em lote paralelo tiver de reter um número mínimo de trabalhadores em funcionamento simultâneo e tiver testado o seu comportamento de drenagem. Da mesma forma, use cluster-autoscaler.kubernetes.io/safe-to-evict: "false" apenas para trabalhos excecionais e não reiniciáveis. A anotação pode impedir a redução de escala e aumentar o custo, mas não protege contra a falha de um nó nem contra todos os eventos de manutenção.
O AKS atualiza o cordão e drena os nós antigos antes de os substituir. Configure janelas de manutenção planeada para alinhar a manutenção do AKS suportada com períodos de menor impacto, mas assegure-se de que a carga de trabalho pode ser reiniciada, porque a calendarização da manutenção não elimina interrupções não planeadas. Para o AKS Standard, execute processos em lote num conjunto dedicado de nós de utilizador quando necessitarem de tamanhos de VM distintos, limites de escalabilidade, taints ou calendarização das atualizações separados. Evite pools de nós Spot para cargas de trabalho que não consigam recuperar após a preempção. Antes da manutenção dos nós, verifique se os checkpoints recentes são utilizáveis e se outro pool de nós elegível tem quota e capacidade suficientes para operar pods de substituição.
Monitorizar o progresso profissional e a recuperação
Use o estado, eventos e registos do Kubernetes juntos quando investigar um trabalho de longa duração:
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
Ative o serviço gerido Azure Monitor para Prometheus e Container Insights para manter registos e correlacionar o estado do trabalho com reinicios de pods, despejos, tempo pendente, saúde dos nós e utilização de recursos. Instrumente a aplicação com sinais de progresso do negócio, como itens concluídos, itens falhados, último ponto de verificação bem-sucedido, taxa de processamento, contagem de tentativas e tempo estimado de conclusão. Alerta sobre um trabalho falhado, um trabalho que excede a sua duração esperada, sem ponto de controlo dentro do objetivo do ponto de recuperação, substituições repetidas de pods, pods pendentes prolongados e processamento estagnado.
Segurança e conformidade
Principal conclusão: Implemente análise CVE, registos de auditoria e controlos de conformidade para proteger os seus dados e cumprir requisitos regulamentares como SOC 2, HIPAA e RGPD.
A segurança e a conformidade são essenciais para proteger seus dados e garantir que seu pipeline de IA atenda aos requisitos regulamentares. Ao implementar práticas recomendadas de segurança e conformidade, você pode:
- Integrar a varredura de Vulnerabilidades e Exposições Comuns (CVEs) para detetar vulnerabilidades comuns em imagens de contentores de modelos open-source.
- Use o Microsoft Defender for Containers para imagens de contêiner modelo armazenadas em seu Registro de Contêiner do Azure.
- Mantenha uma trilha de auditoria dos dados ingeridos, alterações de modelo e métricas para permanecer em conformidade com suas políticas organizacionais.
- Suportam quadros de conformidade como SOC 2 (através do registo de auditoria e controlos de acesso do Azure), HIPAA (via encriptação em repouso e em trânsito, isolamento de rede) e RGPD (através de opções de residência de dados e políticas de gestão de acessos).
No AKS Automatic, os padrões de segurança pré-configurados melhoram a postura base, mas continuam a ser necessários controlos de segurança ao nível do modelo, dos dados e do pipeline.
Agendar cargas de trabalho da GPU
Ideia principal: Expor as GPUs através do plug-in de dispositivos da NVIDIA, solicitar GPUs explicitamente e isolar os nós de GPU dispendiosos com rótulos, taints e tolerations.
O Kubernetes programa GPUs como recursos estendidos. Depois de o plug-in de dispositivo da NVIDIA registar as GPUs num nó, um pod solicita uma GPU definindo nvidia.com/gpu tanto em resources.requests como em resources.limits. O pod seguinte solicita uma GPU e dirige-se a um pool de nós rotulado 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
Os recursos expandidos não têm alocação excessiva. O Kubernetes trata um limite de GPU como um pedido de GPU quando apenas o limite está especificado, mas definir ambos os campos torna explícita a intenção da carga de trabalho e ajuda na validação de políticas.
Aprovisionar um conjunto de nós de GPU no AKS
Para o AKS Standard, cria um pool dedicado de nós de utilizador com um tamanho de VM de GPU Nvidia suportado. O seguinte exemplo do CLI do Azure cria um pool de nós autoescalonadoStandard_NC4as_T4_v3, aplica o rótulo usado pelo pod anterior e contamina os nós para repelir cargas de trabalho que não toleram explicitamente nós 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 criar o pool de nós, verifique se o SKU da VM está disponível na região do cluster e se a subscrição tem quotas regionais e de famílias de VM suficientes. Selecione um tamanho da série NC com base na memória da GPU, número de GPUs, relação CPU-GPU, armazenamento local, rede e as capacidades CUDA exigidas pelo framework de treino. Por exemplo, os tamanhos NCas T4 v3 são adequados para muitas cargas de treino com GPU única e menores, enquanto os tamanhos NC A100 v4 suportam modelos maiores e configurações de GPU multi-instância.
O AKS Automatic pode provisionar capacidade de GPU elegível em resposta a pods pendentes. A carga de trabalho deve continuar a solicitar nvidia.com/gpu, e quaisquer seletores de nós, afinidades, tolerâncias, restrições de topologia, quotas de subscrição e disponibilidade regional de SKU devem ser satisfatórios. Use o AKS Standard quando precisar de um SKU de VM fixo, ciclo de vida personalizado de pool de nós ou controlo detalhado sobre a escalabilidade e topologia do pool de GPU.
Verifique ou instale o plugin do dispositivo NVIDIA
As configurações de GPU do AKS podem disponibilizar controladores de GPU geridos e integração com o plug-in de dispositivos. Verifique a configuração eficaz antes de instalar outro plugin:
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"
Não execute vários DaemonSets do plug-in de dispositivo NVIDIA nos mesmos nós. Se a sua configuração AKS não gerir o plugin, o seguinte DaemonSet standalone regista as GPUs NVIDIA com o kubelet. Instale uma versão do plug-in de dispositivo compatível com o seu controlador NVIDIA e com a versão do 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
Confirma que nvidia.com/gpu aparece em os recursos alocáveis de cada nó de GPU antes de submeter trabalhos de treino.
Partição das GPUs A100 e H100 com MIG
A NVIDIA Multi-Instance GPU (MIG) pode particionar uma GPU A100 ou H100 suportada em instâncias de GPU isoladas. O MIG é útil para ajustes de hiperparâmetros e pequenos ajustes finos que não exigem uma GPU física inteira. Use GPUs completas para cargas de trabalho que exijam toda a memória da GPU, largura de banda máxima de interligação ou um perfil que não seja suportado pela GPU instalada.
Use o NVIDIA GPU Operator e MIG Manager quando precisar de uma gestão declarativa do ciclo de vida MIG. O operador deve gerir o plug-in de dispositivo e a configuração MIG dos nós afetados; não o combine com um segundo plug-in de dispositivo autónomo. Os nomes exatos dos perfis e o número de instâncias dependem do modelo da GPU e da capacidade de memória. A configuração seguinte cria sete 1g.10gb instâncias em configurações suportadas de A100 ou H100 de 80 GB:
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 o Gestor de MIG do GPU Operator para consumir o ConfigMap mig-parted-config, utilize a estratégia MIG mixed quando as cargas de trabalho solicitarem perfis MIG com nome e, em seguida, rotule os nós de destino:
kubectl label nodes \
-l accelerator=nvidia \
nvidia.com/mig.config=hptuning-1g10gb \
--overwrite
Mudar o layout de um MIG interrompe as cargas de trabalho que já usam a GPU. Isole e drene o nó de destino, aplique a configuração durante uma janela de manutenção e confirme que o perfil solicitado existe nos recursos alocáveis do nó antes de submeter as tarefas.
Isolar cargas de trabalho da GPU com contaminações e tolerâncias
Uma NoSchedule contaminação mantém os pods de aplicação comuns afastados de nós caros da GPU. O exemplo de criação de pool de nós utiliza sku=gpu:NoSchedule. O Job completo seguinte inclui a tolerância correspondente e um seletor de nós:
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
Uma tolerância permite o agendamento, mas não força o pod para um nó da GPU. Associe as tolerâncias a um pedido de recursos de GPU e a um seletor de nós ou à afinidade de nó. Certifique-se de que os DaemonSets necessários da plataforma, como os de rede, monitorização, armazenamento e o plug-in de dispositivo, toleram a mancha da GPU.
Executar cargas de treino distribuídas
Conclusão principal: Use um operador de formação para gerir as identidades dos trabalhadores e o ciclo de vida do trabalho, valide a comunicação em rede multi-nós e utilize a admissão em grupo quando todos os trabalhadores têm de começar em conjunto.
O treino distribuído utiliza múltiplos processos para dividir dados, estado do modelo ou etapas do pipeline. No Kubernetes, um operador pode criar pods de trabalho, injetar a configuração de sincronização, acompanhar o estado das réplicas, reiniciar trabalhadores que falharam e limpar a tarefa. Instale e forme os operadores através do processo IaC e lançamento da sua plataforma, em vez de permitir que equipas individuais instalem CRDs não governados a nível de cluster.
Constrói uma imagem portátil de treino CUDA
O Dockerfile seguinte desenvolve o padrão de Dockerfile identificado na secção sobre contentorização. A imagem contém as bibliotecas de execução do CUDA e do PyTorch, enquanto o controlador NVIDIA compatível permanece no nó GPU do 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"]
Fixe a imagem de base utilizando um digest imutável em produção. Mantém os conjuntos de dados e os checkpoints que mudam frequentemente fora da imagem, e analisa a imagem resultante antes de a enviar para o Azure Container Registry.
Executa um PyTorchJob
O Kubeflow Training Operator disponibiliza o CRD PyTorchJob. Instale uma versão de Operador de Treino compatível com a sua versão Kubernetes antes de aplicar este manifesto. O exemplo seguinte de duas réplicas realiza uma operação NCCL all-reduce entre um mestre e um trabalhador:
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 treino em produção, substitui o teste em linha pela tua imagem de treino versionada e pelo teu script versionado. Alinhe o número de réplicas com o número de GPUs e de processos exigidos pelo framework de treino.
Executa um TFJob
O Operador de Formação também fornece o TFJob CRD. O exemplo seguinte executa treino TensorFlow síncrono entre dois trabalhadores da 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 treino com servidor de parâmetros, defina os tipos de réplica Chief, Worker e PS de acordo com a estratégia de distribuição do TensorFlow. Meça os gargalos resultantes da rede e do parâmetro-servidor antes de aumentar o número de réplicas.
Afinar um modelo com KAITO
O KAITO fornece uma abstração de área de trabalho centrada no AKS para a implantação e afinação de modelos. Ative a extensão KAITO ou instale uma versão compatível do KAITO antes de aplicar um Workspace. Verifique se o predefinido selecionado, o SKU da VM e o método de ajuste fino são suportados pela versão instalada do KAITO.
O seguinte espaço de trabalho solicita uma VM da GPU A100 e inicia a afinação do QLoRA para um preset Phi-3 suportado usando um conjunto de dados acessível publicamente:
apiVersion: kaito.sh/v1beta1
kind: Workspace
metadata:
name: workspace-tuning-phi-3-mini
resource:
instanceType: Standard_NC24ads_A100_v4
labelSelector:
matchLabels:
apps: phi-3-mini-tuning
tuning:
preset:
name: phi-3-mini-4k-instruct
method: qlora
input:
urls:
- https://huggingface.co/datasets/yahma/alpaca-cleaned/resolve/main/alpaca_data_cleaned.json
O KAITO pode coordenar a configuração predefinida do modelo e a infraestrutura de GPU necessária para o espaço de trabalho. Para produção, armazene o conjunto de dados de treino numa conta de armazenamento Azure aprovada, use acesso privado e identidade de carga de trabalho quando suportado, e persista o modelo resultante num registo de modelo governado ou Azure Container Registry. Trate o manifesto do workspace, a versão do conjunto de dados de entrada, a versão predefinida, a configuração do adaptador e o digest da imagem de saída como um único registo de treino versionado.
Configurar a comunicação NCCL com o AKS CNI
A NVIDIA Collective Communications Library (NCCL) gere operações coletivas como all-reduce. Para uma base TCP portátil no AKS CNI, use a interface de rede pod, normalmente eth0, e comece por NCCL_IB_DISABLE=1. Em tamanhos de VM suportados com capacidade para RDMA, utilize a configuração de RDMA da NVIDIA e do Azure documentada e valide-a antes de definir NCCL_IB_DISABLE=0.
Use estas variáveis ambientais de base:
-
NCCL_SOCKET_IFNAME=eth0Seleciona a interface de rede POD. -
NCCL_DEBUG=INFOfornece diagnósticos durante a validação. Reduz o nível do log após a afinação. -
NCCL_IB_DISABLE=1seleciona sockets TCP quando o RDMA não está configurado. -
TORCH_NCCL_ASYNC_ERROR_HANDLING=1ajuda o PyTorch a terminar em vez de ficar suspenso indefinidamente após falhas de comunicação assíncronas.
Se a política de rede estiver ativada, permita todo o tráfego necessário de rendezvous e NCCL entre as réplicas. A NCCL pode negociar portos dinâmicos, por isso uma política de portos fixos estreitos pode fazer com que os empregos de formação fiquem suspensos. A seguinte política permite comunicação irrestrita pod-a-pod apenas entre réplicas do trabalho PyTorch e permite a resolução 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
Compare o NCCL independentemente do treino do modelo antes de escalar. Compare a largura de banda reduzida, latência, utilização da GPU e débito de treino em cada número de trabalhadores. Mais trabalhadores podem reduzir o desempenho quando a comunicação ou o carregamento de dados se tornam o gargalo.
Utilize o agendamento em grupo e as filas de cargas de trabalho
Conclusão principal: Admitir trabalhadores distribuídos como grupo e aplicar quotas de GPUs de inquilino para que os trabalhos parcialmente agendados não reservem GPUs enquanto esperam pelos trabalhadores restantes.
O agendador predefinido do Kubernetes atribui os pods individualmente. Para um trabalho distribuído que não consegue progredir até que todos os trabalhadores estejam a funcionar, a colocação parcial pode desperdiçar capacidade da GPU. A Kueue assegura o controlo de admissões e a gestão de quotas antes do início da operação dos pods. O Volcano fornece um agendador e um modelo de agendamento tudo ou nada baseado no PodGroup.
O AKS Automatic fornece o escalonador Kubernetes predefinido e o provisionamento automático de nós como ponto de partida. Submeter empregos ordinários ou trabalhos de formação geridos por operadores com pedidos de recursos precisos e deixar que a plataforma forneça capacidade elegível. Este comportamento não garante a admissão atómica para todos os trabalhadores. Instale o Kueue ou o Volcano quando uma carga de trabalho exigir escalonamento em grupo, colocação em fila, quotas de equipa, partilha justa ou comportamento de preempção personalizado.
Aloque quota de GPU multitenant com Kueue
Instala uma versão Kueue compatível com a versão Kubernetes e ativa integrações para os tipos de carga de trabalho que usas. O manifesto seguinte cria:
- Uma GPU
ResourceFlavorassociada a nós identificados comoaccelerator=nvidia. - Quatro GPUs
ClusterQueuepara a equipa A. - Uma configuração de duas GPUs
ClusterQueuepara a equipa B. - Um
LocalQueuecom escopo de espaço de nomes para cada equipa. - Um trabalho com dois trabalhadores que Kueue admite apenas quando os recursos solicitados estão disponíveis.
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
Uma ClusterQueue quota é uma quota de agendamento, não uma quota de subscrição do Azure. Certifique-se de que o cluster AKS consegue provisionar a capacidade subjacente da VM e que a quota da GPU Azure é suficiente para a carga de trabalho agregada admitida. Use coortes e funcionalidades de partilha justa do Kueue quando as equipas possam pedir quotas não utilizadas umas das outras.
Use o Vulcão como alternativa
O Volcano é uma alternativa quando queres um programador de lotes dedicado com agendamento de grupos, filas e políticas de ciclo de vida do trabalho. Instale uma versão do Volcano compatível com o cluster antes de aplicar os respetivos CRDs. A seguinte tarefa do Volcano exige que ambos os workers de GPU estejam disponíveis antes de a tarefa ser executada:
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
Padronize num sistema primário de fila e agendamento em grupo, a menos que tenha um design de interoperabilidade comprovado. Múltiplos controladores de admissões ou agendadores podem, de outra forma, dificultar a razão sobre comportamentos pendentes e de preempção.
Configurar prioridades de treino e inferência
A inferência sensível à latência normalmente requer uma prioridade superior ao treino em lote interrompível. Os seguintes PriorityClass recursos permitem que os pods de inferência preemptam pods de menor prioridade, ao mesmo tempo que impedem que os pods de treino em lote preemptam outras cargas de trabalho:
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.
Atribui a classe através spec.priorityClassName do modelo do pod. A prioridade do pod do Kubernetes e a prioridade da carga de trabalho do Kueue afetam diferentes fases: o Kueue controla a admissão à fila, enquanto a prioridade do Kubernetes influencia o agendamento e a preempção do pod após a admissão. Coordena ambas as políticas para que expressem a mesma prioridade de negócio.
A preempção termina os pods com prioridade inferior. As cargas de trabalho de treino que podem ser interrompidas devem gravar pontos de verificação em armazenamento persistente, tolerar trabalho duplicado e recuperar após falhas sem depender de ficheiros locais do nó.
Configurar memória partilhada e gestão de recursos
Ideia-chave: Substitua o pequeno valor predefinido do ambiente de execução do contentor /dev/shm, configure os pedidos de recursos com base na utilização observada e configure o dimensionamento dos nós com base nos requisitos completos da carga de trabalho de GPU.
Aumente /dev/shm para carregadores de dados de ML
Os carregadores de dados do PyTorch, os pipelines de entrada do TensorFlow, o NCCL e o multiprocessamento em Python podem usar memória partilhada POSIX. A predefinição do contentor para /dev/shm é frequentemente demasiado pequena para treino com vários processos, o que pode causar falhas dos processos de trabalho, erros de barramento ou aparentes bloqueios no treino.
Monte um emptyDir baseado em memória em /dev/shm e defina um 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
A utilização baseada em memória emptyDir é contabilizada no consumo de memória do pod. Incluir o uso máximo esperado de memória partilhada ao definir o limite de memória do contentor. Se /dev/shm ultrapassar o orçamento efetivo de memória, o pod pode ser desalojado ou terminado por exceder o seu limite de memória.
Dimensionar CPU e memória com base na utilização observada
Comece com um benchmark baseado no modelo representativo, tamanho do lote, comprimento da sequência, concorrência do carregador de dados, aumento e comportamento dos pontos de controlo. Depois, use os dados de monitorização para ajustar:
- Defina as requisições de CPU suficientemente elevadas para manter os pipelines de alimentação da GPU abastecidos. Períodos persistentes de inatividade da GPU podem indicar falta de CPU ou armazenamento.
- Configure os pedidos de memória para valores próximos da utilização estável do conjunto de trabalho, mais uma margem de segurança. Inclua
/dev/shm, o comportamento da cache de páginas, a sobrecarga do alocador do framework e os picos de serialização dos pontos de verificação. - Defina limites de memória acima do pico observado. Investigue os
OOMKilledeventos em vez de continuar a aumentar os limites sem encontrar a causa. - Avalie a limitação da CPU antes de usar limites restritivos da CPU. Limites de CPU demasiado baixos podem reduzir a utilização da GPU mesmo quando o uso médio da CPU parece aceitável.
- Defina solicitações e limites iguais para tarefas de treino previsíveis e de elevado valor, quando a qualidade de serviço garantida é mais importante do que a compactação de nós.
- Analise todas as alterações significativas ao tamanho do modelo, à precisão, ao tamanho do lote, ao número de trabalhadores e à pipeline de dados.
Utilize percentis com base em execuções de treino completas em vez de uma média de curto prazo. As fases de arranque, validação, ponto de verificação e baralhamento de dados têm frequentemente picos de utilização de recursos diferentes.
Configurar o dimensionamento automático do cluster num conjunto de nós com GPU
Para o AKS Standard, ative o autoscaler do cluster no pool de nós do utilizador da GPU e defina a capacidade mínima e 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
Podes ajustar as definições de perfil do autoescalador de cluster suportadas no âmbito do cluster. Alterações no perfil de teste tanto em relação a cargas de treino como de serviço:
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
Um pod de GPU pendente só ativa a escalabilidade quando os seus requisitos completos de agendamento correspondem a um modelo de pool de nós. Verifique o pedido de recursos da GPU, capacidade da VM, etiquetas, contaminações, tolerâncias, afinidade, restrições de topologia, topologia de volumes persistentes, número máximo de nós e quota do Azure quando não ocorrer escalabilidade.
O escalonamento até zero é adequado para conjuntos de recursos de treino interrompíveis, mas acrescenta latência no aprovisionamento das VMs, na obtenção da imagem, na montagem do conjunto de dados e na inicialização do modelo. Mantenha um mínimo não nulo quando a latência de arranque tiver um efeito material nos objetivos do serviço. Orçamentos de interrupção de pods, pods que não podem ser removidos, armazenamento local e longos períodos de tolerância antes da terminação podem atrasar a redução do dimensionamento.
AKS Automatic gere o aprovisionamento e o dimensionamento dos nós como parte da configuração de base do serviço. Concentre-se em pedidos de pods precisos e restrições suportadas, em vez de configurar um escalador automático manual para um conjunto de nós GPU.
Armazenar conjuntos de dados e pontos de verificação
Ideia-chave: Selecione o armazenamento com base no padrão de acesso, débito, partilha e requisitos de recuperação, e guarde os pontos de verificação fora do nó para que o treino possa ser recuperado após expulsão ou preempção.
Mantenha grandes conjuntos de dados, artefactos do modelo e pontos de verificação fora das imagens de contentor. Escolha uma interface de armazenamento com base na carga de trabalho:
- Use o Armazenamento de Blobs do Azure para grandes conjuntos de dados de objetos, artefactos de modelos e repositórios de dados de alta capacidade.
- Use o Ficheiros do Azure quando múltiplos nós worker requerem um sistema de ficheiros partilhado ao estilo POSIX.
- Utilize o Azure Disk para cargas de trabalho de ponto de verificação ou de cache de leitura e escrita de um único nó e de elevado desempenho, quando
ReadWriteOncefor suficiente. - Use o armazenamento efémero local ao nó apenas para caches reconstruíveis e ficheiros temporários.
Aceder a grandes conjuntos de dados com o driver CSI do Azure Blob
Ative o driver CSI do Azure Blob no AKS Standard se ainda não estiver ativado:
RESOURCE_GROUP=myResourceGroup
AKS_CLUSTER=myAKSCluster
az aks update \
--resource-group "$RESOURCE_GROUP" \
--name "$AKS_CLUSTER" \
--enable-blob-driver
O exemplo seguinte cria dinamicamente um contentor Azure Blob premium exposto através do NFS e monta-o num pod de treino. Para um conjunto de dados governado existente, use um volume definido estaticamente ou uma configuração BlobFuse com a identidade adequada e controlos de rede privada em vez de criar um contentor dinâmico vazio:
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
Compare o protocolo e as opções de montagem com tamanhos representativos de fragmentos e padrões de acesso. Muitos trabalhadores que leem muitos ficheiros pequenos podem obter resultados diferentes ao transmitir sequencialmente grandes fragmentos. Considere pré-processar os conjuntos de dados em partições de tamanho adequado e utilizar espaço de cache local ao nó quando, de outra forma, múltiplas épocas obrigariam a descarregar novamente os mesmos objetos.
Partilhar dados de treino com Ficheiros do Azure
O Ficheiros do Azure suporta ReadWriteMany, que permite que trabalhadores distribuídos em diferentes nós montem a mesma partilha. Premium Ficheiros do Azure é apropriado quando a carga de trabalho requer desempenho previsível do sistema de ficheiros e a região selecionada suporta a opção de redundância necessária.
O manifesto seguinte cria uma partilha premium do Ficheiros do Azure e monta-a em dois pods de trabalhadores paralelos:
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 trabalhador enumere repetidamente um diretório contendo milhões de ficheiros. Use uma atribuição de manifesto ou de fragmento determinístico para que cada trabalhador saiba quais os objetos a ler.
Ponto de verificação para armazenamento persistente
Um ponto de verificação deve incluir informação de estado suficiente para retomar corretamente a execução, como os pesos do modelo, o estado do otimizador, o estado do escalonador, o estado do fator de escala, a época ou o número do passo, o estado do gerador de números aleatórios e a posição no carregador de dados, quando aplicável. Escreva pontos de controlo periodicamente e antes de terminarem de forma elegante.
O Job seguinte escreve checkpoints atómicos do PyTorch no Ficheiros do Azure, restaura o checkpoint mais recente após o reinício do contentor ou a substituição de um pod e gere SIGTERM de modo a que a preempção possa preservar o progresso recente:
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
Utilize uma política de recuperação Retain ou uma conta de armazenamento gerida independentemente para os checkpoints de produção, para que a eliminação de um PVC não apague involuntariamente o único ponto de recuperação. Para treino distribuído com paralelismo de dados, normalmente, o processo de rank zero deve escrever o checkpoint global ou utilizar um formato fragmentado de checkpoint suportado pela framework. Evitar que vários ranks escrevam o mesmo ficheiro em simultâneo.
Teste a recuperação eliminando deliberadamente um worker pod durante uma execução não produtiva. Verifique se o controlador recria a carga de trabalho, que o novo pod monta o mesmo volume persistente e que o treino recomeça a partir do passo esperado.
Monitorize a utilização da GPU e a taxa de processamento do treino
Ideia-chave: Monitorize em conjunto a computação da GPU, a memória da GPU, o débito do pipeline de dados, a duração de cada passo e a atividade dos checkpoints para distinguir a saturação computacional de estrangulamentos na CPU, na rede ou no armazenamento.
Ative o serviço gerido do Azure Monitor para Prometheus e Container Insights para correlacionar o estado do Kubernetes, os registos de contentores, a saúde dos nós e as métricas do Prometheus. Utilize as melhores práticas de monitorização para o AKS ao conceber alertas, retenção e dashboards operacionais.
Recolha métricas da GPU NVIDIA
O Exportador NVIDIA Data Center GPU Manager (DCGM) expõe métricas Prometheus para GPUs NVIDIA. Se o Operador de GPU NVIDIA já implementa o Exportador DCGM, não implemente um exportador duplicado. Configure o Prometheus gerido pelo Azure Monitor para extrair o exportador existente.
O PodMonitor seguinte utiliza o CRD de Prometheus gerido do Azure Monitor e tem como destino os pods do Exportador DCGM no espaço de nomes gpu-operator. Ajuste o seletor de etiquetas para corresponder às etiquetas usadas pelo 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
Verifique o nome do serviço exportador ou da porta pod antes de aplicar o monitor. Métricas comuns do DCGM incluem:
| Métrico | Purpose |
|---|---|
DCGM_FI_DEV_GPU_UTIL |
Percentagem de tempo em que a GPU está ativa |
DCGM_FI_DEV_FB_USED |
Memória de frame-buffer utilizada |
DCGM_FI_DEV_FB_FREE |
Memória disponível do frame buffer |
DCGM_FI_DEV_MEM_COPY_UTIL |
Utilização do motor de cópia de memória |
DCGM_FI_DEV_POWER_USAGE |
Consumo de energia da GPU |
DCGM_FI_DEV_GPU_TEMP |
Temperatura da GPU |
DCGM_FI_DEV_XID_ERRORS |
Eventos de erro XID da NVIDIA |
A disponibilidade das métricas depende da GPU, driver, DCGM e versões para exportador.
Métricas de rendimento de treino de exportação
Instrumente o programa de treino com métricas ao nível da carga de trabalho. Métricas úteis incluem:
-
ml_training_samples_totalpara amostras cumulativas ou tokens processados. -
ml_training_steps_totalpara etapas do otimizador concluídas. -
ml_training_step_duration_secondspara a latência por etapa. -
ml_training_checkpoint_duration_secondspara latência do ponto de verificação. -
ml_training_data_wait_secondspara tempo de espera pelos dados de entrada. - Perda específica do modelo, taxa de aprendizagem, norma de gradiente e métricas de validação.
O exemplo executável seguinte expõe métricas sintéticas de treino na porta 8000. Substitua a simulação por métricas emitidas pelo ciclo real de treino:
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 um trabalho distribuído real, inclua etiquetas estáveis como nome do modelo, versão do modelo, nome do trabalho, ID da execução, função de réplica e equipa. Não use rótulos ilimitados como IDs de amostra, IDs de pedido ou caminhos brutos de conjuntos de dados, porque rótulos de alta cardinalidade aumentam o custo de monitorização e a latência das consultas.
Construir dashboards de GPU e throughput
Utilize consultas em PromQL, como as seguintes, como pontos de partida e valide os rótulos das métricas com base no seu exportador:
avg by (namespace, pod, gpu) (
avg_over_time(DCGM_FI_DEV_GPU_UTIL[5m])
)
A consulta seguinte calcula a utilização da memória do frame-buffer em percentagem:
100 *
DCGM_FI_DEV_FB_USED
/
(DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE)
A consulta seguinte calcula amostras de treino processadas por segundo:
sum by (job_name) (
rate(ml_training_samples_total[5m])
)
A consulta seguinte mostra a duração média dos passos:
avg by (job_name) (
ml_training_step_duration_seconds
)
Interprete estes sinais em conjunto:
- A baixa utilização da GPU e o elevado tempo de espera de dados geralmente indicam armazenamento, rede, pré-processamento ou falta de CPU.
- A elevada utilização da GPU com o throughput esperado indica que o acelerador está a ser usado eficazmente.
- A utilização elevada da memória da GPU e os erros repetidos de falta de memória indicam que o tamanho do lote, o comprimento das sequências, a memória de ativação, o estado do otimizador ou a fragmentação necessitam de ajuste.
- A diminuição da taxa de processamento com uma utilização estável da GPU pode indicar sequências mais longas, sobrecarga de comunicação, comportamento térmico ou uma alteração na computação do modelo.
- A baixa utilização da GPU nas GPUs alocadas indica capacidade ociosa que pode ser reduzida, colocada em fila de forma diferente ou particionada com MIG.
- A longa duração dos pontos de controlo pode tornar a preempção dispendiosa e aumentar a quantidade de trabalho repetido após a recuperação.
Crie alertas para subutilização prolongada da GPU, memória GPU quase de capacidade, erros XID, atraso no treino, trabalhadores falhados, cargas de trabalho agendadas em grupo pendentes e checkpoints que não foram concluídos dentro do objetivo esperado de recuperação do ponto.
Perguntas mais frequentes (FAQ)
Qual é a diferença entre o AKS Automatic e o AKS Standard para MLOps?
O AKS Automatic fornece predefinições pré-configuradas para pools de nós, rede, segurança e atualizações, permitindo que as equipas MLOps se concentrem na definição de cargas de trabalho e na governação. O Padrão AKS exige a configuração manual destes componentes da plataforma, mas oferece um controlo mais profundo para arquiteturas personalizadas e requisitos de escalabilidade.
Como posso versionar modelos de ML no AKS?
Versione os seus modelos empacotando os pesos, os metadados e as configurações em imagens de contentores com identificadores de versão semântica. Armazene estas imagens no Azure Container Registry e faça referência a versões específicas nos seus manifestos de implementação Kubernetes para garantir consistência entre os ambientes.
Como faço para agendar cargas de trabalho da GPU no AKS?
Certifique-se de que o plugin do dispositivo NVIDIA está disponível para que os nós da GPU anunciem nvidia.com/gpu. No AKS Standard, prevê um pool dedicado de nós de utilizador da GPU com um tamanho de VM suportado, como um SKU da série Standard_NC, e configura rótulos de nós, um NoSchedule taint e limites do autoscaler do cluster. Em cada pod de treino, solicite nvidia.com/gpu, selecione um nó de GPU elegível e adicione a tolerância correspondente. O AKS Automatic pode aprovisionar capacidade de GPU elegível com base em pedidos de pods, sujeito às SKUs suportadas, à disponibilidade regional, às restrições de agendamento e à quota da subscrição do Azure.
Como posso executar trabalhos de formação distribuída no AKS?
Instale o Kubeflow Training Operator e submeta um PyTorchJob ou TFJob para gerir as réplicas distribuídas, a configuração de rendezvous, o comportamento de reinício e o estado da tarefa. O KAITO fornece uma abstração de área de trabalho orientada para o AKS para fluxos de trabalho suportados de aperfeiçoamento de modelos e pode coordenar a infraestrutura de GPU com predefinições de modelo. Para o treino do PyTorch em vários nós, configure e avalie o desempenho do NCCL na rede de pods AKS CNI, permita o tráfego entre nós de trabalho através da política de rede e utilize uma configuração RDMA suportada quando o SKU de VM selecionado e a carga de trabalho o exigirem.
Como gero a quota de GPUs em várias equipas?
Instale o Kueue e defina recursos ClusterQueue com quotas de CPU, memória e nvidia.com/gpu e, em seguida, associe o espaço de nomes de cada equipa à quota que lhe foi atribuída por meio de um LocalQueue. Utilize coortes do Kueue ou partilha equilibrada quando as equipas puderem usar capacidade não utilizada emprestada. O Volcano é uma alternativa quando precisa de um programador de lotes com admissão de trabalhadores tudo ou nada. Coordenar a prioridade da fila com os recursos do Kubernetes PriorityClass para que a inferência sensível à latência possa preemptar o treino interrompível e garantir que os trabalhos de treino preemptíveis recuperem dos checkpoints em armazenamento persistente.
Quais são as melhores práticas para executar trabalhos em lote de longa duração no AKS?
Use um Kubernetes Job para trabalho finito e um CronJob para trabalho programado. Persistir checkpoints e saídas confirmadas fora do pod, tornar o processamento idempotente, tratar SIGTERM, e definir solicitações explícitas de recursos, limites de repetição, prazos e políticas de limpeza. Parta do princípio de que a manutenção ou falha do nó pode levar à substituição do pod e teste se essa substituição restaura corretamente o checkpoint. Monitorizar o estado do trabalho, eventos do pod, registos, idade do checkpoint, throughput e comportamento de retentativas. Empregos comuns reiniciáveis não exigem agendamento de gangues nem PDB. Use esses controlos apenas quando os trabalhadores paralelos tiverem de começar juntos ou manter uma concorrência mínima testada.
Conteúdo relacionado
Saiba mais sobre as práticas recomendadas em outras áreas de implantação e operações de aplicativos no AKS: