Deploy no Kubernetes via CI/CD

1. Fundamentos do Deploy Automatizado no Kubernetes

Automatizar deploys no Kubernetes com CI/CD elimina erros manuais, acelera entregas e garante consistência entre ambientes. Um pipeline típico segue o fluxo: build da aplicação, testes unitários e de integração, push da imagem Docker para um registry, e deploy dos manifests no cluster. Ferramentas como GitHub Actions, GitLab CI e ArgoCD são amplamente utilizadas, cada uma com suas particularidades. O ArgoCD, por exemplo, adota GitOps, sincronizando automaticamente o estado do cluster com o repositório Git.

2. Preparando o Ambiente de CI/CD

Antes de configurar o pipeline, é necessário preparar o cluster alvo. Isso envolve definir o contexto do kubectl e garantir que o kubeconfig esteja acessível no runner de CI/CD. Crie um service account com permissões adequadas para deploy:

kubectl create serviceaccount ci-deployer -n production
kubectl create clusterrolebinding ci-deployer-binding \
  --clusterrole=cluster-admin \
  --serviceaccount=production:ci-deployer

O token do service account deve ser armazenado como secret no repositório. Integre também com o container registry (Docker Hub, ECR, GCR) gerando credenciais de acesso e configurando-as como variáveis de ambiente seguras no pipeline.

3. Construção e Publicação da Imagem Docker

O pipeline de build deve usar multi-stage Docker para reduzir o tamanho da imagem final. Exemplo de Dockerfile:

# Etapa de build
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o main .

# Etapa final
FROM alpine:3.18
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]

A tag da imagem deve seguir uma estratégia clara: versão semântica para releases, SHA do commit para deploys de desenvolvimento, e branch para ambientes de staging. Exemplo de tagging no pipeline:

IMAGE_TAG="${CI_COMMIT_SHORT_SHA:-latest}"
docker build -t registry.example.com/app:${IMAGE_TAG} .
docker push registry.example.com/app:${IMAGE_TAG}

Autentique-se no registry usando variáveis de ambiente configuradas no CI/CD, nunca expondo credenciais no código.

4. Estrutura de Manifests Kubernetes para Deploy

Organize os manifests em diretórios separados por ambiente. Use Kustomize para parametrização, evitando duplicação de código. Exemplo de estrutura:

k8s/
├── base/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── kustomization.yaml
└── overlays/
    ├── staging/
    │   ├── kustomization.yaml
    │   └── configmap-patch.yaml
    └── production/
        ├── kustomization.yaml
        └── ingress.yaml

Para ambientes mais complexos, considere Helm charts com templates dinâmicos. O arquivo deployment.yaml base pode ser:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
      - name: app
        image: registry.example.com/app:latest
        ports:
        - containerPort: 8080

5. Estratégias de Deploy no Pipeline

A escolha entre rolling update e recreate depende da tolerância a downtime. Rolling update substitui pods gradualmente, mantendo a disponibilidade. Recreate derruba todos os pods antes de recriá-los, útil para aplicações stateful. Configure health checks no deployment:

livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10
readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 3
  periodSeconds: 5

Para rollback automático, utilize o kubectl rollout undo em caso de falha detectada por métricas ou probes. Exemplo de comando no pipeline:

kubectl rollout status deployment/app -n production --timeout=120s || kubectl rollout undo deployment/app -n production

6. Implementação do Pipeline de CI/CD Completo

Um pipeline completo no GitLab CI pode ser estruturado assim:

stages:
  - lint
  - test
  - build
  - deploy-staging
  - deploy-production

lint:
  stage: lint
  script:
    - golangci-lint run

test:
  stage: test
  script:
    - go test ./... -v

build:
  stage: build
  script:
    - docker build -t registry.example.com/app:${CI_COMMIT_SHORT_SHA} .
    - docker push registry.example.com/app:${CI_COMMIT_SHORT_SHA}

deploy-staging:
  stage: deploy-staging
  script:
    - kubectl set image deployment/app app=registry.example.com/app:${CI_COMMIT_SHORT_SHA} -n staging
    - kubectl rollout status deployment/app -n staging
  environment: staging

deploy-production:
  stage: deploy-production
  script:
    - kubectl set image deployment/app app=registry.example.com/app:${CI_COMMIT_SHORT_SHA} -n production
    - kubectl rollout status deployment/app -n production
  environment: production
  when: manual
  only:
    - main

Para produção, adicione aprovação manual e notificações via Slack ou e-mail usando webhooks.

7. Gerenciamento de Secrets e Configurações

Nunca armazene credenciais no repositório. Use ConfigMaps para configurações não sensíveis e Secrets para dados críticos. Exemplo de criação de secret:

kubectl create secret generic db-credentials \
  --from-literal=username=admin \
  --from-literal=password=${DB_PASSWORD} \
  -n production

Para ambientes mais robustos, utilize o External Secrets Operator ou HashiCorp Vault para sincronizar secrets de fontes externas. Injete variáveis no deployment:

env:
  - name: DB_HOST
    valueFrom:
      configMapKeyRef:
        name: app-config
        key: db_host
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: db-credentials
        key: password

8. Monitoramento e Depuração do Deploy

Após o deploy, verifique o status com:

kubectl rollout status deployment/app -n production --watch
kubectl get pods -n production -o wide

Para depuração, analise logs e eventos:

kubectl logs -l app=app -n production --tail=50
kubectl describe pod app-xxxxx -n production

Falhas comuns incluem ImagePullBackOff (imagem não encontrada ou credenciais inválidas), CrashLoopBackOff (aplicação falha ao iniciar) e falta de recursos (CPU/memória insuficientes). Configure métricas com Prometheus e dashboards no Grafana para monitorar saúde pós-deploy.

Implementar um pipeline robusto de CI/CD para Kubernetes exige planejamento cuidadoso, mas o retorno em produtividade e confiabilidade é imenso. Comece com um pipeline simples e evolua gradualmente, adicionando validações, aprovações e monitoramento contínuo.

Referências