Usar ConfigMaps e Secrets no Node.js permite separar configuração e credenciais da imagem do container. Em vez de criar uma nova imagem para cada ambiente, o Kubernetes injeta valores como URLs, limites, flags, certificados e tokens durante a implantação.
ConfigMaps são destinados a dados de configuração não confidenciais. Secrets armazenam informações sensíveis, mas o nome não significa criptografia automática em todas as camadas. Ambos podem ser expostos como variáveis de ambiente ou arquivos montados, e cada formato possui efeitos diferentes em atualização, validação e segurança.
Neste guia, você aprenderá a criar recursos, consumir valores no Node.js, validar configuração, montar arquivos, atualizar sem interromper o serviço, proteger segredos, usar immutable resources e integrar com rollout e observabilidade.
O que são ConfigMaps?
ConfigMap é um objeto do Kubernetes que armazena pares chave-valor ou arquivos de configuração não sensíveis. A documentação oficial de ConfigMaps explica formatos, montagens e atualizações.
Exemplos adequados:
- nome do ambiente;
- nível de log;
- URL pública do serviço;
- limites de paginação;
- feature flags não sensíveis;
- arquivo JSON de regras;
- configuração de cliente HTTP.
Para fundamentos de configuração, consulte Variáveis de Ambiente no Node.js.
O que são Secrets?
Secret é um objeto para dados confidenciais, como tokens, senhas e chaves. A documentação oficial de Secrets descreve tipos e boas práticas.
Exemplos:
- senha do PostgreSQL;
- token de API;
- chave privada;
- certificado de cliente;
- segredo de webhook;
- credencial de registry;
- chave de sessão.
Base64 usado no manifesto é apenas codificação. Quem possui acesso ao objeto pode decodificar o valor.
Criando um ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: my-api-config
data:
NODE_ENV: production
LOG_LEVEL: info
MAX_PAGE_SIZE: "100"
PUBLIC_URL: https://api.example.comTodos os valores em data são strings. Converta números e booleanos explicitamente na aplicação.
Criando um Secret
apiVersion: v1
kind: Secret
metadata:
name: my-api-secrets
type: Opaque
stringData:
DATABASE_URL: postgresql://user:password@db/app
WEBHOOK_SECRET: change-mestringData facilita autoria; a API converte para data. Não versionar o arquivo com valores reais continua sendo obrigatório.
Injetando ConfigMap como ambiente
envFrom:
- configMapRef:
name: my-api-configAs chaves viram variáveis de ambiente do container.
Injetando Secret como ambiente
envFrom:
- secretRef:
name: my-api-secretsEsse método é simples, mas processos e ferramentas com acesso ao ambiente podem visualizar valores. Evite imprimir process.env.
Selecionando chaves individuais
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: my-api-config
key: LOG_LEVEL
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: my-api-secrets
key: DATABASE_URLReferências explícitas documentam dependências e evitam importar chaves desnecessárias.
Lendo no Node.js
const config = {
nodeEnv: process.env.NODE_ENV,
logLevel: process.env.LOG_LEVEL,
databaseUrl: process.env.DATABASE_URL,
maxPageSize: Number(process.env.MAX_PAGE_SIZE)
};Não use os valores diretamente sem validação.
Validação na inicialização
function requireString(name) {
const value = process.env[name];
if (!value || value.trim() === '') {
throw new Error(`Configuração ausente: ${name}`);
}
return value;
}
function positiveInteger(name, fallback) {
const raw = process.env[name];
if (raw === undefined) return fallback;
const value = Number(raw);
if (!Number.isInteger(value) || value < 1) {
throw new Error(`Configuração inválida: ${name}`);
}
return value;
}Falhar cedo é melhor do que iniciar com uma credencial vazia ou limite incorreto.
Não exponha valores no erro
Mensagens devem citar o nome da variável, não o conteúdo:
throw new Error('DATABASE_URL inválida');Não concatene a URL completa, porque ela pode conter senha.
Montando ConfigMap como arquivo
volumes:
- name: app-config
configMap:
name: my-api-config-files
containers:
- name: api
volumeMounts:
- name: app-config
mountPath: /etc/my-api
readOnly: trueUm ConfigMap pode conter um arquivo:
data:
rules.json: |
{
"maxAttempts": 3,
"regions": ["br", "us"]
}Lendo arquivo de configuração
const fs = require('node:fs/promises');
async function loadRules() {
const text = await fs.readFile(
'/etc/my-api/rules.json',
'utf8'
);
return JSON.parse(text);
}Valide o JSON com schema. Consulte File System no Node.js para erros e caminhos.
Montando Secret como arquivo
volumes:
- name: tls-secret
secret:
secretName: client-tls
defaultMode: 0400
volumeMounts:
- name: tls-secret
mountPath: /etc/my-api/tls
readOnly: trueArquivos são adequados para certificados, chaves e credenciais que bibliotecas esperam receber por caminho.
Permissões do arquivo
defaultMode usa representação numérica YAML. Teste as permissões finais e o usuário do container. O processo não deve rodar como root apenas para ler um Secret.
Veja Docker Multi-stage para Node.js para imagens com usuário sem privilégio.
Variável de ambiente versus arquivo
- Ambiente: simples, lido no startup, não atualiza no processo.
- Arquivo: suporta conteúdo estruturado e pode ser atualizado pelo volume.
Valores de ambiente são capturados quando o container inicia. Alterar o ConfigMap não modifica process.env de um pod já em execução.
Atualizações em volumes
Volumes montados podem refletir atualizações após um intervalo. A mudança não é instantânea e não ocorre quando o arquivo foi montado com subPath.
Problema do subPath
volumeMounts:
- name: app-config
mountPath: /etc/my-api/rules.json
subPath: rules.jsonMontagens com subPath normalmente não recebem atualizações automáticas. Use diretório completo ou reinicie os pods.
Reload de configuração
Uma aplicação pode observar o arquivo e recarregar:
let currentRules;
async function reloadRules() {
const next = await loadAndValidateRules();
currentRules = Object.freeze(next);
}Faça troca atômica: só substitua a configuração após leitura e validação completas.
Watchers
O Kubernetes pode trocar links simbólicos durante atualização. Um watcher precisa observar o diretório, não presumir que o inode do arquivo permanece o mesmo.
Em muitos sistemas, um rollout explícito é mais previsível que hot reload de configuração crítica.
Rollout após mudança
Alterar um ConfigMap referenciado não modifica o template do Deployment, portanto não cria pods automaticamente. Estratégias:
- alterar uma annotation com checksum;
- executar
kubectl rollout restart; - usar operador de reloader;
- versionar o nome do ConfigMap;
- automatizar no pipeline.
Checksum no template
Ferramentas como Helm podem calcular hash do manifesto e colocá-lo na annotation do pod. Quando a configuração muda, o Deployment faz rollout.
ConfigMap imutável
immutable: trueRecursos imutáveis reduzem mudanças acidentais e carga de watches. Para atualizar, crie outro nome e altere o Deployment.
Secret imutável
Secrets também podem ser imutáveis. Essa abordagem combina bem com nomes versionados e rotação controlada.
Rotação de segredo
Uma rotação segura pode manter credencial antiga e nova durante uma janela:
- criar nova credencial no provedor;
- atualizar o Secret;
- fazer rollout;
- confirmar adoção;
- revogar a credencial antiga.
Revogar antes do rollout causa indisponibilidade.
Chaves de assinatura
Para JWT ou webhooks, inclua identificador da chave e aceite a anterior durante rotação. Consulte JWT Seguro no Node.js.
Criptografia no etcd
Secrets podem ser armazenados sem criptografia em repouso se o cluster não estiver configurado. Ative encryption at rest e controle acesso ao etcd e backups.
RBAC
Conceda permissão apenas aos service accounts que precisam ler o Secret. Evite papéis amplos com acesso a todos os Secrets do namespace.
Namespace
ConfigMaps e Secrets são namespaced. Um pod normalmente referencia recursos do próprio namespace, o que ajuda a separar ambientes.
Não use Secret para autorização interna
O fato de um pod conseguir ler um Secret não significa que toda requisição recebida está autorizada. Autenticação e autorização da aplicação continuam necessárias.
External Secrets
Em ambientes maduros, um operador pode sincronizar dados de um gerenciador externo como Vault ou serviços de nuvem. Isso reduz segredos manuais em Git, mas adiciona dependência operacional.
Sealed Secrets e GitOps
Ferramentas de criptografia permitem manter um manifesto cifrado no repositório. Proteja chaves de decriptação e considere rotação e recuperação.
Não commite segredo em Base64
Qualquer pessoa consegue decodificar:
echo 'cGFzc3dvcmQ=' | base64 --decodeUse placeholders, templates ou integração segura no pipeline.
Configuração por ambiente
Mantenha o mesmo conjunto de chaves em desenvolvimento, homologação e produção. Valores mudam, mas o contrato de configuração deve permanecer consistente.
Defaults seguros
Use defaults apenas para opções não críticas:
const logLevel = process.env.LOG_LEVEL || 'info';Não use senha ou URL de produção padrão.
Feature flags
Flags simples podem ficar em ConfigMap, mas sistemas com avaliação por usuário, auditoria e rollout gradual se beneficiam de uma plataforma específica.
Readiness
Se a configuração obrigatória está ausente, o processo deve falhar no startup. Se um arquivo recarregado fica inválido, mantenha a última versão válida e marque métrica de erro.
Consulte Probes Kubernetes em Node.js.
Graceful shutdown
Durante rotação e rollout, trate SIGTERM, pare de aceitar requisições e feche conexões. Consulte Graceful Shutdown no Node.js.
Observabilidade
Registre apenas metadados seguros:
- versão da configuração;
- hash não reversível;
- horário de carregamento;
- sucesso ou erro de validação;
- nome das chaves ausentes;
- rollout atual.
Nunca registre valores de Secrets.
Métricas
Exemplos:
config_reload_total;config_reload_errors_total;config_last_success_timestamp;secret_rotation_age_seconds.
Testes
Cubra:
- variável obrigatória ausente;
- número inválido;
- arquivo JSON inválido;
- permissão negada;
- Secret ausente;
- reload válido;
- reload inválido;
- rotação com credencial antiga;
- pod sem RBAC;
- rollout após alteração.
Teste de configuração
test('rejeita MAX_PAGE_SIZE inválido', () => {
process.env.MAX_PAGE_SIZE = 'zero';
assert.throws(
() => loadConfiguration(),
/MAX_PAGE_SIZE/
);
});Erros comuns
- Secret em Git: Base64 não protege o valor.
- envFrom amplo: o processo recebe dados desnecessários.
- Sem validação: a aplicação inicia quebrada.
- Esperar atualização de env: o pod mantém o valor antigo.
- subPath com hot reload: o arquivo não muda.
- Logar process.env: credenciais vazam.
- Revogar antes do rollout: pods antigos falham.
Boas práticas
- Separe configuração e segredo.
- Valide no startup.
- Referencie chaves explicitamente.
- Use arquivos para certificados.
- Proteja Secrets com RBAC e criptografia.
- Evite valores reais em Git.
- Use rollout por checksum.
- Planeje rotação.
- Não registre valores.
- Teste atualização e rollback.
Conclusão
Usar ConfigMaps e Secrets no Node.js separa configuração da imagem e permite implantações consistentes entre ambientes. ConfigMaps guardam opções não confidenciais; Secrets concentram credenciais que exigem proteção adicional.
A segurança e previsibilidade dependem de validação, RBAC, criptografia em repouso, rollout controlado e rotação. Com nomes versionados ou checksums, usuário sem privilégio e logs sem valores sensíveis, a aplicação recebe configuração dinâmica sem transformar o cluster em fonte de vazamento ou inconsistência.




