Pular para o conteúdo

Deploy canário automatizado

Avançado18 min de leituracicd

Canário manual é alguém olhando o painel e decidindo. Canário automatizado é o controlador comparando métrica contra limiar e abortando sozinho quando a nova versão piora. Este guia monta o segundo com Argo Rollouts e Prometheus.

Pré-requisitos honestos: métricas de sintoma já expostas pelo serviço (taxa de erro e latência por versão), Prometheus coletando, e reversão testada. Sem isso, o canário automatiza uma decisão que você não consegue tomar.

Janela do terminal
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f \
https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
kubectl argo rollouts version # plugin do kubectl, útil para acompanhar

O Rollout substitui o Deployment — o spec.template é o mesmo, o que muda é a estratégia.

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata: { name: loja, namespace: prod }
spec:
replicas: 10
selector: { matchLabels: { app: loja } }
template:
metadata: { labels: { app: loja } }
spec:
containers:
- name: loja
image: registry.exemplo.com/loja@sha256:SUBSTITUA_PELO_DIGEST
ports: [{ containerPort: 8080 }]
readinessProbe: { httpGet: { path: /readyz, port: 8080 } }
strategy:
canary:
canaryService: loja-canario # Services que o controlador gerencia
stableService: loja-estavel
trafficRouting:
nginx: { stableIngress: loja } # ou istio, gateway API, alb...
steps:
- setWeight: 5
- pause: { duration: 5m } # tempo para a análise coletar dados
- setWeight: 25
- pause: { duration: 10m }
- setWeight: 50
- pause: { duration: 10m }
- setWeight: 100

Comece conservador: 5% por cinco minutos já expõe o problema em serviços com tráfego razoável. Se o volume for baixo, aumente a duração — porcentagem pequena de pouco tráfego não gera amostra suficiente para nenhuma análise.

O AnalysisTemplate é o que transforma o canário em decisão automática.

apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata: { name: saude-canario, namespace: prod }
spec:
args: [{ name: service-name }]
metrics:
- name: taxa-de-sucesso
interval: 1m
count: 5 # 5 medições antes de concluir
successCondition: result[0] >= 0.99
failureLimit: 1 # 1 medição ruim já aborta
provider:
prometheus:
address: http://prometheus.observabilidade:9090
query: |
sum(rate(http_requests_total{service="{{args.service-name}}",
version="canary", status!~"5.."}[2m]))
/
sum(rate(http_requests_total{service="{{args.service-name}}",
version="canary"}[2m]))
- name: latencia-p95
interval: 1m
count: 5
successCondition: result[0] <= 0.8
failureLimit: 1
provider:
prometheus:
address: http://prometheus.observabilidade:9090
query: |
histogram_quantile(0.95, sum by (le) (
rate(http_request_duration_seconds_bucket{service="{{args.service-name}}",
version="canary"}[2m])))

Detalhe que decide o sucesso do arranjo: a métrica precisa distinguir canário de estável. Sem o label de versão, você compara a nova versão com a média de tudo e o sinal some no ruído.

Ligue a análise em background, para valer durante todos os passos:

strategy:
canary:
analysis:
templates: [{ templateName: saude-canario }]
args: [{ name: service-name, value: loja }]
startingStep: 1 # começa depois do primeiro setWeight
Janela do terminal
kubectl argo rollouts get rollout loja -n prod --watch
kubectl argo rollouts promote loja -n prod # avança um passo manualmente
kubectl argo rollouts abort loja -n prod # volta tudo para a versão estável
kubectl argo rollouts undo loja -n prod # reverte para a revisão anterior

Um canário abortado deixa o tráfego 100% na versão estável e o Rollout em estado Degraded — ele não volta sozinho para a versão nova. Isso é proposital: alguém precisa olhar antes de tentar de novo.

Canário que nunca abortou é hipótese. Antes de confiar, force o abort em homologação:

Janela do terminal
# publique uma versão que devolve 500 em ~10% das requisições
kubectl argo rollouts set image loja loja=registry.exemplo.com/loja:versao-com-falha -n prod
kubectl argo rollouts get rollout loja -n prod --watch

O que você quer observar: a análise reprova em poucos minutos, o tráfego volta para a estável, e a notificação chega ao canal do time. Se algum dos três não acontecer, ajuste antes de usar em produção.

Sintoma Causa provável
Análise sempre Inconclusive Consulta sem dados — label de versão ausente ou serviço sem tráfego
Canário nunca aborta failureLimit alto demais, ou consulta agregando estável junto
Aborta sempre no primeiro passo Peso pequeno demais para o volume; aumente duração ou peso inicial
Tráfego não divide trafficRouting incompatível com o ingress instalado
Divisão de tráfego desigual em gRPC Conexões longas: precisa de roteamento L7 ou mesh
  • Métricas separam canário de estável por label de versão.
  • Passos e pausas dimensionados para o volume real do serviço.
  • Análise em background, com limiar ligado ao SLO.
  • Abort testado com falha induzida.
  • Notificação de progresso e de abort no canal do time.
  • Runbook de plantão diz o que fazer com um rollout Degraded.