Pular para o conteúdo principal

Guia de produção AI/ML

Executar um node pool GPU para experimentos é fácil. Executar inferência AI em escala de produção no AKS sem estourar o orçamento requer decisões de arquitetura cuidadosas. Este guia cobre o que importa.

Estratégia de node pool GPU

Seleção de SKU

Escolha a família de GPU com base na carga de trabalho, não a que tem mais VRAM.

SérieMelhor paraGPUVRAMUse quando
NC-series (T4)Treinamento, fine-tuningNVIDIA T416 GBVocê precisa de treinamento econômico ou inferência de modelos pequenos
NC A100Treinamento de modelos grandesNVIDIA A10080 GBVocê está treinando modelos que precisam de alta largura de banda de memória
ND-series (H100)Inferência de modelos grandesNVIDIA H10080 GBVocê está servindo modelos com 70B+ parâmetros em produção
NV-series (A10)Visualização, inferência leveNVIDIA A1024 GBVocê precisa de renderização ou modelos com menos de 13B parâmetros
aviso

Não use nós ND-series H100 por padrão. Eles custam de 10 a 30x mais que nós NC T4. Um modelo de 7B parâmetros roda bem em um único T4. Dimensione corretamente primeiro, faça upgrade depois.

Pools GPU spot para trabalhos não críticos

Use instâncias spot para inferência em lote, jobs de avaliação e cargas de trabalho de desenvolvimento. Não use spot para servir inferência em tempo real que tenha SLAs de latência.

az aks nodepool add \
--resource-group myResourceGroup \
--cluster-name myAKSCluster \
--name gpuspot \
--node-count 1 \
--node-vm-size Standard_NC6s_v3 \
--priority Spot \
--eviction-policy Delete \
--spot-max-price -1 \
--labels workload-type=batch-gpu

Taints e tolerations

Sempre aplique taints em node pools GPU. Sem taints, o scheduler colocará cargas de trabalho CPU em nós GPU caros.

az aks nodepool add \
--resource-group myResourceGroup \
--cluster-name myAKSCluster \
--name gpupool \
--node-count 1 \
--node-vm-size Standard_NC6s_v3 \
--node-taints sku=gpu:NoSchedule \
--labels sku=gpu

Adicione a toleration correspondente em cada carga de trabalho GPU:

tolerations:
- key: "sku"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
resources:
limits:
nvidia.com/gpu: 1

Scale-to-zero para economia de custos

Nós GPU ociosos custam o mesmo que nós GPU sob carga. Use KEDA com contagem mínima de nós igual a zero para eliminar gasto ocioso.

az aks nodepool add \
--resource-group myResourceGroup \
--cluster-name myAKSCluster \
--name gpuondemand \
--node-count 0 \
--min-count 0 \
--max-count 4 \
--enable-cluster-autoscaler \
--node-vm-size Standard_NC6s_v3 \
--node-taints sku=gpu:NoSchedule
informação

Nós GPU levam de 5 a 10 minutos para provisionar e ficar prontos. Considere esse tempo de cold-start na sua estratégia de escalabilidade. Para cargas de trabalho sensíveis à latência, mantenha pelo menos um nó aquecido.

Opções para servir modelos

Tabela de decisão

Escolha uma opção e comprometa-se. Não construa uma camada de serving customizada a menos que tenha uma equipe para mantê-la.

OpçãoMelhor paraComplexidadeMulti-modeloModelos customizados
KAITOModelos open-source popularesBaixaNãoLimitado
vLLMInferência LLM de alto throughputMédiaSimSim
Text Generation Inference (TGI)Modelos HuggingFaceMédiaNãoSim
Triton Inference ServerMulti-framework, modelos não-LLMAltaSimSim

KAITO

Use KAITO quando quiser implantar um modelo suportado com configuração mínima. KAITO cuida do provisionamento de nós GPU, download do modelo e serving automaticamente.

apiVersion: kaito.sh/v1alpha1
kind: Workspace
metadata:
name: llama-3-8b
spec:
resource:
instanceType: Standard_NC24ads_A100_v4
labelSelector:
matchLabels:
apps: llama-3-8b
inference:
preset:
name: llama-3-8b-instruct
dica

Comece com KAITO para sua primeira implantação. Migre para vLLM ou Triton apenas quando atingir as limitações do KAITO: pesos de modelo customizados, batching avançado ou serving multi-modelo em uma única GPU.

vLLM no AKS

Use vLLM quando precisar de alto throughput, continuous batching ou multiplexação de modelos. Implante-o como um deployment Kubernetes padrão.

apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-server
spec:
replicas: 1
selector:
matchLabels:
app: vllm
template:
metadata:
labels:
app: vllm
spec:
tolerations:
- key: "sku"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
containers:
- name: vllm
image: vllm/vllm-openai:latest
args: ["--model", "meta-llama/Llama-3-8B-Instruct",
"--max-model-len", "4096",
"--gpu-memory-utilization", "0.9"]
resources:
limits:
nvidia.com/gpu: 1
ports:
- containerPort: 8000
volumeMounts:
- name: model-cache
mountPath: /root/.cache/huggingface
volumes:
- name: model-cache
persistentVolumeClaim:
claimName: model-cache-pvc

Cache e armazenamento de modelos

Carregar um modelo de 16 GB da internet a cada inicialização de pod é o erro mais comum em AI de produção no Kubernetes.

Azure Files NFS para pesos de modelo compartilhados

Use Azure Files com NFS para modelos que múltiplos pods precisam acessar simultaneamente. Isso evita baixar o mesmo modelo para cada réplica.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: model-cache-pvc
spec:
accessModes:
- ReadWriteMany
storageClassName: azurefile-csi-nfs
resources:
requests:
storage: 100Gi

Init containers para download de modelos

Use um init container para baixar pesos do modelo do Azure Blob Storage antes que o servidor de inferência inicie. Isso separa a etapa de download do container de serving.

initContainers:
- name: model-downloader
image: mcr.microsoft.com/azure-cli:latest
command:
- bash
- -c
- |
az storage blob download-batch \
--destination /models \
--source model-weights \
--account-name mystorageaccount \
--auth-mode login
volumeMounts:
- name: model-volume
mountPath: /models

Cache NVMe local em VMs GPU

SKUs de VM GPU com NVMe local (NC A100 v4, ND H100 v5) oferecem armazenamento local rápido. Use-o como camada de cache para modelos quentes. Monte o disco local e copie modelos para lá no primeiro acesso.

dica

Combine Azure Files NFS como fonte de verdade com NVMe local como cache read-through. O compartilhamento NFS mantém todos os modelos; cada nó copia apenas os modelos necessários para o NVMe local na inicialização do pod.

Evite modelos baseados em imagem em escala

Embutir pesos do modelo na imagem do container significa pulls lentos, altos custos de egress do registro e tempos longos de inicialização de nós. Use isso apenas para modelos com menos de 2 GB.

Autoscaling de cargas de trabalho AI

KEDA com métricas Prometheus

KEDA é a melhor opção para escalar inferência AI no AKS. Use métricas Prometheus do seu servidor de inferência como trigger de escalabilidade.

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: vllm-scaler
spec:
scaleTargetRef:
name: vllm-server
minReplicaCount: 1
maxReplicaCount: 8
cooldownPeriod: 300
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus-server.monitoring:9090
metricName: vllm_pending_requests
query: sum(vllm:num_requests_waiting)
threshold: "10"

Métricas-chave para escalar:

MétricaEscale quandoPor quê
Profundidade da fila / requisições pendentesRequisições esperando > thresholdMede diretamente a demanda acumulada
Utilização de GPUSustentada > 80%Indica saturação de computação
Latência de requisição (p95)Excede o alvo de SLACaptura degradação antes que os usuários percebam
Tamanho do batchConsistentemente no máximoSignifica que o servidor não está dando conta

HPA com métricas customizadas

Se você não está usando KEDA, configure HPA com métricas customizadas do Prometheus adapter. KEDA é preferido porque suporta scale-to-zero.

Scale-to-zero fora do horário

spec:
minReplicaCount: 0
triggers:
- type: cron
metadata:
timezone: America/Los_Angeles
start: 0 8 * * 1-5
end: 0 20 * * 1-5
desiredReplicas: "1"

Considerações do node autoscaler

O cluster autoscaler provisiona nós GPU quando pods estão pendentes. Espere de 5 a 10 minutos para um nó GPU se tornar agendável. Use classes de prioridade de pod para que pods de inferência críticos sejam agendados primeiro, e considere sobreprovisionar um nó durante horários de pico.

Controles de custo

Computação GPU é o maior fator de custo em cargas de trabalho AI. Cada otimização aqui tem um impacto direto em dinheiro.

Instâncias spot para inferência em lote

Use pools GPU spot para qualquer carga de trabalho que tolere interrupção: scoring em lote, avaliação de modelo, geração de embeddings offline. VMs GPU spot custam de 60 a 90% menos que sob demanda.

Instâncias reservadas para estado estável

Se você executa inferência em produção 24/7, compre uma reserva de 1 ou 3 anos. A economia varia de 30 a 60% em relação ao pay-as-you-go.

Parar/iniciar cluster para dev/test

Pare clusters GPU quando não estiverem em uso. Um único Standard_NC6s_v3 custa aproximadamente $2.700/mês. Parar fora do horário de trabalho economiza até 65%.

# Pare o cluster (desaloca todos os nós)
az aks stop --resource-group myResourceGroup --name myDevGPUCluster

# Inicie o cluster
az aks start --resource-group myResourceGroup --name myDevGPUCluster

Dimensionamento correto de SKUs GPU

Não use uma A100 para servir um modelo de 7B parâmetros. Combine a GPU com o tamanho do modelo.

Tamanho do modeloGPU recomendadaVRAM necessária
< 3B parâmetrosT4 (16 GB)6-8 GB
7-8B parâmetrosT4 (16 GB) ou A10 (24 GB)14-16 GB
13B parâmetrosA10 (24 GB)24 GB
30-34B parâmetrosA100 (80 GB)60-70 GB
70B+ parâmetros2x A100 ou H100140+ GB
aviso

Modelos quantizados (GPTQ, AWQ, GGUF) usam significativamente menos VRAM. Um modelo de 70B quantizado para 4-bit cabe em uma única A100. Sempre verifique os tamanhos de modelos quantizados antes de selecionar seu SKU GPU.

Alertas de orçamento

Configure alertas de orçamento no resource group que contém os nós GPU. Gastos com GPU escalam rapidamente se o autoscaling estiver mal configurado.

Serving multi-modelo

Multiplexação de modelos em uma única GPU

vLLM suporta servir múltiplos adaptadores LoRA a partir de um único modelo base. Use isso para variantes fine-tuned do mesmo modelo base.

python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3-8B-Instruct \
--enable-lora \
--lora-modules customer-a=/models/lora-a customer-b=/models/lora-b \
--max-loras 4

Deployments separados por modelo

Quando modelos têm arquiteturas ou requisitos de GPU diferentes, implante-os como deployments Kubernetes separados com políticas de escalabilidade independentes.

Roteamento A/B de modelos via ingress

Use regras de ingress para rotear tráfego entre versões de modelos para deployments canary e rollouts graduais. Defina nginx.ingress.kubernetes.io/canary-weight para controlar a divisão de tráfego entre versões de modelos.

Erros comuns

ErroPor que prejudicaCorreção
SKUs GPU superdimensionadosPagando por VRAM que você não usaProfile o uso de memória do modelo, escolha o menor SKU que serve
Sem autoscaling em pools GPUGPUs ociosas custam o mesmo que ocupadasUse KEDA com scale-to-zero para cargas de trabalho não críticas
Carregando modelos da internet na inicializaçãoAdiciona de 5 a 15 minutos a cada start de podFaça cache de modelos no Azure Files NFS ou NVMe local
Sem taints em node pools GPUCargas de trabalho CPU vão para nós GPUAplique taint em todos os pools GPU com sku=gpu:NoSchedule
GPU ociosa durante baixo tráfegoDesperdiçando dinheiro com GPUs ligadas sem requisiçõesScale-to-zero com KEDA ou pare clusters de dev
Embutindo modelos grandes em imagens de containerPulls de imagem lentos, custos altos de registroUse montagens de volume com armazenamento compartilhado
Réplica única sem health checksUm crash derruba a inferênciaExecute pelo menos 2 réplicas com probes de liveness e readiness

Recursos