Rolling updates e rollbacks

1. Fundamentos de Rolling Updates no Kubernetes

Rolling update é a estratégia padrão do Kubernetes para atualizar aplicações sem interromper o serviço. O objetivo é substituir gradualmente os pods antigos por novos, mantendo a disponibilidade contínua. Diferente de estratégias como Recreate (que mata todos os pods antes de criar novos, causando downtime) ou Blue-Green (que exige o dobro de recursos), o rolling update opera de forma incremental, controlando quantos pods podem ficar indisponíveis ou exceder o número desejado.

O Deployment Controller gerencia esse processo através de ReplicaSets. Cada atualização gera um novo ReplicaSet, que escala gradualmente enquanto o anterior é reduzido. Isso permite rollback rápido e rastreabilidade.

2. Configurando Rolling Updates no Deployment

Os parâmetros fundamentais são maxSurge e maxUnavailable, definidos dentro de strategy.rollingUpdate:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-web
spec:
  replicas: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
  • maxSurge (padrão 25%): número máximo de pods extras que podem ser criados acima do desejado. maxSurge: 1 permite um pod adicional durante a atualização.
  • maxUnavailable (padrão 25%): número máximo de pods que podem ficar indisponíveis durante o processo. maxUnavailable: 0 garante que sempre haja 5 pods respondendo.

Valores percentuais são relativos ao replicas. Para 10 réplicas, maxSurge: 25% equivale a 2 pods extras (arredondado para cima). A escolha entre absoluto e percentual depende da escala: percentuais são mais flexíveis em ambientes dinâmicos.

3. Executando Rolling Updates na Prática

Atualização por comando direto:

kubectl set image deployment/app-web nginx=nginx:1.26

Atualização via manifesto atualizado:

kubectl apply -f deployment-atualizado.yaml

Monitoramento do progresso:

kubectl rollout status deployment/app-web
# Saída esperada:
# Waiting for rollout to finish: 2 of 5 updated replicas are available...
# deployment "app-web" successfully rolled out

kubectl describe deployment app-web
# Mostra Events como:
# Scaled up replica set app-web-7d4f8b5c6 to 3
# Scaled down replica set app-web-5f9c2a1d4 to 4

O Kubernetes cria automaticamente um novo ReplicaSet e escala incrementalmente. Durante o processo, o serviço continua respondendo, pois apenas pods saudáveis recebem tráfego.

4. Gerenciamento de Histórico e Revisões

O Deployment mantém um histórico de revisões, controlado por revisionHistoryLimit (padrão 10):

spec:
  revisionHistoryLimit: 5

Visualizando o histórico:

kubectl rollout history deployment/app-web
# REVISION  CHANGE-CAUSE
# 1         <none>
# 2         kubectl set image deployment/app-web nginx=nginx:1.26
# 3         kubectl apply --filename=deployment-v3.yaml

Para adicionar anotações de causa durante a atualização:

kubectl annotate deployment/app-web kubernetes.io/change-cause="Atualização de segurança nginx 1.26"

Isso é essencial para rastreabilidade em ambientes de produção, especialmente quando múltiplas equipes realizam deploys.

5. Estratégias de Rollback

Rollback para revisão anterior:

kubectl rollout undo deployment/app-web

Rollback para revisão específica:

kubectl rollout undo deployment/app-web --to-revision=2

Verificação pós-rollback:

kubectl rollout status deployment/app-web
kubectl get pods -l app=web
kubectl describe deployment/app-web | grep -A5 "Replicas"

O rollback reverte o Deployment para o ReplicaSet da revisão alvo, recriando pods com a imagem anterior. Health checks (readiness probe) garantem que apenas pods saudáveis entrem em serviço.

6. Boas Práticas e Troubleshooting

Definindo probes para evitar falhas em cascata:

spec:
  containers:
  - name: nginx
    image: nginx:1.26
    livenessProbe:
      httpGet:
        path: /healthz
        port: 80
      initialDelaySeconds: 10
      periodSeconds: 5
    readinessProbe:
      httpGet:
        path: /ready
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5

Problemas comuns:

  • Pods presos em CrashLoopBackOff: verificar logs com kubectl logs <pod> e ajustar probes ou imagem.
  • Quota de recursos insuficiente: kubectl describe quota revela limites excedidos.
  • Rolling update estagnado: kubectl rollout pause deployment/app-web interrompe o processo, kubectl rollout resume retoma.

Uso de pause/resume para canary controlado:

kubectl rollout pause deployment/app-web
# Verifica 2-3 pods atualizados manualmente
kubectl rollout resume deployment/app-web

7. Integração com CI/CD e Helm

Automatizando em pipelines GitOps (ArgoCD/Flux):

# Exemplo de pipeline GitHub Actions
- name: Deploy to Kubernetes
  run: |
    kubectl set image deployment/app-web nginx=nginx:${{ github.sha }}
    kubectl rollout status deployment/app-web --timeout=5m

Helm: comandos essenciais:

# Upgrade com rolling update
helm upgrade app-web ./chart --set image.tag=1.26 --atomic --wait --timeout=10m

# Rollback para revisão anterior
helm rollback app-web 1

# Visualizar histórico de releases
helm history app-web

Parâmetros como --atomic (reverte automaticamente em falha), --wait (aguarda todos os pods ficarem prontos) e --timeout (limite de tempo) tornam os deploys mais seguros em produção.

O rolling update é a base de estratégias avançadas como canary deployments e blue-green, sendo essencial para qualquer operação de Kubernetes em produção.

Referências