Generators do Kustomize e o Sufixo de Hash
Objective
O Kustomize consegue criar ConfigMaps e Secrets a partir de literals, arquivos .env e arquivos comuns, em vez de você escrevê-las em YAML. Os objetos gerados ganham um sufixo de hash calculado a partir do conteúdo (app-config-g5t6m8m4hk), e o Kustomize reescreve todas as referências a eles. A consequência é o principal motivo para usar generators: mude um valor, e os templates de Pod que o referenciam mudam também, o que dispara um rolling update automaticamente. Este conceito cobre configMapGenerator e secretGenerator (literals, envs, files, type), behavior: merge e replace entre camadas, o sufixo de hash e quando desligá-lo.
Use Cases
- Configuração por ambiente empilhada sobre padrões compartilhados.
- Criar as Secrets de banco e de registry de um ambiente a partir de arquivos
.enve JSON locais que nunca entram no Git. - Reiniciar Pods automaticamente quando a configuração deles muda.
- Objetos que ferramentas externas referenciam por um nome fixo (e que por isso não podem ganhar sufixo).
Deep Dive
configMapGenerator
plaintextconfigMapGenerator: - name: app-config literals: - LOG_LEVEL=INFO - FEATURE_X=false envs: - app.env # linhas CHAVE=VALOR, cada uma vira uma chave files: - application.yaml # chave = nome do arquivo, valor = conteúdo - logging=logging-prod.yaml # chave renomeada para "logging"
literals e envs produzem uma chave por variável, ideal para envFrom. files produz uma chave por arquivo, ideal para montagem em volume.
Camadas: behavior merge e replace
Um generator num overlay com o mesmo nome de um da base precisa dizer o que fazer. Verificado: omitir o behavior falha o build:
plaintextError: merging from generator ... ConfigMap ... Name:"app-config" ... exists; can not use behavior: 'unspecified', behavior must be merge or replace
behavior: mergeadiciona chaves e sobrescreve as existentes. Verificado: baseLOG_LEVEL=info, FEATURE_X=false+ componentLOG_LEVEL=debug+ overlayFEATURE_X=true, ENVIRONMENT=stagingproduziramENVIRONMENT=staging, FEATURE_X=true, LOG_LEVEL=debug.behavior: replacedescarta os dados da base por completo. Verificado:replacecomONLY=1produziu uma ConfigMap contendo sóONLY: "1".behavior: create(o padrão) exige que ainda não exista objeto com esse nome.
secretGenerator
plaintextsecretGenerator: - name: db-credentials envs: [db.env] # DB_USER=..., DB_PASSWORD=... - name: client-tls files: [ca.crt, client.properties] - name: regcred type: kubernetes.io/dockerconfigjson files: [.dockerconfigjson=registry-config.json] - name: api-tls type: kubernetes.io/tls files: [tls.crt=certs/api.crt, tls.key=certs/api.key]
- O
typepadrão éOpaque. Secrets tipadas precisam dos nomes de chave certos (.dockerconfigjson,tls.crt/tls.key), daí a sintaxe de renomearchave=arquivo. - Os arquivos de origem são lidos na hora do build a partir do diretório do overlay. Mantenha-os fora do Git (
.gitignore), num gerenciador de senhas, ou criptografados (SOPS com um plugin do Kustomize como o KSOPS). Um secretGenerator cujo.envestá commitado em texto puro não é melhor que um YAML de Secret commitado. - As regras do env file são as mesmas do
kubectl --from-env-file: umCHAVE=VALORpor linha, comentários com#, e aspas mantidas literalmente como parte do valor.
O sufixo de hash e rollouts automáticos
O nome gerado é <nome>-<hash do conteúdo>, e o Kustomize reescreve as referências em envFrom, env.valueFrom, volumes, imagePullSecrets e outros campos conhecidos. Verificado no build do overlay: configMapRef: {name: app-config-g5t6m8m4hk} e secretRef: {name: db-credentials-dfcfkgfmh9}.
Mude um valor e o hash muda, então:
- uma ConfigMap nova é criada (a antiga não é modificada),
- o template de Pod do Deployment passa a referenciar o nome novo,
- a mudança de template dispara um rolling update normal,
- voltar o Deployment (
rollout undo) restaura a referência à ConfigMap antiga, que ainda existe, então configuração e código voltam juntos.
Sem o sufixo, atualizar uma ConfigMap não muda nada nos Pods em execução que a leem como variáveis de ambiente, e nada os reinicia.
O outro lado: ConfigMaps e Secrets geradas antigas nunca são apagadas pelo kubectl apply -k. Elas se acumulam. Limpe periodicamente, ou aplique com pruning (kubectl apply --prune com um label selector, ou ApplySets), sabendo que o pruning remove o objeto antigo de que o rollout undo precisaria.
Desligando o sufixo
Alguns consumidores precisam de um nome estável: uma Secret referenciada no tls.secretName de um Ingress gerenciado por outra ferramenta, uma ConfigMap lida pelo nome por um operator, uma Secret de registry aplicada numa ServiceAccount.
plaintextgeneratorOptions: disableNameSuffixHash: true # para todo generator desta kustomization
ou por generator:
plaintextsecretGenerator: - name: regcred type: kubernetes.io/dockerconfigjson files: [.dockerconfigjson=registry-config.json] options: disableNameSuffixHash: true
Verificado: com disableNameSuffixHash: true as Secrets ficaram exatamente com os nomes regcred e certs. Você perde então o rollout automático desses objetos; reinicie os consumidores você mesmo depois de mudá-los (kubectl rollout restart).
O generatorOptions também define labels e annotations nos objetos gerados, e immutable: true os marca como imutáveis (menos watches no API server; qualquer mudança precisa produzir um nome novo, o que o hash já faz).
Trade-offs
- Sufixo de hash vs nomes estáveis. O sufixo dá rollouts de configuração automáticos e reversíveis e acumula objetos antigos; nomes estáveis são simples de referenciar e exigem restarts manuais.
- Generators vs ConfigMaps em YAML. Generators mantêm a configuração em formatos naturais (
.env,.yaml,.conf) e adicionam o hash; objetos YAML puros são exatamente o que você vê, sem referências reescritas. - Secrets de arquivos locais vs um gerenciador de segredos. Arquivos locais são simples e dependem da máquina que roda o build; External Secrets Operator ou Sealed Secrets mantêm os segredos reproduzíveis a partir do Git ou de um cofre, ao custo de mais um componente.