kb.erickguedes.com
Kubernetes: Orquestração em Produção

ConfigMaps, Secrets e Volumes

Aula 4 de 8

ConfigMaps — Configuração Não Sensível

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  NODE_ENV: production
  LOG_LEVEL: info
  api.yaml: |
    host: "0.0.0.0"
    port: 3000
    timeout: 30

Injetando ConfigMaps

apiVersion: v1
kind: Pod
spec:
  containers:
    - name: app
      image: minha-app
      # 1. Como variável de ambiente
      env:
        - name: NODE_ENV
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: NODE_ENV
      # 2. Todas as chaves como env
      envFrom:
        - configMapRef:
            name: app-config
      # 3. Como volume (arquivo)
      volumeMounts:
        - name: config
          mountPath: /etc/app
  volumes:
    - name: config
      configMap:
        name: app-config
kubectl create configmap app-config --from-file=config.yaml
kubectl create configmap app-config --from-literal=KEY=value
kubectl create configmap app-config --from-env-file=.env

Secrets — Configuração Sensível

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
data:
  username: YWRtaW4=           # base64(admin)
  password: U2VuaGFTZWd1cmExIQ==  # base64(SenhaSegura1!)
# Criar secret
kubectl create secret generic db-creds \
  --from-literal=username=admin \
  --from-literal=password=SenhaSegura1!

# Ler secret (base64 decodificado)
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d

Consumindo Secrets

apiVersion: v1
kind: Pod
spec:
  containers:
    - name: app
      image: minha-app
      # Como env var
      env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: password
      # Como volume
      volumeMounts:
        - name: secrets
          mountPath: /run/secrets
          readOnly: true
  volumes:
    - name: secrets
      secret:
        secretName: db-credentials
        defaultMode: 0400

Volumes — Armazenamento

apiVersion: v1
kind: Pod
spec:
  containers:
    - name: app
      image: nginx:alpine
      volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
        - name: logs
          mountPath: /var/log/nginx
        - name: tmp
          mountPath: /tmp
  volumes:
    - name: html
      configMap:
        name: site-html
    - name: logs
      emptyDir: {}
    - name: tmp
      emptyDir:
        medium: Memory  # tmpfs

PersistentVolume e PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: standard
---
apiVersion: v1
kind: Pod
spec:
  containers:
    - name: app
      image: postgres:16-alpine
      volumeMounts:
        - name: data
          mountPath: /var/lib/postgresql/data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: app-data
kubectl get pv    # volumes físicos
kubectl get pvc   # requests de volume

Storage Classes

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3
  fsType: ext4
reclaimPolicy: Retain    # ou Delete
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
kubectl get storageclass
kubectl patch pvc app-data -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'

ConfigMaps para config não sensível. Secrets para senhas/tokens (base64 é encoding, não encryption). Use External Secrets Operator ou Vault para secrets reais em produção.