Blue-green deployment scripting
Conceitos Fundamentais do Blue-Green Deployment
Blue-green deployment é uma estratégia de release que mantém dois ambientes de produção idênticos, chamados convencionalmente de "blue" e "green". Apenas um deles recebe tráfego de produção ativo por vez. Quando uma nova versão da aplicação precisa ser implantada, ela é colocada no ambiente inativo, testada e, se aprovada, o roteador ou balanceador de carga comuta o tráfego para esse novo ambiente.
O principal benefício dessa abordagem é a redução drástica do downtime — a comutação é praticamente instantânea. Além disso, o rollback se torna trivial: basta reverter o tráfego para o ambiente anterior, que ainda contém a versão estável. Em termos de arquitetura, o balanceador de carga (como Nginx, HAProxy ou um cloud load balancer) é o ponto central de decisão, pois direciona as requisições para o ambiente ativo.
Estrutura de Diretórios e Versionamento de Ambientes
Para implementar blue-green deployment com scripts Bash, a organização do sistema de arquivos é fundamental. Adotaremos a seguinte estrutura:
/deploy/
├── blue/
│ ├── app/ # Código da aplicação
│ ├── config/ # Configurações específicas
│ └── version.txt # Versão implantada
├── green/
│ ├── app/
│ ├── config/
│ └── version.txt
└── state/
└── active.env # Arquivo contendo "blue" ou "green"
O arquivo /deploy/state/active.env armazena o ambiente atualmente em produção. Um script simples de leitura desse estado permite que qualquer processo no servidor saiba para onde o tráfego está sendo direcionado.
#!/bin/bash
# read_active_env.sh
ACTIVE_ENV=$(cat /deploy/state/active.env)
echo "Ambiente ativo: $ACTIVE_ENV"
Script de Preparação e Sincronização de Artefatos
O primeiro passo de um deploy é preparar o ambiente inativo com a nova versão. O script abaixo identifica qual ambiente está inativo, copia os artefatos e valida a integridade via checksum.
#!/bin/bash
# prepare_deploy.sh
set -euo pipefail
ARTIFACT_DIR="/deploy"
REPO_URL="https://github.com/empresa/app.git"
COMMIT_HASH="${1:-main}"
# Determinar ambiente inativo
ACTIVE_ENV=$(cat $ARTIFACT_DIR/state/active.env)
if [ "$ACTIVE_ENV" == "blue" ]; then
TARGET_ENV="green"
else
TARGET_ENV="blue"
fi
echo "Preparando deploy no ambiente: $TARGET_ENV"
# Clonar repositório no ambiente alvo
rm -rf $ARTIFACT_DIR/$TARGET_ENV/app
git clone --depth 1 --branch $COMMIT_HASH $REPO_URL $ARTIFACT_DIR/$TARGET_ENV/app
# Gerar e validar checksum
cd $ARTIFACT_DIR/$TARGET_ENV/app
find . -type f -exec sha256sum {} \; > ../checksums.txt
# Instalar dependências
npm install --production # Exemplo para Node.js
# ou: pip install -r requirements.txt # Para Python
# Ajustar permissões
chmod -R 755 $ARTIFACT_DIR/$TARGET_ENV/app
# Registrar versão
echo $COMMIT_HASH > $ARTIFACT_DIR/$TARGET_ENV/version.txt
echo "Preparação concluída para $TARGET_ENV"
Lógica de Comutação (Switch) Entre Ambientes
A comutação é o momento crítico do deploy. O script abaixo lê o estado atual, valida a saúde do novo ambiente e, se tudo estiver correto, atualiza o balanceador de carga.
#!/bin/bash
# switch_deploy.sh
set -euo pipefail
ARTIFACT_DIR="/deploy"
ACTIVE_ENV=$(cat $ARTIFACT_DIR/state/active.env)
if [ "$ACTIVE_ENV" == "blue" ]; then
NEW_ENV="green"
OLD_ENV="blue"
else
NEW_ENV="blue"
OLD_ENV="green"
fi
echo "Comutando de $OLD_ENV para $NEW_ENV"
# Validar saúde do novo ambiente
if ! /usr/local/bin/health_check.sh $NEW_ENV; then
echo "ERRO: Health check falhou para $NEW_ENV. Abortando switch."
exit 1
fi
# Atualizar configuração do Nginx (exemplo)
sed -i "s/proxy_pass http:\/\/$OLD_ENV;/proxy_pass http:\/\/$NEW_ENV;/g" /etc/nginx/sites-enabled/app.conf
nginx -s reload
# Atualizar estado
echo $NEW_ENV > $ARTIFACT_DIR/state/active.env
echo "Switch concluído. Ambiente ativo: $NEW_ENV"
Health Checks e Validação Pós-Deploy
Health checks são a garantia de que o novo ambiente está funcionando antes de receber tráfego. O script abaixo implementa verificações com timeout e retry.
#!/bin/bash
# health_check.sh
set -euo pipefail
TARGET_ENV="${1:-green}"
MAX_RETRIES=5
TIMEOUT=10
SLEEP_INTERVAL=3
echo "Executando health check para ambiente: $TARGET_ENV"
# Configurar porta baseada no ambiente
if [ "$TARGET_ENV" == "blue" ]; then
PORT=3001
else
PORT=3002
fi
for i in $(seq 1 $MAX_RETRIES); do
# Teste de conectividade básica
if curl -s --connect-timeout $TIMEOUT http://localhost:$PORT/health | grep -q '"status":"ok"'; then
echo "Health check passou na tentativa $i"
exit 0
fi
# Teste de endpoint crítico
if curl -s --connect-timeout $TIMEOUT http://localhost:$PORT/api/v1/status | grep -q '"db":"connected"'; then
echo "Banco de dados conectado na tentativa $i"
exit 0
fi
echo "Tentativa $i falhou. Aguardando $SLEEP_INTERVAL segundos..."
sleep $SLEEP_INTERVAL
done
echo "ERRO: Health check falhou após $MAX_RETRIES tentativas"
exit 1
Rollback Automatizado e Gerenciamento de Falhas
Quando o health check falha, o rollback deve ser automático. O script abaixo detecta a falha e reverte para o ambiente anterior.
#!/bin/bash
# rollback.sh
set -euo pipefail
ARTIFACT_DIR="/deploy"
ACTIVE_ENV=$(cat $ARTIFACT_DIR/state/active.env)
if [ "$ACTIVE_ENV" == "blue" ]; then
ROLLBACK_ENV="green"
else
ROLLBACK_ENV="blue"
fi
echo "INICIANDO ROLLBACK para $ROLLBACK_ENV"
# Reverter configuração do Nginx
sed -i "s/proxy_pass http:\/\/$ACTIVE_ENV;/proxy_pass http:\/\/$ROLLBACK_ENV;/g" /etc/nginx/sites-enabled/app.conf
nginx -s reload
# Atualizar estado
echo $ROLLBACK_ENV > $ARTIFACT_DIR/state/active.env
# Notificar falha (exemplo com Slack)
curl -X POST -H "Content-type: application/json" \
--data "{\"text\":\"🚨 Rollback executado: deploy em $ACTIVE_ENV falhou, revertido para $ROLLBACK_ENV\"}" \
https://hooks.slack.com/services/TOKEN
echo "Rollback concluído. Ambiente ativo: $ROLLBACK_ENV"
logger -t deploy "Rollback automático: $ACTIVE_ENV -> $ROLLBACK_ENV"
Integração com Ferramentas de CI/CD e Logging
Para integrar com pipelines CI/CD, os scripts bash podem ser chamados diretamente. Abaixo, um exemplo de pipeline para GitHub Actions:
name: Blue-Green Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Preparar deploy
run: |
ssh deploy@servidor "bash /deploy/scripts/prepare_deploy.sh ${{ github.sha }}"
- name: Executar health check
run: |
ssh deploy@servidor "bash /deploy/scripts/health_check.sh green"
- name: Comutar tráfego
run: |
ssh deploy@servidor "bash /deploy/scripts/switch_deploy.sh"
Para logging estruturado, cada script deve gerar saída no formato JSON para facilitar a auditoria:
#!/bin/bash
# Exemplo de log estruturado
LOG='{"timestamp":"'"$(date -u +"%Y-%m-%dT%H:%M:%SZ")"'","action":"deploy","environment":"green","status":"success","version":"v2.1.0"}'
echo $LOG >> /var/log/deployments.log
A rotação de logs pode ser configurada com logrotate:
/var/log/deployments.log {
daily
rotate 30
compress
missingok
notifempty
}
O cleanup de artefatos antigos garante que o ambiente inativo não acumule versões desnecessárias:
#!/bin/bash
# cleanup.sh
ARTIFACT_DIR="/deploy"
ACTIVE_ENV=$(cat $ARTIFACT_DIR/state/active.env)
if [ "$ACTIVE_ENV" == "blue" ]; then
CLEAN_ENV="green"
else
CLEAN_ENV="blue"
fi
# Remover versões antigas, mantendo apenas a atual
find $ARTIFACT_DIR/$CLEAN_ENV -mindepth 1 -maxdepth 1 ! -name "current" -exec rm -rf {} \;
echo "Cleanup concluído para $CLEAN_ENV"
Este conjunto de scripts forma uma base sólida para implementar blue-green deployment com Bash. A simplicidade dos scripts permite fácil manutenção e adaptação a diferentes stacks tecnológicas, mantendo os benefícios fundamentais: zero downtime durante deploys e rollback instantâneo em caso de falhas.
Referências
- Martin Fowler: BlueGreenDeployment — Artigo seminal que define o conceito de blue-green deployment e suas vantagens
- NGINX Blog: Blue-Green Deployment — Guia prático de implementação com NGINX como balanceador de carga
- GitHub Docs: Deploying with GitHub Actions — Documentação oficial sobre pipelines de deploy com GitHub Actions
- AWS Whitepaper: Blue/Green Deployments — Práticas recomendadas para blue/green deployments em infraestrutura cloud
- DigitalOcean Tutorial: Blue-Green Deployment — Tutorial prático com exemplos de scripts bash para deploy
- HashiCorp Learn: Consul Blue-Green Deployments — Implementação de blue-green deployment usando Consul para service discovery
- Stack Overflow: Bash Scripting Best Practices — Discussão sobre boas práticas de script bash, incluindo tratamento de erros e logging