Capitulo 7: ConfigMaps y Secrets

Por: Artiko
k3skubernetesconfigmapssecrets

Capitulo 7: ConfigMaps y Secrets

< Volver al Indice del Tutorial

ConfigMaps

Un ConfigMap almacena datos de configuracion no sensibles en pares clave-valor. Permite desacoplar la configuracion del codigo de la aplicacion.

Crear desde Literal

kubectl create configmap app-config \
  --from-literal=DB_HOST=postgres-svc \
  --from-literal=DB_PORT=5432 \
  --from-literal=LOG_LEVEL=info

Crear desde Archivo

Si tienes un archivo de configuracion, por ejemplo app.properties:

database.host=postgres-svc
database.port=5432
log.level=info
kubectl create configmap app-config --from-file=app.properties

Crear desde YAML

Archivo configmap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DB_HOST: "postgres-svc"
  DB_PORT: "5432"
  LOG_LEVEL: "info"
  nginx.conf: |
    server {
      listen 80;
      server_name localhost;
      location / {
        proxy_pass http://backend-svc:3000;
      }
    }
kubectl apply -f configmap.yaml
kubectl get configmap app-config -o yaml

Inyectar ConfigMap como Variables de Entorno

Todas las claves con envFrom

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mi-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mi-app
  template:
    metadata:
      labels:
        app: mi-app
    spec:
      containers:
        - name: mi-app
          image: nginx:1.27-alpine
          envFrom:
            - configMapRef:
                name: app-config

Todas las claves del ConfigMap se convierten en variables de entorno del contenedor.

Claves especificas con valueFrom

spec:
  containers:
    - name: mi-app
      image: nginx:1.27-alpine
      env:
        - name: DATABASE_HOST
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: DB_HOST
        - name: DATABASE_PORT
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: DB_PORT

Montar ConfigMap como Volumen

Ideal para archivos de configuracion como nginx.conf, config.json, etc:

spec:
  containers:
    - name: nginx
      image: nginx:1.27-alpine
      volumeMounts:
        - name: config-vol
          mountPath: /etc/nginx/conf.d
  volumes:
    - name: config-vol
      configMap:
        name: app-config
        items:
          - key: nginx.conf
            path: default.conf

Cada clave del ConfigMap se convierte en un archivo dentro del directorio montado. Si el ConfigMap se actualiza, los archivos montados se actualizan automaticamente (puede tardar hasta 60 segundos).

Secrets

Los Secrets almacenan datos sensibles: passwords, tokens, claves SSH, certificados TLS. Kubernetes los almacena codificados en base64 (no cifrados por defecto).

Tipos de Secrets

TipoUso
OpaqueDatos genericos (passwords, tokens)
kubernetes.io/dockerconfigjsonCredenciales de registry privado
kubernetes.io/tlsCertificados TLS (cert + key)

Crear desde Literal

kubectl create secret generic db-credentials \
  --from-literal=DB_USER=admin \
  --from-literal=DB_PASSWORD=s3cr3tP4ss

Crear desde Archivo

# Crear archivos con los datos
echo -n "admin" > ./username.txt
echo -n "s3cr3tP4ss" > ./password.txt

kubectl create secret generic db-credentials \
  --from-file=DB_USER=./username.txt \
  --from-file=DB_PASSWORD=./password.txt

# Limpiar archivos locales
rm ./username.txt ./password.txt

Crear desde YAML

Los valores deben estar en base64:

echo -n "admin" | base64        # YWRtaW4=
echo -n "s3cr3tP4ss" | base64  # czNjcjN0UDRzcw==
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
data:
  DB_USER: YWRtaW4=
  DB_PASSWORD: czNjcjN0UDRzcw==

Alternativa sin codificar manualmente usando stringData:

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
stringData:
  DB_USER: admin
  DB_PASSWORD: s3cr3tP4ss
kubectl apply -f secret.yaml
kubectl get secret db-credentials -o yaml

Verificar un Secret

# Ver el secret (valores en base64)
kubectl get secret db-credentials -o yaml

# Decodificar un valor
kubectl get secret db-credentials -o jsonpath='{.data.DB_PASSWORD}' | base64 -d

Inyectar Secrets

Como variables de entorno

spec:
  containers:
    - name: mi-app
      image: mi-app:latest
      envFrom:
        - secretRef:
            name: db-credentials

O claves especificas:

spec:
  containers:
    - name: mi-app
      image: mi-app:latest
      env:
        - name: DATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: DB_PASSWORD

Como volumen

spec:
  containers:
    - name: mi-app
      image: mi-app:latest
      volumeMounts:
        - name: secret-vol
          mountPath: /etc/secrets
          readOnly: true
  volumes:
    - name: secret-vol
      secret:
        secretName: db-credentials

Los archivos montados tienen permisos 0644 por defecto. Puedes cambiarlos con defaultMode:

volumes:
  - name: secret-vol
    secret:
      secretName: db-credentials
      defaultMode: 0400

Buenas Practicas de Seguridad

No commitear Secrets en Git. Los manifiestos YAML con Secrets contienen datos en base64, que se decodifican trivialmente.

Para produccion, considera estas alternativas:

Otras practicas:

Ejemplo: App con Config de DB

Despleguemos una aplicacion que lee la configuracion de base de datos desde un ConfigMap y el password desde un Secret.

ConfigMap con configuracion

apiVersion: v1
kind: ConfigMap
metadata:
  name: db-config
data:
  DB_HOST: "postgres-svc"
  DB_PORT: "5432"
  DB_NAME: "miapp"

Secret con credenciales

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
stringData:
  DB_USER: app_user
  DB_PASSWORD: P4ssw0rd_Seguro

Deployment que consume ambos

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mi-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mi-app
  template:
    metadata:
      labels:
        app: mi-app
    spec:
      containers:
        - name: mi-app
          image: busybox
          command: ["sh", "-c"]
          args:
            - |
              echo "DB: $DB_USER@$DB_HOST:$DB_PORT/$DB_NAME"
              echo "Password length: $(echo -n $DB_PASSWORD | wc -c)"
              sleep 3600
          envFrom:
            - configMapRef:
                name: db-config
            - secretRef:
                name: db-secret
kubectl apply -f db-config.yaml
kubectl apply -f db-secret.yaml
kubectl apply -f mi-app-deployment.yaml

# Verificar que las variables se inyectan
kubectl logs -l app=mi-app

Salida esperada:

DB: app_user@postgres-svc:5432/miapp
Password length: 16

La configuracion no sensible vive en el ConfigMap (se puede versionar en Git) y las credenciales en el Secret (gestionadas aparte).


Siguiente: Capitulo 8: Namespaces y RBAC —>