Em ambientes DevOps, a capacidade de reverter rapidamente uma implantação problemática é tão crucial quanto a própria implantação. Rollback e recuperação são práticas que garantem a resiliência do sistema, minimizando o impacto de falhas em produção. Nesta aula, exploraremos estratégias de rollback, versionamento de releases, automação e testes, fornecendo um guia completo para implementar recuperações eficientes e seguras.

Dominar essas técnicas é essencial para manter a disponibilidade e a confiança no ciclo de entrega contínua. Veremos como diferentes abordagens se adaptam a cenários distintos, desde aplicações monolíticas até microserviços, e como ferramentas como Kubernetes e pipelines CI/CD podem facilitar o processo.

Estratégias de rollback

Rollback é o processo de reverter uma aplicação para uma versão anterior, geralmente após a detecção de falhas ou regressões. As estratégias variam em complexidade e impacto no usuário, e a escolha depende do contexto da aplicação e da infraestrutura.

As abordagens mais comuns incluem:

  • Rollback de imagem: Reverter a imagem do contêiner para uma tag anterior, simples e direto, mas pode causar indisponibilidade momentânea.
  • Blue-Green: Manter dois ambientes idênticos (blue e green) e alternar o tráfego entre eles. Se a nova versão falhar, o tráfego é redirecionado para o ambiente anterior, com zero downtime.
  • Canário: Lançar a nova versão para uma pequena porcentagem de usuários e monitorar. Se houver problemas, o tráfego é revertido para a versão estável.
  • Rollback com banco de dados: Em casos de migrações de schema, é necessário reverter também as alterações no banco, o que pode exigir scripts de downgrade ou snapshots.

Exemplo de rollback de imagem em Kubernetes usando kubectl:

# Reverter para a versão anterior de um deployment
kubectl rollout undo deployment/my-app

# Reverter para uma revisão específica
kubectl rollout undo deployment/my-app --to-revision=3

# Ver histórico de revisões
kubectl rollout history deployment/my-app

Em pipelines CI/CD, ferramentas como Jenkins ou GitLab CI podem ter stages de rollback automáticos, acionados por falhas em testes ou monitoramento.

Versionamento de releases

Versionamento de releases é a prática de atribuir identificadores únicos a cada versão do software, permitindo rastreabilidade e rollback preciso. Sem um bom versionamento, é impossível saber exatamente qual código está em produção ou qual versão reverter.

Recomenda-se usar versionamento semântico (SemVer) no formato MAJOR.MINOR.PATCH, além de tags em repositórios Git e imagens de contêiner. Por exemplo, uma imagem pode ser taggeada como my-app:1.2.3 ou my-app:latest (embora latest seja desencorajado para produção).

Além disso, é importante manter um changelog ou registro de releases, documentando mudanças e possíveis impactos. Ferramentas como Helm, para Kubernetes, permitem versionar charts e fazer upgrade/rollback com comandos simples.

Exemplo de versionamento com Git e Docker:

# Criar uma tag no Git
git tag -a v1.2.3 -m "Release 1.2.3"

# Construir e taggear a imagem Docker
docker build -t my-app:1.2.3 .
docker push my-app:1.2.3

Em pipelines, o número da versão pode ser gerado automaticamente a partir do commit ou de um contador, garantindo unicidade.

Automatizando

Automatizar o rollback é fundamental para garantir respostas rápidas e consistentes. A automação pode ser implementada em várias camadas, desde scripts simples até integrações com orquestradores e ferramentas de monitoramento.

Em Kubernetes, o rollout nativo permite automação básica, mas para cenários mais complexos, usam-se operadores ou pipelines que monitoram métricas e disparam rollback automaticamente. Por exemplo, se a taxa de erros exceder um limite, um webhook pode acionar um rollback.

Exemplo de automação em um pipeline GitLab CI:

stages:
  - deploy
  - rollback

deploy:
  stage: deploy
  script:
    - kubectl set image deployment/my-app my-app=my-app:${CI_COMMIT_TAG}
    - kubectl rollout status deployment/my-app
  only:
    - tags

rollback:
  stage: rollback
  script:
    - kubectl rollout undo deployment/my-app
  when: on_failure
  only:
    - tags

Além disso, ferramentas como Argo Rollouts oferecem estratégias avançadas de deploy e rollback automático baseado em métricas, como análise de canário.

Testando rollback

Testar o rollback é tão importante quanto testar o deploy. Sem testes, um rollback pode falhar no momento crítico, causando indisponibilidade prolongada. Os testes devem verificar não apenas a reversão da aplicação, mas também a consistência dos dados e a integridade do sistema.

Práticas recomendadas incluem:

  • Testes em ambiente de staging: Simular falhas e executar rollback antes de ir para produção.
  • Testes de caos: Introduzir falhas deliberadamente para validar a resiliência.
  • Validação pós-rollback: Verificar se a aplicação está saudável e se os dados não foram corrompidos.
  • Automação de testes de rollback: Incluir no pipeline uma etapa que execute testes de rollback periodicamente.

Exemplo de script para testar rollback em um ambiente Kubernetes:

#!/bin/bash
# Simular falha: deletar um pod crítico
kubectl delete pod my-app-pod

# Aguardar o rollout undo automático
sleep 30

# Verificar se o deployment voltou à versão anterior
kubectl rollout status deployment/my-app

# Testar se a aplicação responde
curl -f http://my-app/health

Além disso, é importante documentar os procedimentos de rollback e treinar a equipe para executá-los manualmente se necessário.

Boas práticas e observações finais

Algumas boas práticas incluem: manter releases pequenas e frequentes para facilitar rollbacks, usar estratégias de deploy que minimizem o impacto (como blue-green), e sempre ter um plano de recuperação documentado. Lembre-se de que rollback não é uma solução para todos os problemas; em alguns casos, pode ser melhor corrigir o problema e avançar (rollforward). Avalie cada situação.

Referências

Exercícios

  1. Explique a diferença entre rollback de imagem e blue-green deployment, citando vantagens e desvantagens de cada um.

    ✓ Resposta: Rollback de imagem é reverter a imagem do contêiner para uma versão anterior, simples e rápido, mas pode causar downtime. Blue-green mantém dois ambientes idênticos e alterna o tráfego, permitindo rollback instantâneo sem downtime, mas requer mais recursos.
  2. Como o versionamento semântico auxilia no rollback? Dê um exemplo prático.

    ✓ Resposta: O versionamento semântico permite identificar exatamente qual versão está em produção e reverter para uma versão anterior conhecida. Por exemplo, se a versão 2.0.0 apresenta um bug, podemos reverter para a 1.9.0 usando a tag correspondente no repositório e na imagem Docker.
  3. Escreva um comando kubectl para reverter um deployment para a revisão 2 e verifique o histórico.

    ✓ Resposta:
    kubectl rollout undo deployment/my-app --to-revision=2
    kubectl rollout history deployment/my-app
  4. Descreva como você automatizaria um rollback em um pipeline CI/CD, citando uma ferramenta e um gatilho.

    ✓ Resposta: Em GitLab CI, posso adicionar um job de rollback que é acionado quando o job de deploy falha, usando a diretiva when: on_failure. O job executaria kubectl rollout undo deployment/my-app.
  5. Qual é a importância de testar rollback? Cite duas práticas para garantir que o rollback funcione.

    ✓ Resposta: Testar rollback garante que a reversão funcione em momentos de crise, evitando indisponibilidade prolongada. Práticas: realizar testes em staging e automatizar testes de rollback no pipeline, além de simular falhas com testes de caos.