VoltarOptimus AI Platform
Infrastructure & DevOpsPlatform Engineering

Infrastructure & DevOps Pipeline

Arquitetura containerizada production-grade com scaling horizontal automático, alta disponibilidade via Redis Sentinel, e CI/CD com validação de arquitetura integrada. Da prototipação ao scaling de múltiplas instâncias sem downtime.

15+
Microserviços
6
Compose Overlays
3
Sentinels HA
12
Workflows CI/CD

! O Problema

Plataformas AI multi-tenant têm características únicas que complicam infraestrutura tradicional: workloads altamente variáveis (um prompt pode levar 100ms ou 30s), dependência crítica de serviços externos (LLMs, WhatsApp), e a necessidade de isolar tenants enquanto compartilha recursos eficientemente.

Desafios Específicos

  • Spiky traffic: Campanhas de marketing podem 10x o tráfego em minutos — precisa escalar rápido e voltar sem desperdiçar recursos
  • Stateful services: Memory Engine e pgvector precisam de connection pools controlados — não é só "spawn more containers" e pronto
  • Redis as SPOF: Cache, sessions, queues, rate limiting — tudo passa pelo Redis. Precisa de HA real
  • 12+ microservices: Orquestrar deploys coordenados sem breaking changes entre serviços de versões diferentes
  • Secrets sprawl: 40+ API keys de LLMs, webhooks, databases — precisam de rotação sem downtime

A solução foi construída iterativamente: começou com docker-compose monolítico, evoluiu para overlays por ambiente, depois scaling horizontal com nginx LB, e finalmente Redis Sentinel para HA. Cada passo foi motivado por necessidades reais de produção.

📦 Arquitetura de Containers

Dockerfiles seguem padrões production-grade: multi-stage builds para imagens menores, usuários non-root para segurança, BuildKit cache mounts para builds rápidos, e health checks que realmente testam a aplicação (não só se o processo existe).

memory-engine/DockerfileProduction Patterns
# Multi-stage build with Python 3.12-slim
FROM python:3.12-slim as base

# Non-root user for security (CVE mitigation)
RUN useradd --create-home --shell /bin/bash memory
USER memory

# BuildKit cache mount - doesn't re-download wheels on each build
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install --no-cache-dir -r requirements.txt

# Health check that tests real endpoint, not just process
HEALTHCHECK --interval=30s --timeout=15s --start-period=60s --retries=5 \
    CMD curl -f http://localhost:8050/health || exit 1

# Startup script (not direct CMD) for init logic
CMD ["/app/scripts/start-memory-engine.sh"]

Docker Compose Overlays

Em vez de um docker-compose.yml monolítico, usamos overlays que compõem configurações. Isso permite que desenvolvimento, staging e produção compartilhem a base mas customizem o que precisam — sem duplicação e sem drift acidental.

docker-compose.yml

Base: todos os serviços, volumes, networks. Configuração comum que funciona em qualquer ambiente.

docker-compose.scale.yml

Overlay: nginx-lb, job de migrations separado, portas removidas (tudo via LB), WEB_CONCURRENCY configurável.

docker-compose.sentinel.yml

Overlay: topologia Redis master/replica/sentinel para HA. Serviços recebem vars REDIS_SENTINEL_*.

docker-compose.dev.yml

Overlay: volumes de código montados, debug habilitado, hot reload, portas expostas diretamente.

Composição de Overlays
# Local development
docker compose -f docker-compose.yml -f docker-compose.dev.yml up

# Production with scaling
docker compose -f docker-compose.yml -f docker-compose.scale.yml up \
  --scale ai-engine=3 \
  --scale backend-orchestrator=2

# Production with full HA
docker compose \
  -f docker-compose.yml \
  -f docker-compose.scale.yml \
  -f docker-compose.sentinel.yml \
  up -d

Resource Limits & Reservations

docker-compose.yml - Redis with limits
redis:
  image: redis:8.0-alpine
  command:
    - redis-server
    - --maxmemory 2gb
    - --maxmemory-policy allkeys-lru  # Automatic eviction
    - --activedefrag yes              # Background defrag
    - --latency-monitor-threshold 100
  deploy:
    resources:
      limits:
        cpus: '2.0'
        memory: 2G
      reservations:
        cpus: '0.5'
        memory: 512M
  labels:
    - "com.optimus.service=redis"
    - "com.optimus.environment=production"

📈 Scaling Horizontal

Sistema de scaling que vai de 1 a N instâncias sem mudança de código. Load balancer nginx distribui tráfego, session affinity via Redis, e health checks determinam routing.

Arquitetura de Scaling

External Traffic
nginx-lb:8010, :8020
ai-enginereplica 1
ai-enginereplica 2
ai-enginereplica 3
least_conn + dynamic DNS

Nginx Load Balancer

nginx/nginx-lb.conf
# Docker internal DNS resolver - CRITICAL for --scale
resolver 127.0.0.11 ipv6=off;

upstream ai_engine {
    zone ai_engine 64k;
    least_conn;  # Request goes to instance with fewest connections
    
    # 'resolve' enables dynamic DNS - new replicas are discovered
    server ai-engine:8010 resolve;
    
    keepalive 32;  # Connection pooling for backends
}

upstream backend_orchestrator {
    zone backend_orchestrator 64k;
    least_conn;
    server backend-orchestrator:8020 resolve;
    keepalive 32;
}

# Backend Orchestrator needs WebSocket for real-time dashboard
server {
    listen 8020;
    
    location / {
        proxy_pass http://backend_orchestrator;
        
        # WebSocket upgrade headers
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        
        # Longer timeouts for WebSocket
        proxy_read_timeout 300s;
    }
}

# Mapping for connection upgrade
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

Migration Job Isolado

Quando você escala serviços, todos tentam rodar migrations ao iniciar — race condition garantida. A solução foi um job dedicado que roda ANTES das replicas subirem, usando depends_on: condition: service_completed_successfully.

docker-compose.scale.yml
# Single migrations job (runs once, exits)
migrations:
  extends:
    file: docker-compose.yml
    service: memory-engine
  restart: "no"
  ports: []  # No exposure
  environment:
    - RUN_MIGRATIONS_ONLY=true
  command: >
    bash -c "
      python /app/scripts/wait-for-postgres.py &&
      python -m alembic upgrade head &&
      echo '✅ Migrations completed'
    "

# Replicas only come up after migrations finish
memory-engine:
  extends:
    file: docker-compose.yml
    service: memory-engine
  environment:
    - SKIP_STARTUP_BOOTSTRAP=true  # Don't attempt migrations
    - RUN_MIGRATIONS=false
  depends_on:
    migrations:
      condition: service_completed_successfully

Scale-Up Script

scripts/scale-up.sh (options)
./scripts/scale-up.sh \
  --scale ai-engine=3 \
  --scale backend-orchestrator=2 \
  --scale memory-engine=2 \
  --build ai-engine \      # Rebuild only what changed
  --run-migrations \       # Force migrations
  --observability \        # Enable Tempo/Loki/Alloy
  --logs on               # Tail instance logs

# Scale down (keeps volumes)
./scripts/scale-up.sh --down

# Scale down + cleanup network
./scripts/scale-up.sh --down --prune-network

⚠️ Considerações Stateful

Memory Engine é stateful — mantém connection pools com PostgreSQL. Escalar de 2 para 6 replicas cria 6x mais conexões ao banco. Por isso configuramos DB_POOL_SIZE e DB_MAX_OVERFLOW via env vars, permitindo ajuste dinâmico: DB_POOL_SIZE=5 DB_MAX_OVERFLOW=10 = máx 15 conexões/replica. DB_POOL_SIZE=5 DB_MAX_OVERFLOW=10 = max 15 connections/replica.

🛡️ Alta Disponibilidade

Redis Sentinel para failover automático. Três sentinels monitoram o master e promovem replica automaticamente em caso de falha.

Topologia Sentinel

sentinel-1:26379
sentinel-2:26379
sentinel-3:26379
quorum: 2 (2 de 3 precisam concordar)
↓ monitora ↓
redis-master:6379 (writes)
→ replica →
redis-replica-1:6379 (reads)
redis-replica-2:6379 (reads)
docker-compose.sentinel.yml (excerpt)
# Redis Master with replication enabled
redis:
  image: redis:8.0-alpine
  hostname: redis-master
  command:
    - redis-server
    - --appendonly yes          # Durability (AOF)
    - --lazyfree-lazy-eviction yes
    - --replica-announce-ip redis-master

# Replicas point to master
redis-replica-1:
  command:
    - redis-server
    - --replicaof redis-master 6379
    - --replica-announce-ip redis-replica-1

# Sentinels monitor and perform failover
redis-sentinel-1:
  command:
    - redis-sentinel
    - /etc/redis/sentinel.conf
    - --port 26379

# Services use Sentinel mode
ai-engine:
  environment:
    - REDIS_SENTINEL_ENABLED=true
    - REDIS_SENTINEL_MASTER=mymaster
    - REDIS_SENTINEL_HOSTS=sentinel-1:26379,sentinel-2:26379,sentinel-3:26379

Failover Automático

  1. 1Master fica inacessível (crash, network partition, ou qualquer falha)
  2. 2Sentinels detectam (configurable timeout, default 30s)
  3. 3Quorum de 2 sentinels concorda que master está down
  4. 4Eleição de novo master entre replicas (baseia-se em replication offset)
  5. 5Sentinels atualizam configuração; clientes reconectam automaticamente

✓ Por que 3 Sentinels?

Com quorum de 2, você precisa de no mínimo 3 sentinels para tolerar 1 falha. Se tiver só 2 sentinels e 1 falhar, não atinge quorum e failover não acontece. Número ímpar evita split-brain (empate de votos).

⚙️ CI/CD Pipeline

GitHub Actions com 12 workflows especializados. Cada PR passa por lint, type check, testes unitários, e validação de arquitetura antes de merge.

ci.yml

Ruff lint, mypy type-check, pytest, Docker build. Roda em todo push/PR.

guardrails.yml

Validação de arquitetura. Bloqueia PRs que violam patterns definidos em policy.yaml.

e2e-tests.yml

Testes end-to-end com pgvector + Redis reais. Valida fluxos multi-ERP.

llm-eval.yml

Avaliação de qualidade de outputs do AI Engine. Detecta regressões em prompts.

Architecture Guardrails

O sistema de guardrails usa um MCP server que analisa diffs e valida contra regras. Se um PR viola um pattern (ex: import direto entre camadas, SQL raw em controllers), o workflow falha e posta um comentário detalhado no PR.

.github/workflows/guardrails.yml (excerpt)
# Runs only on PRs that touch Python code
on:
  pull_request:
    paths:
      - 'ai-engine/**/*.py'
      - 'backend-orchestrator/**/*.py'
      - 'memory-engine/**/*.py'

jobs:
  validate:
    steps:
      - name: Generate diff
        run: |
          git diff origin/${{ github.base_ref }}...HEAD > pr.diff
          
      - name: Validate guardrails
        run: |
          python mcp_servers/optimus_project_mcp/cli_validate_diff.py < pr.diff
          
      # If fails, post comment on PR with violations
      - name: Comment on PR (if violations)
        if: failure()
        uses: actions/github-script@v7
        with:
          script: |
            const violations = JSON.parse(fs.readFileSync('guardrails-result.json'));
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              body: formatViolations(violations)
            });

E2E Tests com Services

.github/workflows/e2e-tests.yml
jobs:
  e2e-tests:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    
    # Real containers as GitHub Actions services
    services:
      postgres:
        image: pgvector/pgvector:0.8.1-pg16
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-retries 5
      redis:
        image: redis/redis-stack:latest
        options: >-
          --health-cmd "redis-cli ping"
    
    steps:
      - name: Run migrations
        run: python -m alembic upgrade head
        
      - name: Run E2E tests
        run: |
          pytest tests/e2e/ -v --tb=short \
            --cov=ai_engine --cov-report=xml

🔐 Segurança

Múltiplas camadas de segurança: secrets management, network isolation, e scanning automatizado.

scripts/secrets-manager.sh
./secrets-manager.sh init        # Create .env.secrets from example
./secrets-manager.sh validate    # Verify all are filled
./secrets-manager.sh backup      # Encrypted backup (GPG)
./secrets-manager.sh restore     # Restore from backup
./secrets-manager.sh rotate      # Interactive key rotation
./secrets-manager.sh check-security  # Audit for issues

Separação de Secrets

.env.secrets

API keys, passwords, tokens. Nunca commitado. Gitignore'd.

.env.models

Configurações de modelos LLM. Pode ser commitado (sem keys).

.env.example

Template com placeholders. Commitado para documentação.

Container Security

  • Non-root users: Todos os containers rodam como usuário não-root (appuser:1001 ou similar). Mitiga privilege escalation.
  • Slim base images: python:3.12-slim em vez de full. Menos pacotes = menos superfície de ataque.
  • Read-only configs: Arquivos de config montados como :ro (read-only). Containers não podem modificar.
  • Network isolation: Rede bridge dedicada (optimus). Services só acessíveis via LB.
  • Internal Memory Engine: Porta 8050 não exposta ao host — só acessível via nginx-lb internamente.

🔧 Operações

Ferramentas de operação para gerenciar o ciclo de vida dos serviços.

scale-up.sh

Scaling completo com build, migrations, e tail de logs.

--scale, --build, --observability, --attach

validate_redis.sh

Health check de Redis: ping, memory, connected clients.

redis-cli info, dbsize, latency

run_load_tests.sh

Load testing com k6 ou locust. Gera relatório.

--users, --duration, --endpoint

trace_smoke_test.sh

Valida tracing E2E: gera trace, verifica no Tempo.

opentelemetry, tempo, span verification

Health Checks Úteis

Quick Health Commands
# Via load balancer
curl http://localhost:8010/health  # AI Engine
curl http://localhost:8020/health  # Backend Orchestrator

# Container status
docker compose -f docker-compose.yml -f docker-compose.scale.yml ps

# Check LB routing (DNS resolution)
docker exec nginx-lb nslookup ai-engine
docker exec nginx-lb nslookup backend-orchestrator

# Redis health
docker exec optimus_redis_8_production redis-cli ping
docker exec optimus_redis_8_production redis-cli info memory

📊 Resultados

<5 min
Deploy Time
99.9%
Uptime
0
Secrets expostos (validação automática)
~30s
Failover automático Redis

Lições Aprendidas

  • Compose overlays > monolítico: Manutenção muito mais fácil quando cada concern está isolado
  • Migrations job separado: Evita race conditions e permite escalar replicas livremente
  • Health checks reais: Testar o endpoint /health, não só se o processo existe
  • DNS dinâmico no LB: Sem isso, nginx não descobre novas replicas
  • Sentinel quorum ímpar: 3 sentinels com quorum 2 é o mínimo para HA real

Stack Técnico

Docker ComposeNginxRedis SentinelGitHub ActionspgvectorBuildKitRuffmypypytestOpenTelemetryTempoLokiBash

Explore Outros Case Studies

Veja como outros componentes do Optimus foram construídos

Case Study: Infrastructure & DevOps — Optimus AI Platform