Depois de lidar com uns trinta bloqueios no SonarQube, tratar vulnerabilidades com Trivy e resolver race conditions no Terraform, implementando uma pipeline CI/CD na Oracle Cloud Infrastructure (OCI) com GitHub Actions, ArgoCD e Oracle Container Registry (OCIR).
Trago aqui uma pipeline de CI/CD com GitOps para Kubernetes (OKE) que combina GitHub Actions, SonarQube para análise estática, Trivys, OCIR e ArgoCD (com ArgoCD Image Updater). O Terraform provisiona a infraestrutura em camadas para evitar problemas.
Arquitetura da Build Pipeline
A pipeline de build é dividida em 4 partes:
-
Testes Unitários: O GitHub Actions usa
pytestcom relatório de cobertura de código. - Análise de Qualidade: O SonarQube valida o código e bloqueia a build caso não atinja a qualidade que ele espera.
- Análise de Segurança: O Trivy escaneia o sistema de arquivos e as imagens de contêiner em busca de vulnerabilidades.
- Containerização e Publicação: A imagem da aplicação é gerada e enviada ao Oracle Container Registry (OCIR).
Deploy Pipeline: Entrega Contínua com GitOps
Em vez de executar scripts manuais de implantação ou chamadas diretas via kubectl, a entrega da aplicação usa GitOps.
- O cluster Oracle Kubernetes Engine (OKE) roda o ArgoCD e o ArgoCD Image Updater.
- O ArgoCD Image Updater vigia o repositório OCI Registry em busca de novas tags de imagem.
- Ao detectar uma nova imagem, o repositório Git de manifesto é atualizado automaticamente.
- O ArgoCD aplica o estado desejado no cluster Kubernetes sem intervenção humana direta nem permissão de escrita do GitHub Actions no cluster.
Provisionamento com Terraform em 4 Camadas
O Terraform só valida se o recurso existe na API do Kubernetes naquele instante, não se ele está funcional e reconciliado. É aí que mora a race condition.
Para resolver isso, os manifestos foram dividida em quatro camadas independentes executadas em ordem:
| Camada | Nome | Responsabilidade | Dependência |
|---|---|---|---|
| 01 | 01-infra |
Redes e o cluster OKE | VCN (que eu já criei antes) |
| 02 | 02-k8s-base |
Instalação do ArgoCD via Helm | Requer cluster OKE ativo |
| 03 | 03-k8s-addons |
Configuração do ArgoCD Image Updater | Requer ArgoCD instalado |
| 04 | 04-apps |
Manifestos de aplicações e rotas do ArgoCD | Requer ArgoCD e Addons prontos; Container Registry (que eu já criei manualmente) |
Dividi os arquivos .tf em pastas distintas e executei o terraform apply sequencialmente para que a API do Kubernetes se preparasse para receber recursos do Helm antes e configurasse a aplicação dos manifestos depois.
Aprendizados
1. Hash no SonarQube e GitHub Actions
O SonarQube recusava meu código para atender a critérios rigorosos de segurança e reprodutibilidade. Entendi que as ações do GitHub Actions devem ser referenciadas pelo hash commit completo em vez de tags mutáveis de versão:
# Recomendado: Imutável e seguro contra Supply Chain Attacks
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2
# Evitar em produção: Tags podem ser alteradas no repositório de origem
- uses: actions/checkout@v4.0.0
O mesmo princípio aplica-se ao pip, fixando o hash dos pacotes via pip-compile --generate-hashes para impedir a execução de dependências adulteradas.
2. Trivy
Imagens padrão muitas vezes tem vulnerabilidades a nível do sistema operacional. Para evitar falhas na verificação do Trivy sem comprometer o pipeline de CI/CD, o melhor seria usar ChainGuard. Na ausência deste, o melhor é utilizar imagens base minimalistas como Distroless ou Alpine Linux.
3. Execução sem Privilégios no Dockerfile (Non-Root User)
Os alertas do SonarQube também me mostraram que executar contêineres como root expõe o host a riscos de container escape. O Dockerfile deve explicitar a criação de um usuário sem privilégios administrativos:
FROM python:3.11-slim
RUN groupadd -r appgroup && \
useradd -r -g appgroup -s /sbin/nologin appuser
WORKDIR /app
COPY . /app/
RUN chown -R appuser:appgroup /app && \
chmod -R 755 /app
USER appuser
CMD ["python", "main.py"]
Por que utilizar Oracle Cloud Infrastructure (OCI)?
- Custo-benefício: A OCI oferece alta performance com menor custo operacional.
- Fim dos Noisy Neighbors: Cada OCPU entrega um núcleo físico exclusivo, o que evita quedas de rendimento por outras instâncias computacionais (noisy neighbors, ou vizinhos barulhentos).
- Taxa de Egress: A OCI oferece 10 TB mensais de transferência de saída de dados sem custo adicional, além de taxas moderadas depois dos 10 TB.
- Zero-Trust Networking: Redes VCN nativas e integração direta entre o OKE e o OCIR simplificam o isolamento do ambiente.
No Futuro
Graças à natureza granular dos manifestos Terraform, posso integrar mais recursos futuros.
Monitoramento e Observabilidade do Cluster
A própria infraestrutura do plano de controle do OKE coleta métricas automaticamente e as envia para o OCI Monitoring. Para um monitoramento aprofundado dos Pods, do estado dos objetos do cluster ou para clusters fora do OKE, utiliza-se o OCI Management Agent. Também pode-se usar Prometheus e Grafana/Zabbix. Para coletar stout e sterr, também pode-se usar OCI Kubernetes Monitoring Solution.
Segurança
Para uma segurança mais rígida e complementar ao Trivy, pode-se usar OCI Cloud Guard (que centraliza alertas de segurança em um único painel) e OCI Vulnerability Scanning Service (que analisa imagens de contêineres enviadas ao OCIR).
Aceito mais sugestões!
FAQ
O que é GitOps e qual a diferença para o CI/CD tradicional?
O GitOps é stateful: em vez do pipeline executar comandos diretamente no cluster, um agente interno monitora o repositório Git e aplica automaticamente as alterações. Enquanto em um CI/CD tradicional pode gerar desalinhamento se alguém alterar o ambiente de produção, no GitOps, o repositório Git sempre revela exatamente o código em produção.
Por que especificar hashes SHA-256 em dependências do GitHub Actions?
Anotar dependências com o SHA-256 garante imutabilidade. Se a tag de uma ação pública (ex: v4) for sobrescrita por um código malicioso, o uso do commit hash impede que o pipeline execute a versão comprometida.
Por que usar o ArgoCD Image Updater em vez de apenas ArgoCD?
O ArgoCD sozinho não atualiza tags automaticamente. O Image Updater automatiza a atualização de tags. Ele reduz a necessidade de o GitHub Actions ter permissão direta no cluster, melhorando a segurança.
Por que a infraestrutura foi dividida em pastas em vez de usar depends_on nos módulos do Terraform?
A separação física das pastas garante a inicialização sequencial e limpa. O uso do provedor Kubernetes/Helm no Terraform exige que o endpoint da API do Kubernetes já esteja acessível durante a fase de planejamento (terraform plan). Se o cluster OKE e as rotas Helm estiverem no mesmo estado/pasta, o terraform apply falhará na primeira execução porque o provedor tentará se conectar a uma API que ainda nem existe.
Por que optar pelo OKE em vez de provisionar um cluster Kubernetes "do zero" (Unmanaged) via Terraform na OCI?
O OKE é um serviço gerenciado onde a Oracle arca com os custos e a manutenção do Control Plane (Master Nodes), garantindo alta disponibilidade, atualização de versão da API e integração nativa com o OCI Registry e Load Balancers. Isso economiza horas de administração de infraestrutura e reduz os custos operacionais.


Top comments (0)