Projeto final: pipeline completo de CI/CD com Docker e Kubernetes
1. Visão Geral do Projeto e Arquitetura
Este projeto final materializa o ciclo completo de DevOps: desde o commit do código-fonte até o deploy automatizado em um cluster Kubernetes. O pipeline integra as três tecnologias centrais — Docker para containerização, Kubernetes para orquestração e uma ferramenta de CI/CD (GitHub Actions) para automação.
Objetivo do pipeline: garantir que toda alteração no repositório principal passe por validação, empacotamento e entrega contínua ao cluster, com zero intervenção manual.
Componentes do ecossistema:
- Git (GitHub): repositório do código-fonte, Dockerfile e manifestos Kubernetes.
- GitHub Actions: servidor de CI/CD que executa lint, testes, build e push da imagem.
- Docker Registry (Docker Hub): armazenamento das imagens containerizadas.
- Kubernetes (Minikube ou cluster cloud): orquestrador que recebe as atualizações.
Fluxo do pipeline:
1. Desenvolvedor faz push para branch main
2. GitHub Actions detecta o evento e inicia o workflow
3. Executa lint e testes unitários
4. Build da imagem Docker multi-estágio
5. Push da imagem para Docker Hub
6. Atualiza o deployment no Kubernetes com `kubectl set image`
7. Cluster realiza rolling update com health checks
8. Monitoramento e logs são coletados para validação
Cada etapa tem responsabilidade clara: CI valida a qualidade do código e gera o artefato (imagem), CD entrega esse artefato ao cluster com segurança e observabilidade.
2. Preparação do Ambiente de Desenvolvimento e Infraestrutura
Antes de codificar o pipeline, configure o ambiente local ou em nuvem.
Cluster Kubernetes:
# Minikube (local)
minikube start --cpus 4 --memory 8192
kubectl get nodes
# Ou cluster cloud (EKS, GKE, AKS)
# Configure o kubeconfig adequadamente
Docker e Docker Compose:
# Verificar instalação
docker --version
docker-compose --version
Servidor de CI/CD (GitHub Actions):
- Não requer instalação local; o workflow é definido em .github/workflows/.
- Para Jenkins ou GitLab CI, seria necessário provisionar um servidor, mas aqui usaremos GitHub Actions pela simplicidade e integração nativa.
3. Criação e Containerização da Aplicação Exemplo
Estrutura do repositório:
meu-projeto/
├── .github/
│ └── workflows/
│ └── ci-cd-pipeline.yml
├── app/
│ ├── main.py
│ ├── requirements.txt
│ └── test_main.py
├── Dockerfile
├── docker-compose.yml
├── k8s/
│ ├── deployment.yml
│ ├── service.yml
│ └── ingress.yml
└── README.md
Dockerfile multi-estágio (Python Flask simples):
# Estágio 1: build
FROM python:3.11-slim AS builder
WORKDIR /app
COPY app/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app/ .
# Estágio 2: runtime (imagem final enxuta)
FROM python:3.11-alpine
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /app .
EXPOSE 5000
CMD ["python", "main.py"]
Testes locais com Docker Compose:
# docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
environment:
- FLASK_ENV=development
# Executar
docker-compose up --build
# Acessar http://localhost:5000
4. Configuração do Pipeline de Integração Contínua (CI)
Workflow do GitHub Actions (.github/workflows/ci-cd-pipeline.yml):
name: CI/CD Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
env:
DOCKER_IMAGE: ${{ secrets.DOCKER_USERNAME }}/meu-app
K8S_NAMESPACE: production
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: pip install -r app/requirements.txt
- name: Lint
run: pip install flake8 && flake8 app/
- name: Testes unitários
run: cd app && python -m pytest test_main.py -v
- name: Login no Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build e push da imagem
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ env.DOCKER_IMAGE }}:${{ github.sha }}
Gatilhos: push e pull request na branch main. A imagem é taggeada com o SHA do commit para rastreabilidade.
5. Configuração do Pipeline de Entrega Contínua (CD)
Manifestos Kubernetes no diretório k8s/:
deployment.yml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: meu-app
namespace: production
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app: meu-app
template:
metadata:
labels:
app: meu-app
spec:
containers:
- name: app
image: meuusuario/meu-app:latest
ports:
- containerPort: 5000
readinessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 15
periodSeconds: 20
service.yml:
apiVersion: v1
kind: Service
metadata:
name: meu-app-service
namespace: production
spec:
selector:
app: meu-app
ports:
- protocol: TCP
port: 80
targetPort: 5000
type: LoadBalancer
Etapa de CD no workflow (após o push da imagem):
cd:
needs: ci
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Configurar kubectl
uses: azure/setup-kubectl@v4
with:
version: 'latest'
- name: Configurar kubeconfig
run: |
echo "${{ secrets.KUBE_CONFIG }}" | base64 --decode > kubeconfig
export KUBECONFIG=kubeconfig
- name: Atualizar deployment
run: |
kubectl set image deployment/meu-app app=${{ env.DOCKER_IMAGE }}:${{ github.sha }} \
--namespace=${{ env.K8S_NAMESPACE }}
A estratégia de rolling update com health checks garante zero downtime: o Kubernetes só substitui pods quando o readiness probe do novo pod responde com sucesso.
6. Gerenciamento de Segredos e Configurações Sensíveis
Secrets e ConfigMaps no Kubernetes:
# ConfigMap para variáveis não sensíveis
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
data:
FLASK_ENV: "production"
LOG_LEVEL: "info"
# Secret para credenciais
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
namespace: production
type: Opaque
data:
DB_PASSWORD: c2VuaGEgY29tcGxleGE= # base64
No deployment, injete os valores:
env:
- name: FLASK_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: FLASK_ENV
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: DB_PASSWORD
Boas práticas:
- Nunca armazene secrets no repositório; use GitHub Secrets para as variáveis do pipeline (ex.: DOCKER_PASSWORD, KUBE_CONFIG).
- Para ambientes mais robustos, integre com HashiCorp Vault ou sealed-secrets do Bitnami.
7. Monitoramento, Rollback e Validação do Pipeline
Health checks e readiness probes já definidos no deployment garantem que o tráfego só seja direcionado a pods saudáveis.
Estratégia de rollback automático:
# No workflow, adicione validação pós-deploy
- name: Validar deployment
run: |
kubectl rollout status deployment/meu-app --namespace=${{ env.K8S_NAMESPACE }} --timeout=120s
# Se falhar, rollback automático
- name: Rollback em caso de falha
if: failure()
run: |
kubectl rollout undo deployment/meu-app --namespace=${{ env.K8S_NAMESPACE }}
Logs e métricas:
# Para logs centralizados
kubectl logs -l app=meu-app --namespace=production
# Prometheus + Grafana (instalação via Helm)
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack --namespace monitoring
# Métricas customizadas da aplicação expostas em /metrics
8. Considerações Finais e Próximos Passos
Checklist de verificação:
- [ ] Pipeline CI executa lint, testes e build com sucesso
- [ ] Imagem Docker é enviada ao registry
- [ ] CD atualiza o deployment sem downtime
- [ ] Health checks e probes funcionam corretamente
- [ ] Rollback automático é acionado em falha
- [ ] Segredos são gerenciados via Secrets do K8s e GitHub Secrets
Extensões possíveis:
- GitOps com ArgoCD: o cluster sincroniza automaticamente com o repositório Git, eliminando a necessidade de kubectl set image no pipeline.
- Canary deployments: liberar a nova versão para 10% dos usuários antes do rollout completo, usando Service Mesh (Istio) ou Flagger.
- Cluster upgrades e multi-tenancy: temas avançados que se beneficiam deste pipeline como base sólida.
Este projeto final unifica Docker, Kubernetes e CI/CD em uma esteira automatizada, pronta para produção. A partir daqui, o céu (ou o cluster) é o limite.
Referências
- Documentação oficial do GitHub Actions — Guia completo para criação de workflows de CI/CD com exemplos práticos.
- Kubernetes: Rolling Update Deployment — Estratégia oficial de deploy contínuo com zero downtime.
- Docker multi-stage builds — Otimização de imagens com builds em múltiplos estágios.
- GitOps com ArgoCD — Extensão natural para entrega contínua declarativa baseada em Git.
- Prometheus Operator para Kubernetes — Monitoramento e métricas para clusters Kubernetes.
- Bitnami Sealed Secrets — Criptografia de secrets para versionamento seguro no Git.