Pular para o conteúdo principal

Repositórios de Aplicação como Golden Paths: Dockerfile, CI e .k8s em Cada Repo

· 6 min para ler
Platform Engineering Team

Nossa plataforma gerencia onde e como os serviços são implantados através de repositórios GitOps. Mas e a aplicação em si — o código, o build, o contêiner? Até agora, cada equipe configurava seu próprio Dockerfile, escrevia seu próprio pipeline de CI e elaborava sua própria estratégia de tagueamento de imagens. O resultado era previsível: 10 times, 10 workflows de CI diferentes, 10 abordagens diferentes de build de contêiner e zero consistência.

A convenção de Repositórios de Aplicação muda isso. Quando um novo serviço é scaffoldado via Backstage, ele entrega um repositório completo e opinativo com código fonte, Dockerfile, pipeline de CI e uma pasta .k8s — dando à equipe da aplicação autonomia sobre a configuração de sua carga de trabalho enquanto mantém a plataforma no controle do modelo de implantação.

A arquitetura: dois repos, uma implantação

Nosso modelo GitOps usa uma separação clara entre configuração de implantação e configuração da aplicação:

{domain}-gitops/k8s/{env}/{service}/ ← Manifestos base gerenciados pela plataforma
{app}-repo/.k8s/values.yaml ← Sobrescrições gerenciadas pelo desenvolvedor

O repositório GitOps do domínio contém a configuração fundacional do Kubernetes — Deployments, Services, NetworkPolicies, HPA, PDB — gerada pelo template create-service e mantida pelas convenções de plataforma do time do domínio.

O repositório da aplicação contém uma pasta .k8s onde o time de desenvolvimento gerencia valores que mudam frequentemente com os releases da aplicação.

O padrão de Múltiplas Fontes (Multiple Sources) do ArgoCD mescla ambas as fontes no momento da sincronização. Os manifestos base do repo GitOps fornecem estrutura e segurança. As sobrescrições da aplicação fornecem flexibilidade e velocidade.

O que os desenvolvedores podem sobrescrever

O .k8s/values.yaml no repositório da aplicação dá aos desenvolvedores controle sobre:

  • Tag da imagem: Atualizada automaticamente pelo CI em cada build bem-sucedido
  • Réplicas: Sobrescrever limites min/max do HPA para necessidades específicas da carga de trabalho
  • CPU e memória: Ajustar requests e limits conforme o perfil da aplicação evolui
  • Variáveis de ambiente: Configuração específica da aplicação que muda com os releases

Esses são os valores que mudam com mais frequência e estão mais diretamente ligados ao código da aplicação. Mantendo-os no repo da app, desenvolvedores não precisam de um PR no repo GitOps toda vez que fazem push de um release.

O que os desenvolvedores não tocam

Os manifestos base em {domain}-gitops/k8s/ permanecem sob controle da convenção da plataforma:

  • Definição do Namespace com todos os 9 labels obrigatórios
  • Contexto de segurança: runAsNonRoot, readOnlyRootFilesystem, capabilities: drop: [ALL]
  • NetworkPolicy: isolamento por fronteira de projeto
  • PodDisruptionBudget: rede de segurança apenas para prod
  • ResourceQuota: limites dimensionados por ambiente

Essa separação garante que as garantias de segurança e conformidade nunca sejam acidentalmente sobrescritas por um desenvolvedor que "só precisa mudar o limite de memória."

O pipeline de CI: do commit ao deploy

Todo repositório de aplicação scaffoldado pelo create-service inclui um workflow pré-configurado do GitHub Actions. O pipeline não é algo que o time precisa escrever — ele chega pronto:

Desenvolvedor faz push do código


┌─── Pipeline de CI ─────────────────────────────────┐
│ │
│ 1. Test & Lint Executa testes, verificações │
│ 2. Build Constrói contêiner do Dockerfile│
│ 3. Publish Push da imagem para o registry │
│ 4. Atualização de Atualiza .k8s/values.yaml com │
│ Tag nova tag, commit de volta │
│ │
└─────────────────────────────────────────────────────┘


ArgoCD detecta mudança no app repo (fonte secundária)


Implantação sincroniza com nova tag da imagem

O passo chave é a Atualização de Tag. Após publicar a imagem do contêiner, o pipeline atualiza automaticamente image.tag em .k8s/values.yaml e faz commit da mudança de volta no repositório da aplicação. Esse commit é o que o ArgoCD observa.

Como o ArgoCD está configurado com Multiple Sources — uma apontando para o repo GitOps para manifestos base, outra apontando para o repo da app para sobrescrições — a nova tag aciona uma sincronização automática para o ambiente alvo.

Sem atualizações manuais de tag de imagem. Sem passo separado de "deploy". Faça push do código, obtenha a implantação.

O Dockerfile: seguro por padrão

O Dockerfile scaffoldado segue os padrões de segurança da plataforma:

  • Build multi-estágio: Estágios separados de build e runtime para minimizar o tamanho da imagem
  • Usuário não-root: USER 1000 — combina com o contexto de segurança do pod (runAsNonRoot: true)
  • Compatível com filesystem somente leitura: Escritas da aplicação vão para /tmp (montado como emptyDir)
  • Otimização específica por linguagem: Node.js, .NET e Python recebem cada um um Dockerfile adaptado com imagens base e cache de dependências apropriados

O desenvolvedor não precisa saber sobre contextos de segurança de pod ou filesystems somente leitura. O Dockerfile e os manifestos Kubernetes são projetados para funcionar juntos desde o primeiro dia.

O quadro completo

Quando o create-service é executado, o desenvolvedor recebe:

O quêOndeQuem mantém
Código fonte boilerplate{app}-repo/src/Time da aplicação
Dockerfile{app}-repo/DockerfileTime da aplicação
Pipeline de CI{app}-repo/.github/workflows/ci.yamlTime de plataforma (gerado), time da aplicação (estendido)
Sobrescrições da carga de trabalho{app}-repo/.k8s/values.yamlTime da aplicação
TechDocs{app}-repo/docs/Time da aplicação
Manifestos K8s base{domain}-gitops/k8s/{env}/{service}/Time do domínio
Roteamento ArgoCDplatform-gitops/argocd/applicationsets/Time de plataforma

Três repositórios, três fronteiras de propriedade, uma implantação que funciona sem coordenação manual.

Por que não tudo no repo da app?

Uma pergunta comum: "Por que não colocar todos os manifestos Kubernetes no repositório da aplicação?"

Porque quebra o modelo de propriedade:

  1. Contexto de segurança e políticas de rede são preocupações da plataforma, não da aplicação. Desenvolvedores não deveriam precisar (nem poder) modificá-los.
  2. Múltiplos serviços compartilham o mesmo ApplicationSet e estrutura de domínio. Centralizar isso no repo GitOps evita duplicação e garante consistência.
  3. Validação de convenção roda no repo GitOps. Verificações de CI para nomenclatura, labels e padrões de segurança acontecem onde essas definições vivem.

A pasta .k8s dá aos desenvolvedores a autonomia que precisam — tags de imagem, escalonamento, recursos — sem dar acesso às coisas que não deveriam mudar.


A convenção de Repositórios de Aplicação está documentada na Convenção da Plataforma — Repositórios de Aplicação. O padrão de Múltiplas Fontes do ArgoCD está na Convenção ArgoCD.