Canary deploy com GitHub Actions em Kubernetes usando Helm e Flagger
Por John Pires · 19 de março de 2026

Canary deploy com GitHub Actions em Kubernetes usando Helm e Flagger
1) Motivacao e trade-offs
Canary deploy reduz risco ao liberar versões incrementais para uma fração do tráfego, permitindo validar métricas reais antes de promoção ampla. Para equipes com 1-3 anos de experiência, implementar Canary com Helm, Flagger e GitHub Actions entrega automação, reprodutibilidade e rollback automático com base em métricas. Porém existem trade-offs:
Menor blast radius vs. maior complexidade operacional. Flagger e Istio/Contour/NGINX adicionam componentes e configuração; pipelines mais longos e observabilidade são obrigatórios. As decisões de rede, métricas e testes determinam se o canary realmente reduz falhas em produção.
Outra troca: rapidez de deploy vs. custo de infra e latência de decisões. Analisar recursos (CPU/mem), tempos de inicialização e tolerância a erros é essencial. Sem métricas corretas, o canary vira apenas roteamento parcial sem proteção real.
Use canary quando você precisa validar mudanças que não são cobertas por testes locais (por exemplo: performance, integração com terceiros, configurações de runtime). Evite canary para deploys triviais com transações idempotentes irrelevantes ao usuário.
Quando usar canary
Use canary para mudanças que impactam disponibilidade, latência, comportamentos estatísticos (caches, circuit-breakers), ou integridade de dados. Não use canary como substituto para testes unitários e de integração; use em conjunto com esses testes.
Principais trade-offs
- Complexidade: mais entes (istio/flagger/prometheus) a gerenciar.
- Observabilidade: requisito mínimo — sem métricas apropriadas, canary falha.
- Automação: pipelines precisam orquestrar imagens, Helm upgrades e monitorar Flagger.
Tip: Não adote canary por modismo. Avalie custo operacional e maturidade do time em deploys e monitoramento.
2) Fundamentos tecnicos
Arquitetura típica: GitHub Actions constrói a imagem, publica no registry, atualiza o chart Helm (ou executa helm upgrade) e aplica a nova imagem ao Kubernetes. Flagger observa o Kubernetes e o serviço mesh / ingress controller para manipular tráfego progressivo. Prometheus fornece métricas, e Alertmanager ou hooks personalizados podem disparar rollbacks.
Componentes envolvidos:
- GitHub Actions — CI/CD para build e deploy.
- Helm — package e values para parametrizar imagem e recursos.
- Flagger — CRDs Canary/AnalysisTemplate para controlar rollouts.
- Service mesh ou ingress (Istio, Contour, NGINX): roteamento canário.
- Prometheus — métricas (latência, erro, saturação).
O fluxo básico é: Actions → Registry → Helm upgrade (nova imagem tag) → Flagger detecta alteração na Deployment → Flagger cria/trabalha com recurso de tráfego (VirtualService/Ingress) → análise de métricas → promoção ou rollback.
Como Flagger funciona
Flagger monitora mudanças no Deployment alvo. Quando detecta uma nova imagem, ele cria um Canary custom resource e convoca o controller para ajustar pesos de tráfego entre stable e canary. Flagger executa checks configurados (Prometheus queries, webhooks, etc.) em cada etapa e decide subir percentual ou reverter.
Integração com Helm
Helm gerencia as versões do manifesto. A prática recomendada é deixar a imagem parametrizada via values.yaml e disparar um helm upgrade --install com o novo tag. Flagger deve ser capaz de observar Deployments gerados pelo Helm. Em pipelines Idempotentes, use helm diff para prever mudanças e garantir infra como código.
3) Exemplo 1: caso simples
Caso: serviço web stateless chamado web-api. Objetivo: deploy canário de 10% → 50% → 100% com rollback automático se taxa de erro > 1% ou latência p95 > 500ms.
Contexto da infraestrutura
Kubernetes com NGINX Ingress Controller, Prometheus operando e Flagger instalado. Helm charts já configurados para web-api com values.yaml parametrizável.
Padrão de pipeline (GitHub Actions)
Antes do código, explique: este workflow faz build, push para registry (GHCR ou DockerHub), atualiza Helm usando helm upgrade com --set image.tag e espera Flagger executar o canary.
O bloco abaixo é o arquivo .github/workflows/canary.yml. Ele foca em build/push e helm upgrade. Ajuste segredos: DOCKER_USERNAME, DOCKER_PASSWORD, KUBE_CONFIG_DATA.
# .github/workflows/canary.yml
name: canary-deploy
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ghcr.io/myorg/web-api:${{ github.sha }}
- name: Setup kubectl
uses: azure/setup-kubectl@v3
with:
version: '1.28.0'
- name: Configure Kubeconfig
run: |
echo "${{ secrets.KUBE_CONFIG_DATA }}" | base64 -d > kubeconfig
export KUBECONFIG=$PWD/kubeconfig
- name: Helm upgrade
uses: azure/helm@v1
with:
command: upgrade
chart-type: file
chart-path: ./charts/web-api
release-name: web-api
namespace: production
args: --install --atomic --set image.tag=${{ github.sha }}
O que esse workflow faz: builda imagem, publica no registry e faz helm upgrade. Depois do helm upgrade, Flagger detecta o novo Deployment e inicia a sequência canária. O step --atomic ajuda a garantir que helm rollback ocorra se helm falhar.
Resultado esperado: novo canary é criado; Flagger controla pesos e realiza validações via Prometheus; se métricas passarem, o canary é promovido para stable.
Exemplo de Canary CRD mínimo
Este Canary custom resource indica os checks básicos. Coloque o arquivo canary.yaml no chart templates ou aplique separadamente.
# canary.yaml
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: web-api
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
service:
port: 80
progressDeadlineSeconds: 600
analysis:
interval: 1m
threshold: 5
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
threshold: 99
interval: 1m
- name: request-duration
threshold: 500
interval: 30s
O que esse CRD faz: define a política de rollout. Flagger usará as métricas configuradas para decidir subir o tráfego. maxWeight define o máximo antes da promoção final; stepWeight o incremento por ciclo.
4) Exemplo 2: caso avancado do mundo real
Contexto: microserviço com dependências externas (fila, cache e terceiros), múltiplas equipes e SLAs rígidos. Requer canary com validação de integridade de negócio (synthetic tests), canary em múltiplas regiões e rollout baseado em SLO.
Arquitetura e requisitos
Requisitos práticos:
- Executar testes sintéticos (end-to-end básicos) contra canary antes de aumentar peso.
- Verificar métricas customizadas: taxa de erros de integração com terceiros e latência da fila.
- Implantar canary por região/cluster e coordenar promoção global.
Padrão de implementação
Estratégia recomendada:
- Pipeline faz build/push da imagem e atualiza Helm com image.tag.
- Flagger inicia canary. Primeiro passo: health checks e readiness.
- Executa analysis com métricas Prometheus e um webhook que dispara testes sintéticos contra a URL canary.
- Se todos os checks passarem, Flagger incrementa tráfego; se falhar, rollback automático e notificação.
Exemplo de AnalysisTemplate com webhook sintético abaixo.
# analysis-template.yaml
apiVersion: flagger.app/v1beta1
kind: AnalysisTemplate
metadata:
name: synthetic-e2e
namespace: production
spec:
metrics:
- name: e2e-test
provider:
type: web
url: http://{{.ServiceName}}.production.svc.cluster.local/health/e2e
timeout: 5s
threshold: 1
interval: 30s
initialDelay: 10s
O que acontece: Flagger ataca o endpoint /health/e2e no pod canary. Se a resposta for OK dentro do timeout, métrica conta como sucesso. Combine com Prometheus para métricas de latência e erro para decisão final.
Para multinúmeros/regiões, mantenha pipelines separados e coordene a promoção via tag de imagem e um job central que aguarda todos os clusters confirmarem promoção. Evite tentar sincronizar tráfego global via Flagger — prefira coordenação por CI.
5) Debugging e troubleshooting
Erros no fluxo canário costumam se originar de problemas em métricas, readiness probes, roteamento ou permissões. Abaixo listamos técnicas práticas para diagnosticar e corrigir.
Logs e eventos
Verifique logs do Flagger e eventos do namespace. Flagger registra decisões e motivos de rollback. Use kubectl -n production logs deploy/flagger e kubectl describe canary web-api -n production para obter contexto.
Métricas e queries Prometheus
Verifique as queries configuradas no Canary CRD. Erros comuns: queries retornam null ou taxa baseada em metrics-server incorreta. Teste queries manualmente no Prometheus UI antes de confiar no canary.
Erros comuns e armadilhas
Listagem de problemas frequentes e soluções práticas:
- Mismatch nas labels: Flagger não encontra pods porque targetRef não corresponde ao selector do deployment. Solução: alinhar names/labels no Deployment e Canary.
- Readiness too long: Pods do canary demoram e atrapalham passo de análise. Ajuste readinessProbe e initialDelay na análise.
- Métricas insuficientes: Queries mal definidas geram falso-positivo. Teste queries e configure intervals maiores para reduzir ruído.
- Ingress/VirtualService mal configurado: Roteamento entre stable e canary não muda. Verifique recursos de mesh e se Flagger tem permissão para editar VirtualService/Ingress.
- Rate-limits por CDN/terceiros: Tests sintéticos podem acionar limites. Use circuit-breakers e mocks onde possível.
Tip: Sempre reproduza uma análise manualmente. Se Flagger falha ao aplicar peso, faça um curl direto aos endpoints dos pods canary para validar comportamento.
Comandos úteis
Comandos rápidos que resolvem 80% dos problemas:
# verificar canary
kubectl -n production get canaries
kubectl -n production describe canary web-api
# logs do flagger
kubectl -n flagger-system logs deployment/flagger
# verificar virtualservice (istio) ou ingress
kubectl -n production get virtualservice
kubectl -n production describe virtualservice web-api
# testar promql
# abrir UI do prometheus e testar queries configuradas no canary
O que esses comandos fazem: ajudam a entender em que etapa o rollout está (pending, progressing, aborted), por que um rollback ocorreu e quais métricas falharam.
Conclusao pratico
Canary com GitHub Actions, Helm e Flagger é uma solução robusta para reduzir risco em deploys: automatiza rollout, integra validações reais e permite rollback automático. A chave é investir em métricas corretas, probes realistas e pipelines idempotentes.
Boas práticas resumidas:
- Parametrize imagens via Helm e use tags imutáveis (sha).
- Configure métricas Prometheus claras e testadas antes de confiar em rollouts automatizados.
- Use AnalysisTemplates para casos avançados (synthetic tests, webhooks).
- Monitore logs do Flagger e eventos do Kubernetes para troubleshooting.
Implementar canary exige setup inicial, mas paga dividendos via menor tempo de recuperação e menos impacto por regressões. Comece com um canary simples e evolua para análise sintética e multi-região conforme maturidade da equipe.
Se implementar, documente o processo no repositório (README) e crie playbooks de rollback e de investigação para reduzir MTTR quando algo falhar.
Assuntos: DevOps, Kubernetes, github-actions, helm, flagger
Leia também
Docker Buildx + GitHub Actions: publicar imagens multi-arch (ARM/x86) corretamente
Guia prático para publicar imagens Docker multi-arch (arm64/x86) usando Docker Buildx e GitHub Actions. Mostro o jeito errado, o certo, workflows, debug e…
Escanear imagens Docker no CI com Trivy e GitHub Actions — falhe por CVSS
Aprenda a escanear imagens Docker no CI com Trivy e GitHub Actions e a fazer o pipeline falhar quando uma vulnerabilidade atingir um limiar CVSS. Passo a…
GitHub Actions: build, testar em container e publicar imagem no GHCR
Pipeline prática: build de imagem Docker, executar testes no container carregado e publicar no GHCR usando GitHub Actions. Código e workflow para iniciar e…
GitHub Actions + OIDC: provisionar infraestrutura com Terraform sem credenciais
Aprenda a usar OIDC do GitHub Actions para provisionar infraestrutura com Terraform na AWS sem armazenar credenciais. Guia prático com Terraform, IAM…
Testes em CI com GitHub Actions e Docker Compose para Postgres e Redis
Aprenda a rodar testes de integração no CI usando GitHub Actions e Docker Compose com Postgres e Redis. Guia passo a passo para iniciantes: arquivos…
Validando assinaturas de imagens Docker no Kubernetes com cosign e OPA Gatekeeper
Guia prático para validar assinaturas de imagens Docker no Kubernetes usando cosign e OPA Gatekeeper: padrões, exemplos com CI (GitHub Actions)…