Pular para o conteúdo
CESAR ZANIS
Tech Reference
Infra

DevOps & Cloud

CI/CD que funciona, Docker com critério, Kubernetes quando faz sentido e FinOps embutido desde o início. DORA Metrics como bússola, não como vaidade de slide.

"Em TI, tudo é nivelado pelo mais lento. O alicerce precisa ser feito da melhor maneira possível desde o início."

Cesar Zanis
01

DORA Metrics: as 4 que importam

Frequência de deploy, tempo de entrega, taxa de falha e tempo de recuperação ajudam a diagnosticar a entrega de software. Use esses sinais para entender gargalos, não como metas isoladas.

Deployment Frequency

> 1x por dia (Elite)vs< 1x por mês (Low)

Por que importa

Frequência alta = lotes pequenos = menor risco por deploy. Time que deploya 1x por mês está acumulando risco, não sendo cuidadoso.

Como melhorar

Reduza o tamanho dos lotes. Feature flags para desacoplar deploy de release.

Lead Time for Changes

< 1 hora (Elite)vs> 6 meses (Low)

Por que importa

Tempo entre commit e produção. Longo = feedback lento = problemas descobertos tarde. Não é velocidade por velocidade: é ciclo de aprendizado.

Como melhorar

Automatize stages. Elimine aprovações manuais desnecessárias. Teste em PR, não depois do merge.

Change Failure Rate

< 5% (Elite)vs> 46% (Low)

Por que importa

Porcentagem de deploys que causam incidente. Alto = qualidade de teste ruim ou escopo de mudança grande demais.

Como melhorar

Testes automatizados com cobertura real (não decorativa). Blue/green deployment. Rollback em < 5 minutos.

MTTR (Mean Time to Restore)

< 1 hora (Elite)vs> 6 meses (Low)

Por que importa

Quanto tempo para restaurar serviço após incidente. Mais importante que não cair é saber voltar rápido.

Como melhorar

Runbooks documentados. Alertas com contexto (não só "CPU alta"). Post-mortem sem blame após cada SEV-1.

02

CI/CD: pipelines que funcionam

Pipeline mínimo que funciona (GitHub Actions)

YAML
# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Cache de dependências: evita downloads repetidos
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - run: npm ci
      - run: npm run lint
      - run: npm run test -- --coverage

      # Upload de coverage: visibilidade dos testes
      - uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

  build:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4

      # Build e push da imagem Docker
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - uses: docker/build-push-action@v5
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:latest
          cache-from: type=gha   # Cache de layer Docker entre runs
          cache-to: type=gha,mode=max

Dockerfile multi-stage: a diferença entre 1.2GB e 120MB

YAML
# Dockerfile multi-stage
# Stage 1: Build (tem tudo que precisa para compilar)
FROM node:20-alpine AS builder
WORKDIR /app

# Copiar só package.json primeiro: cache eficiente
# Se o código muda mas as dependências não, esta layer é reutilizada
COPY package*.json ./
RUN npm ci --only=production

COPY . .
RUN npm run build

# Stage 2: Runtime (tem só o que precisa para rodar)
FROM node:20-alpine AS runner
WORKDIR /app

# Usuário não-root: segurança básica
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

# Copiar apenas o output do build
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=builder --chown=nextjs:nodejs /app/public ./public

USER nextjs
EXPOSE 3000
ENV PORT=3000 NODE_ENV=production

# Health check: expõe a saúde do container ao orquestrador
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
  CMD wget -qO- http://localhost:3000/api/health || exit 1

CMD ["node", "server.js"]

# Meça o tamanho final da imagem na sua aplicação
03

FinOps: custo como feature, não como acidente

A fatura mensal não deveria ser o primeiro sinal de desperdício. FinOps conecta o gasto ao valor para o negócio, com visibilidade e decisões ao longo do desenvolvimento.

01

Dimensione para o P90, não para o pico

Picos máximos podem durar pouco. Autoescalamento atende os picos; right-sizing atende a demanda cotidiana. Meça a carga real antes de escolher a capacidade.

02

Spot/Preemptible para workloads sem estado

CI/CD, processamento em lote e workers de filas podem usar capacidade interrompível com desconto. Projete para interrupções e verifique a economia para o provedor e a carga.

03

Reserved instances só para baseline comprovado

Reserve o que você tem certeza que vai usar. O risco de comprometer capacidade que você não usa supera o desconto em cenários de mudança rápida.

04

Tags de custo desde o início

Sem tags por serviço/time/ambiente, o billing vira uma caixa preta. Crie a política de tags antes de criar qualquer recurso. Retroagir é doloroso.

05

Budget alert antes de estourar, não depois

Configure alertas em 50%, 80% e 100% do budget. O alerta de 50% é o que importa: te dá tempo de agir sem urgência.

Kubernetes: o mais mal-aplicado da lista

Kubernetes resolve problemas de orquestração em escala. Antes de adotá-lo, considere quantidade de serviços, complexidade operacional e capacidade do time de gerenciar a plataforma.

Use quando: múltiplos serviços com ciclos de deploy independentes, necessidade de auto-scaling granular, equipe com experiência real em K8s.

Evite quando: monólito funcional e time pequeno sem necessidade clara de orquestração. Avalie Docker Compose, Cloud Run ou ECS antes de adicionar uma plataforma para manter.

Precisa de ajuda para estruturar CI/CD, reduzir custo cloud ou medir DORA no seu time?

Falar com Cesar Zanis