(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como fazer deploy canário em Kubernetes com GitHub Actions: passo a passo

João Barros 10 de September de 2026 4 min de leitura

Este tutorial mostra como fazer um deploy canário em Kubernetes com GitHub Actions para implementar novas versões gradualmente e reduzir o risco. Explico por que o deploy canário é útil; de seguida detalho um fluxo concreto com manifestos Kubernetes, GitHub Actions e verificação simples.

Pré-requisitos

  • Conta no GitHub e repositório com o código da aplicação (ex.: imagem Docker pública ou registada).
  • Cluster Kubernetes acessível (minikube, kind ou cluster na cloud) com o kubectl configurado.
  • Runner do GitHub Actions com permissões para o kubectl (use secrets KUBECONFIG ou um token).
  • Conhecimentos básicos de Kubernetes: Deployment, Service e labels.

Passo 1: Preparar manifestos Kubernetes para suporte a canário

Crie um Deployment principal e prepare um Deployment separado para o canário. A ideia é ter dois Deployments (app-primary, app-canary) e um Service que balanceie por label. Assim conseguimos controlar o tráfego para o canário alterando réplicas ou weights no Ingress/Service.

# deployment-primary.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-primary
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      role: primary
  template:
    metadata:
      labels:
        app: myapp
        role: primary
    spec:
      containers:
      - name: myapp
        image: myrepo/myapp:stable
        ports:
        - containerPort: 80

# deployment-canary.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
      role: canary
  template:
    metadata:
      labels:
        app: myapp
        role: canary
    spec:
      containers:
      - name: myapp
        image: myrepo/myapp:canary
        ports:
        - containerPort: 80

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
spec:
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 80
  type: ClusterIP

Passo 2: Configurar GitHub Actions para criar imagem e fazer deploy canário

Crie um workflow que constrói a imagem canary, faz push para o registry e aplica os manifestos ao cluster. Use um job que actualiza apenas o Deployment canary para a nova tag; assim o primary mantém a versão estável.

# .github/workflows/canary-deploy.yaml
name: Canary Deploy
on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v2
    - name: Build and push image
      uses: docker/build-push-action@v4
      with:
        push: true
        tags: myrepo/myapp:${{ github.sha }}
        # configure registry credentials via secrets
    - name: Configure kubectl
      run: |
        echo "$KUBECONFIG" > kubeconfig
        export KUBECONFIG=$PWD/kubeconfig
      env:
        KUBECONFIG: ${{ secrets.KUBECONFIG }}
    - name: Update canary deployment image
      run: |
        kubectl set image deployment/app-canary myapp=myrepo/myapp:${{ github.sha }}
        kubectl rollout status deployment/app-canary --timeout=60s

Passo 3: Gradualmente aumentar o tráfego para o canário

Há várias formas de aumentar o tráfego: aumentar as réplicas do canário, usar Ingress/Service com weights (ex.: Istio, Traefik) ou manipular selectors. Aqui mostramos a forma simples: aumentar as réplicas do canário e, mais tarde, reduzir as do primary.

# scale-canary.sh  (executar via GitHub Action ou manualmente)
kubectl scale deployment/app-canary --replicas=2
# após verificação
kubectl scale deployment/app-primary --replicas=2
# finalmente promover o canário para primary alterando images e restaurando réplicas
kubectl set image deployment/app-primary myapp=myrepo/myapp:${CANARY_TAG}
kubectl scale deployment/app-canary --replicas=0
kubectl scale deployment/app-primary --replicas=3

Passo 4: Monitorização e rollback automático

Configure health checks liveness/readiness e use um script simples para verificar métricas (erros, latência) ou o estado de readiness. No exemplo abaixo, um passo do workflow verifica endpoints e faz rollback se a taxa de erro subir.

# exemplo simplificado de verificação via curl
STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://myapp-svc/health)
if [ "$STATUS" != "200" ]; then
  kubectl set image deployment/app-canary myapp=myrepo/myapp:stable
  kubectl rollout status deployment/app-canary --timeout=60s
  exit 1
fi

Verificar o resultado

Confirme que o canário está a correr a nova imagem e a servir tráfego apenas para parte dos utilizadores. Use kubectl para inspecionar:

kubectl get deployments
kubectl get pods -l role=canary -o wide
kubectl describe deployment app-canary
kubectl logs deployment/app-canary --tail=50

Se usar um Ingress ou Service com weight, verifique métricas no controlador de Ingress ou nas ferramentas de observabilidade (Prometheus/Grafana). Teste endpoints e confirme que o rollback funciona simulando falhas.

Conclusão

O deploy canário em Kubernetes com GitHub Actions permite reduzir o risco de releases, controlando gradualmente o tráfego. Próximos passos: integrar Istio/Linkerd para traffic shifting por weight, automatizar métricas com Prometheus e criar gates automáticos no workflow. Dica: comece com réplicas e health checks simples antes de introduzir um service mesh — qual é a maior preocupação que pretende mitigar com canários?