Kustomize: overlays e configurações por ambiente

1. Introdução ao Kustomize no Ecossistema Kubernetes

Gerenciar configurações de Kubernetes para múltiplos ambientes (desenvolvimento, homologação, produção) é um dos maiores desafios em pipelines DevOps. Sem uma abordagem estruturada, desenvolvedores acabam mantendo dezenas de arquivos YAML quase idênticos, com apenas pequenas variações de variáveis, nomes ou réplicas. O Kustomize surge como uma solução declarativa e nativa do ecossistema Kubernetes para resolver exatamente esse problema.

Diferentemente do Helm, que utiliza templates Go com lógica de programação, o Kustomize opera sem modelos — ele parte de manifestos YAML válidos e aplica transformações em camadas. Isso significa que você nunca perde a visibilidade do que está sendo aplicado, pois a saída final é sempre um YAML puro. Desde o Kubernetes 1.14, o Kustomize está integrado ao kubectl através do comando kubectl apply -k, tornando seu uso ainda mais natural para quem já opera clusters.

2. Estrutura de Diretórios e Conceitos Fundamentais

O coração do Kustomize é o arquivo kustomization.yaml. Ele define quais recursos serão incluídos e quais transformações serão aplicadas. A arquitetura básica separa o que é comum (base) do que é específico (overlays):

meu-app/
├── base/
│   ├── kustomization.yaml
│   ├── deployment.yaml
│   └── service.yaml
└── overlays/
    ├── dev/
    │   └── kustomization.yaml
    ├── staging/
    │   └── kustomization.yaml
    └── prod/
        └── kustomization.yaml

A base contém os manifestos compartilhados por todos os ambientes. Cada overlay referencia essa base e adiciona ou sobrescreve configurações específicas. Essa separação permite que alterações comuns sejam feitas uma única vez na base, enquanto cada ambiente mantém suas particularidades.

3. Trabalhando com Bases: Configurações Compartilhadas

Uma base típica define os recursos fundamentais da aplicação. Vamos criar um exemplo concreto:

base/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - deployment.yaml
  - service.yaml

commonLabels:
  app: meu-app
  managed-by: kustomize

commonAnnotations:
  version: "1.0.0"
  environment: "base"

base/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: meu-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: meu-app
  template:
    metadata:
      labels:
        app: meu-app
    spec:
      containers:
        - name: app
          image: meu-app:latest
          ports:
            - containerPort: 8080

Note que commonLabels e commonAnnotations são automaticamente adicionados a todos os recursos definidos na base, garantindo consistência de metadados.

4. Overlays: Customização por Ambiente

Os overlays são onde a mágica acontece. Cada ambiente pode modificar seletivamente partes da base sem duplicar arquivos inteiros.

overlays/dev/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

namePrefix: dev-

patchesStrategicMerge:
  - deployment-patch.yaml

configMapGenerator:
  - name: app-config
    literals:
      - LOG_LEVEL=debug
      - API_URL=http://localhost:8080

overlays/dev/deployment-patch.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: meu-app
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: app
          image: meu-app:dev-latest
          envFrom:
            - configMapRef:
                name: app-config

Para produção, podemos usar patchesJson6902 para alterações mais precisas:

overlays/prod/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

nameSuffix: -prod

patchesJson6902:
  - target:
      group: apps
      version: v1
      kind: Deployment
      name: meu-app
    patch: |
      - op: replace
        path: /spec/replicas
        value: 5
      - op: replace
        path: /spec/template/spec/containers/0/image
        value: meu-app:stable

images:
  - name: meu-app
    newTag: v1.2.3-prod

O uso de namePrefix e nameSuffix evita conflitos quando múltiplos ambientes compartilham o mesmo namespace, enquanto patchesStrategicMerge e patchesJson6902 oferecem granularidade na customização.

5. Gerenciamento de ConfigMaps e Secrets com Kustomize

Uma das funcionalidades mais poderosas do Kustomize é a geração automática de ConfigMaps e Secrets com hash. Quando o conteúdo muda, o Kustomize gera um novo nome com hash, forçando o rolling update dos Pods que o referenciam.

base/kustomization.yaml (adicione):

secretGenerator:
  - name: db-credentials
    literals:
      - username=admin
      - password=supersecret
    type: Opaque

configMapGenerator:
  - name: app-config
    files:
      - configs/app.properties

O comportamento de hash garante que alterações em configurações disparem atualizações automáticas, sem necessidade de reinicializações manuais.

6. Transformações Avançadas e Plugins

O campo images permite substituir tags de imagem de forma declarativa:

images:
  - name: nginx
    newName: myregistry.com/nginx
    newTag: 1.25-alpine

Para substituições mais complexas, o Kustomize suporta vars que permitem injetar valores de outros recursos em campos específicos. Plugins executáveis estendem ainda mais as capacidades, permitindo transformações customizadas escritas em qualquer linguagem.

7. Fluxo de Trabalho DevOps com Kustomize

Em uma pipeline CI/CD típica, o fluxo é simples:

# Construir a configuração final do ambiente
kustomize build overlays/prod/ > output.yaml

# Validar a saída
kustomize build overlays/prod/ | kubectl apply --dry-run=client -f -

# Aplicar ao cluster
kustomize build overlays/prod/ | kubectl apply -f -

Para GitOps com ArgoCD ou Flux, o Kustomize é nativamente suportado. Basta apontar o diretório do overlay desejado como fonte da aplicação:

# Exemplo de Application do ArgoCD
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
  source:
    repoURL: https://github.com/meu-repo/meu-app
    path: overlays/prod
    kustomize: {}

8. Boas Práticas e Troubleshooting

  • Versionamento completo: Sempre versionar toda a estrutura de diretórios do Kustomize no Git, incluindo bases e overlays.
  • Overlays enxutos: Cada overlay deve conter apenas as diferenças necessárias. Evite duplicar patches para o mesmo recurso em overlays diferentes.
  • Depuração com kustomize build: Use kustomize build overlays/dev/ para inspecionar o YAML final antes de aplicar. Isso ajuda a identificar problemas de merge ou patches malformados.
  • Testes automatizados: Incorpore kustomize build --enable-helm em testes de pipeline para validar que todos os overlays produzem saída válida.
  • Consistência de labels: Use commonLabels na base para garantir que todos os recursos tenham labels consistentes, facilitando consultas e monitoramento.

O Kustomize resolve o problema de gerenciamento de configurações por ambiente de forma elegante e declarativa, mantendo a simplicidade dos YAMLs puros enquanto oferece poder de transformação. Quando combinado com práticas DevOps e GitOps, ele se torna uma ferramenta indispensável para qualquer equipe que opera Kubernetes em múltiplos ambientes.

Referências