Boas práticas de gerenciamento de configurações em produção

1. Fundamentos do gerenciamento de configurações

O gerenciamento de configurações em produção é o processo de controlar e manter as definições que determinam o comportamento de sistemas em ambiente produtivo. Sua importância reside no fato de que uma configuração incorreta pode causar indisponibilidade, falhas de segurança ou degradação de performance.

É essencial compreender a distinção entre três elementos fundamentais:

  • Código: lógica de negócio que raramente muda entre ambientes
  • Configuração: parâmetros que variam conforme o ambiente (URLs, portas, thresholds)
  • Dados: informações persistentes geradas pela aplicação

O princípio da separação entre código e configuração, estabelecido pelo manifesto 12 Factor App, determina que uma aplicação deve armazenar configurações externamente ao código-fonte. Isso permite modificar comportamentos sem recompilar ou redistribuir artefatos.

# Exemplo de separação inadequada (configuração embutida no código)
const dbHost = "localhost";
const dbPort = 5432;
const apiKey = "sk-abc123";

# Exemplo correto (configuração externa)
DB_HOST=localhost
DB_PORT=5432
API_KEY=${SECRET_API_KEY}

2. Estrutura e versionamento de configurações

Arquivos de configuração devem seguir formatos padronizados e hierárquicos. YAML é preferível para configurações complexas com aninhamento; JSON para integração com APIs; TOML para projetos que exigem simplicidade.

# config/production.yaml
server:
  host: "0.0.0.0"
  port: 8080
  cors:
    origins:
      - "https://app.exemplo.com"
      - "https://admin.exemplo.com"

database:
  pool:
    min: 5
    max: 20
    idle_timeout: 30000
  ssl:
    enabled: true
    ca_cert: "/etc/ssl/certs/ca.pem"

O versionamento de configurações com Git exige estratégias específicas:

  • Branches por ambiente: main para produção, staging para pré-produção
  • Pull requests obrigatórios: toda alteração de configuração deve passar por revisão
  • Commits atômicos: cada mudança deve ser isolada e descritiva
# Estratégia de branches para configurações
main/           # Configurações de produção
├── database.yaml
├── cache.yaml
└── secrets.enc.yaml

staging/        # Configurações de staging
├── database.yaml
├── cache.yaml
└── secrets.enc.yaml

3. Ambientes e variáveis de configuração

Cada ambiente (desenvolvimento, staging, produção) requer seu próprio conjunto de variáveis. O uso de arquivos .env é prática comum, mas requer cuidados de segurança.

# .env.production (NUNCA versionar este arquivo)
DB_HOST=db-prod.exemplo.com
DB_USER=app_prod
DB_PASSWORD=${SECRET_DB_PASSWORD}
REDIS_HOST=redis-prod.exemplo.com
API_RATE_LIMIT=100
LOG_LEVEL=warn

# .env.development (pode ser versionado com valores seguros)
DB_HOST=localhost
DB_USER=app_dev
DB_PASSWORD=dev_password
REDIS_HOST=localhost
API_RATE_LIMIT=1000
LOG_LEVEL=debug

Boas práticas de segurança incluem:

  • Defaults seguros: valores padrão que minimizam riscos
  • Override explícito: ambientes produtivos devem sobrescrever todos os defaults
  • Nunca versionar segredos: arquivos .env.production devem estar em .gitignore
# Implementação de defaults e override
def get_config():
    defaults = {
        "DB_HOST": "localhost",
        "DB_PORT": 5432,
        "LOG_LEVEL": "info"
    }

    # Carrega variáveis de ambiente (sobrescreve defaults)
    env_config = {
        key: os.environ.get(key, default)
        for key, default in defaults.items()
    }

    return env_config

4. Ferramentas de gerenciamento centralizado

Para sistemas distribuídos, ferramentas centralizadas de configuração oferecem vantagens significativas:

  • etcd: sistema de chave-valor consistente e altamente disponível
  • Consul: serviço de descoberta e configuração distribuída
  • ZooKeeper: coordenação distribuída com watchers

Serviços cloud como AWS Parameter Store e Azure App Configuration oferecem integração nativa com ecossistemas cloud.

# Exemplo de configuração dinâmica com Consul
consul kv put config/app/production/database/host db-prod.exemplo.com
consul kv put config/app/production/database/port 5432
consul kv put config/app/production/cache/ttl 3600

# Aplicação monitora mudanças
watch -n 30 consul kv get -recurse config/app/production/

A principal vantagem da configuração dinâmica é a capacidade de alterar parâmetros sem reinicializar serviços, permitindo ajustes em tempo real.

5. Segredos e dados sensíveis em produção

Dados sensíveis como senhas, chaves de API e certificados exigem tratamento especializado:

  • HashiCorp Vault: gerenciamento completo de segredos com rotação automática
  • AWS Secrets Manager: rotação programada e integração com RDS
  • Criptografia em repouso: dados armazenados devem ser criptografados
# Exemplo de acesso a segredos via Vault
vault kv put secret/app/production/database \
  username=admin \
  password=$(openssl rand -base64 32)

# Aplicação obtém segredo dinamicamente
vault kv get -field=password secret/app/production/database

Políticas de IAM devem restringir acesso:

  • Princípio do menor privilégio: cada serviço acessa apenas seus segredos
  • Rotação automática: senhas de banco devem expirar a cada 90 dias
  • Auditoria: todo acesso a segredos deve ser registrado

6. Validação e testes de configurações

Antes de implantar configurações em produção, é fundamental validar:

  • Validação sintática: YAML/JSON bem formados
  • Validação semântica: valores dentro de ranges aceitáveis
  • Testes de integração: configurações funcionam com serviços reais
# Schema de validação com JSON Schema
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["database", "server"],
  "properties": {
    "database": {
      "type": "object",
      "required": ["host", "port", "pool"],
      "properties": {
        "host": {"type": "string", "pattern": "^[a-zA-Z0-9.-]+$"},
        "port": {"type": "integer", "minimum": 1024, "maximum": 65535},
        "pool": {
          "type": "object",
          "required": ["min", "max"],
          "properties": {
            "min": {"type": "integer", "minimum": 1},
            "max": {"type": "integer", "minimum": 1}
          }
        }
      }
    }
  }
}

Ferramentas como CUE e Dhall permitem validação em tempo de compilação, prevenindo erros antes da implantação.

7. Monitoramento e auditoria de configurações

Manter trilhas de auditoria é essencial para conformidade e troubleshooting:

  • Logs de alterações: quem alterou, o quê e quando
  • Alertas de desvios: configuração diferente do esperado
  • Dashboards: status atual das configurações distribuídas
# Log de auditoria de configuração
{
  "timestamp": "2024-01-15T10:30:00Z",
  "user": "admin@exemplo.com",
  "action": "UPDATE",
  "resource": "database/pool/max",
  "old_value": 10,
  "new_value": 20,
  "source_ip": "10.0.1.100",
  "environment": "production"
}

# Alerta para desvio de configuração
if actual_pool_size != expected_pool_size:
    alert(
        severity="critical",
        message=f"Database pool size mismatch: expected {expected}, got {actual}",
        service="db-config-monitor"
    )

8. Estratégias de rollback e recuperação

Configurações incorretas podem causar incidentes. Estratégias de rollback são cruciais:

  • Snapshots periódicos: backup completo do estado de configuração
  • Versionamento semântico: cada alteração recebe um número de versão
  • Rollback automatizado: script para reverter ao último estado estável
# Script de rollback de configuração
#!/bin/bash
# Uso: ./rollback-config.sh <versao_anterior>

BACKUP_DIR="/var/backups/config"
CURRENT_VERSION=$(cat /etc/app/config/version)

if [ -f "$BACKUP_DIR/config-v$1.yaml" ]; then
    echo "Revertendo de v$CURRENT_VERSION para v$1..."
    cp "$BACKUP_DIR/config-v$1.yaml" /etc/app/config/current.yaml
    systemctl reload app-service
    echo "Rollback concluído. Versão atual: v$1"
else
    echo "Erro: Backup v$1 não encontrado em $BACKUP_DIR"
    exit 1
fi

Checkpoints regulares garantem que seja possível retornar a estados conhecidos como estáveis:

# Criação de checkpoint automático
0 */6 * * * /usr/local/bin/backup-config.sh --checkpoint

Referências