DevOps & CI/CD

ConfigMaps e Secrets em Kubernetes: Gerenciando Configuração na Prática

12 min de leitura

ConfigMaps e Secrets em Kubernetes: Gerenciando Configuração na Prática

ConfigMaps e Secrets em Kubernetes: Gerenciando Configuração Quando você trabalha com Kubernetes em produção, rapidamente percebe que hardcoding configurações dentro de imagens Docker é uma péssima prática. ConfigMaps e Secrets são os mecanismos nativos do Kubernetes para separar dados de configuração da lógica da aplicação. A diferença fundamental é simples: ConfigMaps armazenam dados não-sensíveis em texto plano, enquanto Secrets são projetados para dados sensíveis como senhas e tokens, com suporte a encoding em base64. Neste artigo, vou guiá-lo através dos conceitos práticos, mostrando como estruturar suas aplicações para aproveitar essas ferramentas corretamente. Você aprenderá não apenas a sintaxe, mas o porquê dessas decisões arquiteturais importam para escalabilidade e manutenção. Entendendo ConfigMaps: Configuração sem Sensibilidade O que é um ConfigMap e quando usá-lo Um ConfigMap é um objeto Kubernetes que permite armazenar dados de configuração em pares chave-valor. Pense nele como um arquivo de properties ou um arquivo que vive dentro do cluster e pode ser montado em seus Pods. O

<h2>ConfigMaps e Secrets em Kubernetes: Gerenciando Configuração</h2>

<p>Quando você trabalha com Kubernetes em produção, rapidamente percebe que hardcoding configurações dentro de imagens Docker é uma péssima prática. ConfigMaps e Secrets são os mecanismos nativos do Kubernetes para separar dados de configuração da lógica da aplicação. A diferença fundamental é simples: <strong>ConfigMaps armazenam dados não-sensíveis em texto plano</strong>, enquanto <strong>Secrets são projetados para dados sensíveis como senhas e tokens</strong>, com suporte a encoding em base64.</p>

<p>Neste artigo, vou guiá-lo através dos conceitos práticos, mostrando como estruturar suas aplicações para aproveitar essas ferramentas corretamente. Você aprenderá não apenas a sintaxe, mas o porquê dessas decisões arquiteturais importam para escalabilidade e manutenção.</p>

<h2>Entendendo ConfigMaps: Configuração sem Sensibilidade</h2>

<h3>O que é um ConfigMap e quando usá-lo</h3>

<p>Um ConfigMap é um objeto Kubernetes que permite armazenar dados de configuração em pares chave-valor. Pense nele como um arquivo de properties ou um arquivo <code>.env</code> que vive dentro do cluster e pode ser montado em seus Pods. O uso mais comum é para variáveis de ambiente que mudam entre ambientes (desenvolvimento, staging, produção), como URLs de bancos de dados, timeouts, níveis de log, e parâmetros de aplicação.</p>

<p>A vantagem de usar ConfigMaps é que você pode atualizar configurações sem recriar suas imagens Docker. Você muda o ConfigMap, e na próxima vez que o Pod for criado ou reiniciado, ele recebe a nova configuração. Isso acelera o ciclo de desenvolvimento e reduz significativamente o tamanho e complexidade das imagens.</p>

<h3>Criando ConfigMaps: Métodos Práticos</h3>

<p>Existem várias formas de criar um ConfigMap. A mais simples é usar argumentos diretos no <code>kubectl</code>:</p>

<pre><code class="language-bash">kubectl create configmap app-config \

--from-literal=DATABASE_URL=postgresql://db:5432/myapp \

--from-literal=LOG_LEVEL=info \

--from-literal=MAX_CONNECTIONS=100</code></pre>

<p>Para configurações mais complexas ou que vêm de arquivos, você pode usar a abordagem declarativa com YAML:</p>

<pre><code class="language-yaml">apiVersion: v1

kind: ConfigMap

metadata:

name: app-config

namespace: production

data:

DATABASE_URL: postgresql://db:5432/myapp

LOG_LEVEL: info

MAX_CONNECTIONS: &quot;100&quot;

app.properties: |

server.port=8080

server.shutdown=graceful

cache.ttl.seconds=3600</code></pre>

<p>Note que chaves com conteúdo multilinhas (como <code>app.properties</code>) usam o pipe <code>|</code>. Quando você tem arquivos inteiros de configuração, pode referenciá-los diretamente:</p>

<pre><code class="language-bash">kubectl create configmap nginx-config --from-file=nginx.conf --from-file=default.conf</code></pre>

<h3>Consumindo ConfigMaps em Pods</h3>

<p>Uma vez criado, você pode injetar ConfigMaps em seus Pods de duas formas principais. <strong>Como variáveis de ambiente</strong> é a mais comum:</p>

<pre><code class="language-yaml">apiVersion: v1

kind: Pod

metadata:

name: my-app

spec:

containers:

  • name: app

image: myapp:1.0

env:

  • name: DATABASE_URL

valueFrom:

configMapKeyRef:

name: app-config

key: DATABASE_URL

  • name: LOG_LEVEL

valueFrom:

configMapKeyRef:

name: app-config

key: LOG_LEVEL</code></pre>

<p>Ou você pode expor <strong>todas as chaves</strong> do ConfigMap de uma só vez usando <code>envFrom</code>:</p>

<pre><code class="language-yaml">apiVersion: v1

kind: Pod

metadata:

name: my-app

spec:

containers:

  • name: app

image: myapp:1.0

envFrom:

  • configMapRef:

name: app-config</code></pre>

<p>A segunda abordagem é <strong>montar o ConfigMap como um volume</strong>, útil quando você precisa de arquivos completos de configuração:</p>

<pre><code class="language-yaml">apiVersion: v1

kind: Pod

metadata:

name: nginx-app

spec:

containers:

  • name: nginx

image: nginx:latest

volumeMounts:

  • name: config-volume

mountPath: /etc/nginx/conf.d

volumes:

  • name: config-volume

configMap:

name: nginx-config</code></pre>

<p>Neste caso, cada chave do ConfigMap vira um arquivo dentro do diretório <code>/etc/nginx/conf.d</code>. Se o ConfigMap tiver uma chave <code>default.conf</code>, você encontrará um arquivo <code>/etc/nginx/conf.d/default.conf</code> dentro do container.</p>

<h2>Secrets: Protegendo Dados Sensíveis</h2>

<h3>Diferenças entre ConfigMap e Secret</h3>

<p>Enquanto ConfigMaps são para dados públicos, <strong>Secrets são para informações sensíveis</strong>: senhas de banco de dados, tokens de API, chaves SSH, certificados TLS. A principal diferença técnica é que Secrets são armazenados em base64 por padrão (etcd) e o Kubernetes oferece opções de criptografia em repouso. Porém, <strong>não confunda base64 com encriptação</strong>: base64 é apenas encoding, não oferece segurança real.</p>

<p>Se você precisa de segurança real, você deve configurar encriptação em repouso no etcd. Mas mesmo com base64, Secrets têm um propósito importante: separam dados sensíveis de dados públicos, facilitam rotação de credenciais, e permitem controles RBAC (Role-Based Access Control) mais granulares.</p>

<h3>Criando Secrets de Forma Segura</h3>

<p>Para criar um Secret com dados sensíveis, use <code>kubectl create secret</code>:</p>

<pre><code class="language-bash">kubectl create secret generic db-credentials \

--from-literal=username=admin \

--from-literal=password=mysecurepassword123</code></pre>

<p>Ou de forma declarativa (mas cuidado com o controle de versão!):</p>

<pre><code class="language-yaml">apiVersion: v1

kind: Secret

metadata:

name: db-credentials

type: Opaque

data:

username: YWRtaW4= # base64 encoded &quot;admin&quot;

password: bXlzZWN1cmVwYXNzd29yZDEyMw== # base64 encoded &quot;mysecurepassword123&quot;</code></pre>

<p>Para gerar os valores em base64 seguramente (sem colocar senhas em histórico de shell):</p>

<pre><code class="language-bash">echo -n &quot;mysecurepassword123&quot; | base64</code></pre>

<p>Para Secrets de tipo <code>docker-registry</code> (credentials para puxar imagens privadas):</p>

<pre><code class="language-bash">kubectl create secret docker-registry registry-credentials \

--docker-server=docker.io \

--docker-username=myusername \

--docker-password=mypassword \

--docker-email=myemail@example.com</code></pre>

<p>E para certificados TLS:</p>

<pre><code class="language-bash">kubectl create secret tls tls-secret \

--cert=path/to/cert.crt \

--key=path/to/key.key</code></pre>

<h3>Consumindo Secrets em Pods</h3>

<p>Secrets são consumidos de forma idêntica aos ConfigMaps. Como variáveis de ambiente:</p>

<pre><code class="language-yaml">apiVersion: v1

kind: Pod

metadata:

name: app-with-db

spec:

containers:

  • name: app

image: myapp:1.0

env:

  • name: DB_USER

valueFrom:

secretKeyRef:

name: db-credentials

key: username

  • name: DB_PASSWORD

valueFrom:

secretKeyRef:

name: db-credentials

key: password</code></pre>

<p>Ou montado como volume (para quando você precisa de arquivos, como certificados):</p>

<pre><code class="language-yaml">apiVersion: v1

kind: Pod

metadata:

name: secure-app

spec:

containers:

  • name: app

image: myapp:1.0

volumeMounts:

  • name: tls-certs

mountPath: /etc/tls

readOnly: true

volumes:

  • name: tls-certs

secret:

secretName: tls-secret</code></pre>

<p>Para usar Secrets como credenciais de pull de imagens privadas, configure-o no <code>imagePullSecrets</code>:</p>

<pre><code class="language-yaml">apiVersion: v1

kind: Pod

metadata:

name: private-image-app

spec:

imagePullSecrets:

  • name: registry-credentials

containers:

  • name: app

image: private.docker.io/myapp:1.0</code></pre>

<h2>Boas Práticas e Padrões Reais</h2>

<h3>Organizando ConfigMaps e Secrets por Ambiente</h3>

<p>Em um projeto real, você não quer um único ConfigMap gigante. Organize por função e ambiente. Exemplo de estrutura para uma aplicação com múltiplos serviços:</p>

<pre><code class="language-yaml"># namespace: production

---

apiVersion: v1

kind: ConfigMap

metadata:

name: api-config

labels:

app: api

env: production

data:

LOG_LEVEL: warn

CACHE_TTL: &quot;3600&quot;

API_TIMEOUT: &quot;30&quot;

---

apiVersion: v1

kind: ConfigMap

metadata:

name: worker-config

labels:

app: worker

env: production

data:

QUEUE_WORKERS: &quot;10&quot;

RETRY_ATTEMPTS: &quot;3&quot;

---

apiVersion: v1

kind: Secret

metadata:

name: api-secrets

labels:

app: api

env: production

type: Opaque

data:

# Encode: echo -n &quot;your-api-key&quot; | base64

API_KEY: eW91ci1hcGkta2V5

JWT_SECRET: eW91ci1qd3Qtc2VjcmV0</code></pre>

<p>Isso facilita a manutenção e permite diferentes configurações para staging, development, etc.</p>

<h3>Validação e Versionamento</h3>

<p>Sempre valide seu YAML antes de aplicar:</p>

<pre><code class="language-bash">kubectl apply --dry-run=client -f config.yaml</code></pre>

<p>Use controle de versão para seus ConfigMaps e Secrets. Uma prática comum é manter versões numeradas:</p>

<pre><code class="language-bash">kubectl create configmap app-config-v1 --from-file=app.properties

kubectl create configmap app-config-v2 --from-file=app.properties # quando houver mudanças</code></pre>

<p>Depois, você atualiza os Pods para usar a nova versão. O Kubernetes não atualiza Pods automaticamente quando um ConfigMap ou Secret é modificado — você precisa recriar os Pods ou usar ferramentas como Reloader.</p>

<h3>Rotação de Secrets em Produção</h3>

<p>Nunca comita Secrets em Git. Use uma solução de gerenciamento de secrets como Vault, AWS Secrets Manager, ou Azure Key Vault, e sincronize com Kubernetes usando operadores como External Secrets Operator:</p>

<pre><code class="language-yaml">apiVersion: external-secrets.io/v1beta1

kind: SecretStore

metadata:

name: vault-backend

spec:

provider:

vault:

server: &quot;https://vault.example.com&quot;

path: &quot;secret&quot;

auth:

kubernetes:

mountPath: &quot;kubernetes&quot;

role: &quot;my-app-role&quot;

---

apiVersion: external-secrets.io/v1beta1

kind: ExternalSecret

metadata:

name: db-credentials

spec:

refreshInterval: 1h

secretStoreRef:

name: vault-backend

kind: SecretStore

target:

name: db-credentials

creationPolicy: Owner

data:

  • secretKey: username

remoteRef:

key: myapp/db

property: username

  • secretKey: password

remoteRef:

key: myapp/db

property: password</code></pre>

<p>Isso sincroniza secrets de forma dinâmica e segura, permitindo rotação centralizada.</p>

<h2>Conclusão</h2>

<p>Você aprendeu que <strong>ConfigMaps e Secrets são ferramentas essenciais para separar configuração de código</strong>, permitindo que suas imagens Docker sejam imutáveis e reutilizáveis em diferentes ambientes. A diferença não é apenas técnica — é arquitetural: ConfigMaps para dados públicos e Secrets para sensíveis.</p>

<p>A segunda lição é que <strong>encoding em base64 (usado por padrão em Secrets) não é encriptação real</strong>. Para produção, você deve configurar encriptação em repouso no etcd e considerar soluções externas de gerenciamento de secrets como HashiCorp Vault, que oferecem rotação automática, auditoria e controle de acesso mais granular.</p>

<p>Por último, <strong>organize ConfigMaps e Secrets por função, ambiente e app</strong>, valide sempre antes de aplicar, e automize a sincronização quando trabalhar com backends externos. Isso transforma Kubernetes de um orquestrador para um verdadeiro gerenciador de configuração corporativo.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://kubernetes.io/docs/concepts/configuration/configmap/" target="_blank" rel="noopener noreferrer">Kubernetes Official Documentation - ConfigMaps</a></li>

<li><a href="https://kubernetes.io/docs/concepts/configuration/secret/" target="_blank" rel="noopener noreferrer">Kubernetes Official Documentation - Secrets</a></li>

<li><a href="https://external-secrets.io/" target="_blank" rel="noopener noreferrer">External Secrets Operator - HashiCorp Vault Integration</a></li>

<li><a href="https://12factor.net/config" target="_blank" rel="noopener noreferrer">12 Factor App - Store config in the environment</a></li>

<li><a href="https://kubernetes.io/docs/concepts/configuration/secret/#security-properties" target="_blank" rel="noopener noreferrer">Kubernetes Security - Managing Secrets</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em DevOps & CI/CD

Incident Management: Runbooks, Post-mortems e Cultura de Confiabilidade na Prática
Incident Management: Runbooks, Post-mortems e Cultura de Confiabilidade na Prática

Incident Management: Fundamentos e Importância Incident Management é a discip...

Como Usar Azure para DevOps: AKS, Azure Pipelines e Resource Groups em Produção
Como Usar Azure para DevOps: AKS, Azure Pipelines e Resource Groups em Produção

Azure Resource Groups: Fundação da Organização em Nuvem Um Resource Group (Gr...

GitHub Actions: Workflows, Jobs, Steps e Actions Reutilizáveis na Prática
GitHub Actions: Workflows, Jobs, Steps e Actions Reutilizáveis na Prática

GitHub Actions: Dominando Workflows, Jobs, Steps e Actions Reutilizáveis GitH...