Blue-green deployment em sistemas distribuídos

1. Fundamentos do Blue-Green Deployment

1.1. Definição e objetivo

Blue-green deployment é uma estratégia de implantação que mantém dois ambientes de produção idênticos, chamados "blue" e "green". Apenas um ambiente recebe tráfego ativo por vez. O objetivo principal é eliminar downtime durante implantações e reduzir drasticamente os riscos associados a falhas em novas versões. Quando uma nova versão precisa ser implantada, ela é colocada no ambiente inativo, testada exaustivamente, e então o tráfego é comutado instantaneamente.

1.2. Comparação com outras estratégias

Estratégia Tempo de implantação Risco Complexidade
Rolling update Lento Médio Baixa
Canary release Controlado Baixo Alta
Blue-green Instantâneo Muito baixo Média
Feature toggle Imediato Baixo Alta (dívida técnica)

Diferente do rolling update, que atualiza nós gradualmente, o blue-green permite rollback imediato. Comparado ao canary release, não requer roteamento granular por usuário. Já os feature toggles podem coexistir com blue-green para desabilitar funcionalidades problemáticas sem nova implantação.

1.3. Pré-requisitos arquiteturais

Para implementar blue-green em sistemas distribuídos, são necessários:

  • Balanceadores de carga capazes de rotear 100% do tráfego para um ambiente
  • Ambientes isolados com infraestrutura duplicada (computação, rede, armazenamento)
  • Roteamento de tráfego gerenciado por DNS, load balancer ou service mesh
  • Estratégia de dados para lidar com estado compartilhado entre ambientes

2. Arquitetura de Ambientes Blue e Green

2.1. Infraestrutura duplicada

Cada ambiente deve ter sua própria infraestrutura completa:

Ambiente Blue (ativo):
  - 3 instâncias de API server (Kubernetes pods)
  - 2 instâncias de worker (processamento assíncrono)
  - 1 banco de dados PostgreSQL (primário)
  - 1 cache Redis
  - Load balancer interno (envio para blue)

Ambiente Green (inativo):
  - 3 instâncias de API server (nova versão)
  - 2 instâncias de worker (nova versão)
  - 1 banco de dados PostgreSQL (réplica)
  - 1 cache Redis (vazio ou populado)
  - Load balancer interno (envio para green, sem tráfego)

2.2. Sincronização de dados entre ambientes

A sincronização de banco de dados é o maior desafio. Estratégias comuns:

Replicação assíncrona (recomendada para leitura):

-- No ambiente ativo (blue):
CREATE PUBLICATION pub_blue FOR ALL TABLES;

-- No ambiente inativo (green):
CREATE SUBSCRIPTION sub_green 
CONNECTION 'host=blue-db port=5432 dbname=prod' 
PUBLICATION pub_blue;

Snapshots pré-comutação:

# Antes de comutar para green:
pg_dump -h blue-db -U admin prod_db > /snapshots/pre_switch_$(date +%Y%m%d_%H%M%S).sql

# Após comutação, se rollback for necessário:
psql -h blue-db -U admin prod_db < /snapshots/pre_switch_*.sql

2.3. Gerenciamento de configurações

Cada ambiente deve ter configurações específicas, gerenciadas por variáveis de ambiente ou sistemas de configuração centralizada:

# Ambiente Blue (produção ativa)
DATABASE_URL=postgres://user:pass@blue-db:5432/prod
REDIS_URL=redis://blue-cache:6379
API_VERSION=v2.1.0

# Ambiente Green (preparação)
DATABASE_URL=postgres://user:pass@green-db:5432/prod
REDIS_URL=redis://green-cache:6379
API_VERSION=v2.2.0

3. Estratégias de Roteamento e Comutação de Tráfego

3.1. Uso de balanceadores de carga

Exemplo com NGINX para alternar entre ambientes:

upstream backend_blue {
    server blue-api-1:8080;
    server blue-api-2:8080;
}

upstream backend_green {
    server green-api-1:8080;
    server green-api-2:8080;
}

server {
    listen 80;

    # Variável de controle (pode ser alterada via API ou arquivo)
    set $active_backend "blue";

    location / {
        if ($active_backend = "blue") {
            proxy_pass http://backend_blue;
        }
        if ($active_backend = "green") {
            proxy_pass http://backend_green;
        }
    }
}

3.2. Roteamento por DNS

Para comutação via DNS, ajuste o TTL para mínimo (60 segundos) e use registros do tipo A:

api.exemplo.com.  60  IN  A  203.0.113.10   # Blue (ativo)
api.exemplo.com.  60  IN  A  203.0.113.20   # Green (inativo, sem tráfego)

# Durante comutação, remova o registro do blue e mantenha apenas o green

3.3. Comutação gradual vs. instantânea

Instantânea: Todo tráfego muda de uma vez. Rápido, mas pode perder requisições em andamento.

Gradual: Percentual de tráfego é transferido aos poucos (ex: 10%, 50%, 100%). Reduz impacto, mas exige monitoramento contínuo.

# Exemplo de script para comutação gradual com HAProxy
for percent in 10 25 50 75 100; do
    echo "Redirecionando $percent% para green"
    # Atualizar configuração do HAProxy
    sed -i "s/weight blue [0-9]*/weight blue $((100 - $percent))/" haproxy.cfg
    sed -i "s/weight green [0-9]*/weight green $percent/" haproxy.cfg
    sleep 60  # Aguardar estabilização
done

4. Gerenciamento de Estado e Dados em Blue-Green

4.1. Desafios com bancos de dados compartilhados

O maior risco é a incompatibilidade de esquemas entre versões. Migrações devem ser retrocompatíveis:

-- Migração segura: adicionar coluna com valor padrão
ALTER TABLE usuarios ADD COLUMN plano VARCHAR(20) DEFAULT 'basico';

-- Migração perigosa: renomear coluna (quebra versão antiga)
ALTER TABLE usuarios RENAME COLUMN email TO email_contato;  -- EVITAR

4.2. Estratégias de sincronização

Blue-green de banco de dados: Cada ambiente tem seu próprio banco, com replicação bidirecional ou mestre-escravo:

# Configuração de replicação bidirecional (cuidado com conflitos)
-- No blue:
CREATE SUBSCRIPTION sub_blue_from_green 
CONNECTION 'host=green-db port=5432 dbname=prod' 
PUBLICATION pub_green;

-- No green:
CREATE SUBSCRIPTION sub_green_from_blue 
CONNECTION 'host=blue-db port=5432 dbname=prod' 
PUBLICATION pub_blue;

4.3. Tratamento de sessões de usuário

Sessões baseadas em sticky sessions no load balancer ou tokens JWT são mais seguras:

# Token JWT com claims de ambiente (opcional)
{
  "sub": "user123",
  "exp": 1700000000,
  "env": "blue",  # ambiente onde a sessão foi criada
  "iat": 1699996400
}

# Cache distribuído compartilhado (Redis externo a ambos ambientes)
# Ambos ambientes leem do mesmo Redis, mas apenas o ativo escreve

5. Processo de Implantação e Validação

5.1. Pipeline CI/CD

Pipeline típico para blue-green:

1. Build da imagem Docker (v2.2.0)
2. Push para registry
3. Deploy no ambiente inativo (green)
   kubectl apply -f k8s/green-deployment.yaml
4. Testes de smoke automatizados
   curl -f https://green-api.exemplo.com/health
5. Validação manual (opcional)
   - Acessar green via header X-Forward: green
6. Comutação de tráfego
   - Alterar DNS ou load balancer
7. Monitoramento pós-comutação (15 min)
8. Se ok: manter green ativo, blue como próximo alvo
   Se erro: rollback imediato

5.2. Verificação de saúde

Readiness probes no Kubernetes garantem que apenas pods saudáveis recebam tráfego:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-green
spec:
  template:
    spec:
      containers:
      - name: api
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 15

5.3. Estratégias de rollback

Rollback é simples: basta reverter o roteamento para o ambiente anterior:

# Rollback manual
kubectl rollout undo deployment/api-green  # Opcional
# Reverter DNS para blue
# Ou alterar load balancer para apontar para blue novamente

Para rollback de dados, utilize snapshots ou replicação reversa:

# Restaurar banco do snapshot pré-comutação
pg_restore -d prod_db /snapshots/pre_switch_20231001_120000.sql

6. Monitoramento e Observabilidade Durante a Transição

6.1. Métricas críticas

Monitore estas métricas antes, durante e após a comutação:

Métrica                | Limiar de alerta
-----------------------|------------------
Latência p95           | > 500ms
Taxa de erro HTTP 5xx  | > 1%
Throughput (req/s)     | Queda > 20%
Uso de CPU (pods)      | > 80%
Conexões de banco      | > 90% do pool

6.2. Logs e tracing distribuído

Compare logs entre ambientes usando correlação por trace ID:

# Log estruturado com ambiente
{
  "timestamp": "2023-10-01T12:00:00Z",
  "level": "ERROR",
  "service": "api",
  "environment": "green",
  "trace_id": "abc123",
  "message": "Timeout na conexão com banco",
  "duration_ms": 15000
}

6.3. Alertas automatizados

Configure alertas que disparam imediatamente após a comutação:

# Prometheus + Alertmanager
groups:
- name: blue-green
  rules:
  - alert: HighErrorRateAfterSwitch
    expr: |
      rate(http_requests_total{status=~"5..", environment="green"}[5m]) 
      / 
      rate(http_requests_total{environment="green"}[5m]) > 0.05
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "Taxa de erro alta no ambiente green após comutação"

7. Desafios e Padrões Avançados em Sistemas Distribuídos

7.1. Blue-green com microsserviços

Em sistemas com dezenas de microsserviços, a orquestração é complexa. Utilize service mesh (Istio, Linkerd) para roteamento:

# VirtualService no Istio para rotear tráfego
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: api-routing
spec:
  hosts:
  - api.exemplo.com
  http:
  - match:
    - headers:
        x-environment:
          exact: "green"
    route:
    - destination:
        host: api-green
        port:
          number: 8080
  - route:
    - destination:
        host: api-blue
        port:
          number: 8080

7.2. Problemas de consistência eventual

Transações distribuídas entre microsserviços exigem padrões como Saga ou Two-Phase Commit:

# Saga coreografada para pedido + pagamento
1. Serviço de pedidos (green) cria pedido PENDENTE
2. Serviço de pagamento (green) processa pagamento
3. Se pagamento OK: pedido CONFIRMADO
4. Se pagamento falha: pedido CANCELADO (compensação)

7.3. Chaos engineering durante troca de ambiente

Teste a resiliência injetando falhas durante a comutação:

# Injetar latência em 50% das requisições do green
kubectl run -i --tty chaos --image=chaosblade \
  -- blade create network delay --time 3000 \
  --interface eth0 --percent 50

# Monitorar se o sistema degrada graciosamente
# Se green falha, load balancer deve redirecionar para blue automaticamente

Conclusão

Blue-green deployment é uma estratégia poderosa para sistemas distribuídos que exigem alta disponibilidade e zero downtime. Sua implementação requer planejamento cuidadoso de infraestrutura, gerenciamento de estado e observabilidade. Quando combinado com boas práticas de CI/CD, monitoramento e chaos engineering, oferece uma das abordagens mais seguras para implantação de software em produção.

Referências