tutoriales.com

Gestión de Configuración en Kubernetes: ConfigMaps y Secrets para Aplicaciones Robustas ⚙️

Este tutorial profundiza en el uso de ConfigMaps y Secrets en Kubernetes, herramientas esenciales para la gestión de la configuración y la protección de información sensible. Exploraremos cómo definirlos, desplegarlos y utilizarlos en tus pods, asegurando un despliegue seguro y flexible de tus aplicaciones.

Intermedio18 min de lectura9 views19 de marzo de 2026Reportar error

Kubernetes se ha consolidado como la plataforma líder para la orquestación de contenedores, y una de sus fortalezas es la forma en que maneja la configuración de las aplicaciones. Desplegar una aplicación implica no solo sus contenedores, sino también cómo se configura para diferentes entornos (desarrollo, staging, producción) y cómo se manejan datos sensibles como contraseñas y claves API. Aquí es donde entran en juego los ConfigMaps y Secrets.

Estas dos herramientas son fundamentales para desacoplar la configuración del código de la aplicación y la imagen del contenedor, lo que facilita la reutilización, el mantenimiento y, crucialmente, la seguridad.

¿Por Qué Necesitamos ConfigMaps y Secrets? 🤔

Antes de sumergirnos en los detalles, entendamos por qué estas características son tan importantes:

  1. Desacoplamiento: Separan la configuración de la aplicación de su código. Esto significa que puedes usar la misma imagen de Docker para diferentes entornos, simplemente cambiando la configuración. Es una aplicación del principio de Twelve-Factor App.
  2. Flexibilidad: Permite cambiar la configuración de una aplicación sin tener que reconstruir su imagen de contenedor o reiniciar todos sus pods (aunque algunos cambios pueden requerir un reinicio para que surtan efecto).
  3. Seguridad: Los Secrets proporcionan un mecanismo seguro para manejar datos sensibles, evitando que se almacenen directamente en el código fuente, en imágenes de Docker o en ficheros de configuración visibles.
  4. Auditoría y control: La gestión centralizada de la configuración facilita la auditoría y el control de versiones.

ConfigMaps: Gestión de la Configuración General 🛠️

Un ConfigMap es un objeto API de Kubernetes que se utiliza para almacenar datos de configuración no confidenciales como pares clave-valor. Está diseñado para inyectar datos de configuración en los contenedores de tus pods.

💡 Consejo: Piensa en los ConfigMaps como un mapa de configuración que tus aplicaciones pueden consultar para saber cómo comportarse en un entorno específico.

Formas de Crear un ConfigMap ✨

Hay varias maneras de crear un ConfigMap:

1. Desde literales

Puedes especificar los datos directamente usando --from-literal.

kubectl create configmap app-config --from-literal=database.host=mydb.example.com --from-literal=app.port=8080

2. Desde un archivo

Ideal para cuando ya tienes archivos de configuración existentes.

Supongamos que tienes un archivo application.properties:

database.host=production-db.example.com
app.port=80
api.key=xyz123abc

Para crearlo:

kubectl create configmap app-settings --from-file=application.properties

Cada línea o sección del archivo se convierte en una entrada del ConfigMap. Si quieres que el contenido del archivo se guarde como una sola clave, puedes especificar el nombre de la clave:

kubectl create configmap app-settings-single-file --from-file=my-app-config=application.properties

3. Desde un directorio

Si tienes múltiples archivos de configuración en un directorio:

mkdir config-files
echo "host=localhost" > config-files/db.properties
echo "port=8080" > config-files/server.properties
kubectl create configmap app-multi-config --from-file=config-files

Esto creará un ConfigMap con dos entradas: db.properties y server.properties, donde los valores son el contenido de cada archivo.

4. Usando un manifiesto YAML (Recomendado) ✅

Esta es la forma más común y recomendable para gestionar ConfigMaps en un entorno de CI/CD, ya que permite el control de versiones.

my-configmap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-app-config
data:
  # Clave-valor directamente
  app_environment: production
  log_level: INFO
  # Contenido multilínea como un string
  database.properties: |
    db.host=prod-db
    db.port=5432
    db.user=admin

Para aplicar el manifiesto:

kubectl apply -f my-configmap.yaml

Consumir ConfigMaps en Pods 📖

Una vez creado, un ConfigMap puede ser consumido por un pod de varias maneras.

🔥 Importante: Los datos de ConfigMap son inmutables por defecto a partir de Kubernetes 1.18. Esto mejora la estabilidad y la trazabilidad.

1. Como variables de entorno

La forma más sencilla para inyectar valores individuales.

pod-with-env-configmap.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: my-app-env
spec:
  containers:
  - name: my-app-container
    image: nginx:latest
    env:
    - name: APP_ENV
      valueFrom:
        configMapKeyRef:
          name: my-app-config # Nombre del ConfigMap
          key: app_environment # Clave dentro del ConfigMap
    - name: LOG_LEVEL
      valueFrom:
        configMapKeyRef:
          name: my-app-config
          key: log_level
kubectl apply -f pod-with-env-configmap.yaml
kubectl exec -it my-app-env -- env | grep APP_ENV
kubectl exec -it my-app-env -- env | grep LOG_LEVEL
📌 Nota: Para inyectar *todas* las claves de un ConfigMap como variables de entorno, usa `envFrom`.

pod-with-envFrom-configmap.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: my-app-envfrom
spec:
  containers:
  - name: my-app-container
    image: alpine/git
    command: ["sh", "-c", "env; sleep 3600"]
    envFrom:
    - configMapRef:
        name: my-app-config # Nombre del ConfigMap
kubectl apply -f pod-with-envFrom-configmap.yaml
k exec -it my-app-envfrom -- env | grep -E 'APP_ENV|LOG_LEVEL|database.properties'

2. Como archivos en un volumen

Esto es útil cuando la aplicación espera archivos de configuración en una ruta específica. Cada clave del ConfigMap se convierte en un archivo dentro del volumen.

pod-with-volume-configmap.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: my-app-volume
spec:
  containers:
  - name: my-app-container
    image: nginx:latest
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config # Ruta dentro del contenedor
  volumes:
  - name: config-volume
    configMap:
      name: my-app-config # Nombre del ConfigMap
kubectl apply -f pod-with-volume-configmap.yaml
k exec -it my-app-volume -- ls /etc/config
k exec -it my-app-volume -- cat /etc/config/app_environment

Aquí, cada clave de my-app-config (como app_environment o log_level) se materializará como un archivo en /etc/config dentro del contenedor.

ConfigMap my-app-config Variables de Entorno Volumen Montado (/etc/config) Pod my-app-container Inyectar como Inyectar como

Secrets: Protegiendo la Información Sensible 🔒

Los Secrets son similares a los ConfigMaps, pero están diseñados específicamente para almacenar y gestionar datos sensibles como contraseñas, tokens de autenticación, claves API y claves TLS. Kubernetes proporciona un mecanismo para mantener estos datos seguros y desacoplados de la imagen de la aplicación.

⚠️ Advertencia: Por defecto, los Secrets se almacenan como Base64. Esto NO es cifrado. Cualquiera con acceso al clúster y los permisos adecuados puede decodificar los Secrets. Considera soluciones adicionales de cifrado como [HashiCorp Vault](https://www.vaultproject.io/) o los [Secretes KMS](https://cloud.google.com/kubernetes-engine/docs/how-to/encrypting-secrets) para una mayor seguridad.

Formas de Crear un Secret 🔑

1. Desde literales

Similar a ConfigMaps, pero los valores son automáticamente codificados en Base64.

kubectl create secret generic my-db-secret --from-literal=username=dbadmin --from-literal=password=SuperSecretPassword123!

2. Desde archivos

echo -n 'dbadmin' > ./username.txt
echo -n 'SuperSecretPassword123!' > ./password.txt
kubectl create secret generic my-db-secret-file --from-file=./username.txt --from-file=./password.txt

3. Usando un manifiesto YAML (Recomendado) ✅

Los valores en el YAML deben estar codificados en Base64. Puedes usar una herramienta como base64 para esto.

echo -n 'dbadmin' | base64
# ZGJhZG1pbg==
echo -n 'SuperSecretPassword123!' | base64
# U3VwZXJTZWNyZXRQYXNzd29yZDEyMyE=

my-secret.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: my-app-secret
type: Opaque # Tipo general de Secret
data:
  username: ZGJhZG1pbg== # 'dbadmin' en Base64
  password: U3VwZXJTZWNyZXRQYXNzd29yZDEyMyE= # 'SuperSecretPassword123!' en Base64
kubectl apply -f my-secret.yaml

Para ver un Secret (con cuidado):

kubectl get secret my-app-secret -o yaml

Los valores estarán codificados en Base64. Para decodificarlos temporalmente:

kubectl get secret my-app-secret -o jsonpath="{.data.username}" | base64 --decode
kubectl get secret my-app-secret -o jsonpath="{.data.password}" | base64 --decode

Consumir Secrets en Pods 📖

La forma de consumir Secrets es muy similar a ConfigMaps, pero con implicaciones de seguridad adicionales.

1. Como variables de entorno

pod-with-secret-env.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: my-app-secret-env
spec:
  containers:
  - name: my-app-container
    image: alpine/git
    command: ["sh", "-c", "env; sleep 3600"]
    env:
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: my-app-secret # Nombre del Secret
          key: username
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: my-app-secret
          key: password
kubectl apply -f pod-with-secret-env.yaml
k exec -it my-app-secret-env -- env | grep DB_USERNAME
k exec -it my-app-secret-env -- env | grep DB_PASSWORD
⚠️ Advertencia: Exponer Secrets como variables de entorno puede ser menos seguro en ciertos escenarios, ya que otros procesos en el mismo nodo pueden listarlos. Considera montar como volumen para mayor aislamiento.

2. Como archivos en un volumen

Esta es la forma recomendada para consumir Secrets, ya que el archivo se monta en un tmpfs (sistema de archivos en memoria) y se puede controlar más finamente los permisos.

pod-with-secret-volume.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: my-app-secret-volume
spec:
  containers:
  - name: my-app-container
    image: nginx:latest
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secrets # Ruta dentro del contenedor
      readOnly: true # ¡Muy importante!
  volumes:
  - name: secret-volume
    secret:
      secretName: my-app-secret # Nombre del Secret
      # Por defecto, los archivos se crean con permisos 0644. Puedes ajustarlos:
      # defaultMode: 0400 # rw------- para el owner
kubectl apply -f pod-with-secret-volume.yaml
k exec -it my-app-secret-volume -- ls -l /etc/secrets
k exec -it my-app-secret-volume -- cat /etc/secrets/username

Dentro del contenedor, verás archivos username y password con los valores decodificados del Secret.

Secret (my-app-secret) Pod (my-app-container) Environment Variables (menos seguro) Volume Mount /etc/secrets Recomendado, tmpfs

Tipos de Secrets 💡

Además del tipo Opaque general, Kubernetes tiene tipos de Secrets predefinidos que añaden validación o comportamientos específicos:

  • kubernetes.io/service-account-token: Para tokens de Service Account.
  • kubernetes.io/dockercfg o kubernetes.io/dockerconfigjson: Para credenciales de registro de imágenes (Docker Hub, GCR, ACR, ECR, etc.).
  • kubernetes.io/tls: Para certificados TLS y claves privadas.

Por ejemplo, un Secret TLS:

apiVersion: v1
kind: Secret
metadata:
  name: my-tls-secret
type: kubernetes.io/tls
data:
  tls.crt: <base64 encoded cert>
  tls.key: <base64 encoded key>

Diferencias Clave y Cuándo Usar Cada Uno 🎯

Aunque ConfigMaps y Secrets comparten la forma en que se consumen, su propósito y tratamiento de seguridad son muy diferentes.

CaracterísticaConfigMapSecret
PropósitoDatos de configuración no sensiblesDatos sensibles (contraseñas, API keys)
AlmacenamientoTexto plano (en etcd)Codificado en Base64 (en etcd)
Seguridad por defectoBaja (texto plano)Media (Base64 no es cifrado)
Casos de usoURLs de DB, niveles de log, flagsContraseñas de DB, tokens, certificados TLS
InmutabilidadPor defecto (configurable)
TipoOpaque (implícito)Opaque, kubernetes.io/tls, etc.
💡 Consejo: Siempre usa Secrets para cualquier dato que no quieras que sea fácilmente legible por cualquier persona con acceso al clúster, incluso si crees que no es 'tan sensible'. Es una buena práctica de seguridad.

Actualización de ConfigMaps y Secrets 🔄

Un punto crucial a entender es cómo los cambios en ConfigMaps y Secrets afectan a los pods en ejecución.

  • Variables de entorno: Los cambios en un ConfigMap o Secret no se reflejan automáticamente en las variables de entorno de los pods en ejecución. Para que los cambios surtan efecto, debes reiniciar los pods (por ejemplo, con un rollout restart de tu Deployment).

  • Volúmenes montados: Los ConfigMaps y Secrets montados como volúmenes se actualizan automáticamente en el sistema de archivos del pod. Sin embargo, esto puede tardar unos segundos o minutos (dependiendo de la configuración de Kubelet, típicamente de 60 a 300 segundos). La aplicación debe estar diseñada para detectar y recargar la configuración desde los archivos cuando estos cambian.

¿Cómo forzar un reinicio de Deployment tras un cambio de ConfigMap/Secret?

Una técnica común es usar un hash del ConfigMap o Secret en la plantilla del pod del Deployment. Cuando el ConfigMap/Secret cambia, el hash también cambia, lo que provoca que el Deployment detecte un cambio en la plantilla del pod y realice un rollout.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-deployment
spec:
  template:
    metadata:
      annotations:
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
        checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
    spec:
      containers:
      - name: my-app
        image: my-app:latest
        envFrom:
        - configMapRef:
            name: my-app-config
        - secretRef:
            name: my-app-secret

Esta técnica se usa a menudo con herramientas como Helm, donde {{ include ... | sha256sum }} es una función de plantilla. Para YAML plano, tendrías que generar el sha256sum manualmente o usar un operador de Kubernetes (como el Reloader de Stakater).


Buenas Prácticas y Consideraciones de Seguridad 🛡️

  • Principio de mínimo privilegio: Otorga a los pods solo los Secrets y ConfigMaps que realmente necesitan. Usa RBAC para controlar quién puede leer o modificar estos objetos.
  • No guardar Secrets en Git sin cifrar: Aunque los Secrets de Kubernetes están codificados en Base64, esto no es cifrado. Nunca almacenes manifiestos de Secrets con valores codificados directamente en un repositorio Git público. Utiliza herramientas como kubeseal (Sealed Secrets) o soluciones de terceros como HashiCorp Vault para cifrar Secrets en reposo en Git.
  • Rotación de credenciales: Implementa una política de rotación regular para las credenciales almacenadas en Secrets. Kubernetes no lo hace automáticamente, pero puede integrarse con soluciones de gestión de identidades y accesos (IAM) o herramientas externas.
  • Auditoría: Monitorea los accesos a Secrets y ConfigMaps a través de los logs de auditoría de Kubernetes.
  • Secrets para Service Accounts: Los Service Accounts en Kubernetes usan Secrets para autenticar los pods con la API de Kubernetes. Entiende cómo funcionan para asegurar que tus pods tengan los permisos adecuados.
90% Seguridad ConfigMaps y Secrets

Escenarios Avanzados y Herramientas Complementarias 🚀

La gestión de configuración y secretos en Kubernetes va más allá de lo básico, especialmente en entornos de producción con alta exigencia.

Sealed Secrets (por Bitnami)

Intermedio

Sealed Secrets es una herramienta muy popular que resuelve el problema de almacenar Secrets cifrados en Git. Permite cifrar un Secret en un formato que puede ser almacenado de forma segura en un repositorio público, y solo el controlador de Sealed Secrets que se ejecuta en el clúster puede descifrarlo.

Paso 1: Instala el controlador Sealed Secrets en tu clúster.
Paso 2: Cifra tus Secrets usando la herramienta `kubeseal` localmente.
Paso 3: Sube el manifiesto `SealedSecret` cifrado a tu repositorio Git.
Paso 4: El controlador Sealed Secrets detecta el `SealedSecret` y lo descifra automáticamente en un `Secret` estándar de Kubernetes.

Esto es ideal para flujos de trabajo de GitOps.

HashiCorp Vault con Kubernetes

Avanzado

Para necesidades de seguridad más rigurosas y gestión de secretos a nivel empresarial, integrar HashiCorp Vault con Kubernetes es una solución robusta. Vault ofrece:

  • Cifrado en reposo y en tránsito.
  • Generación dinámica de credenciales: Vault puede generar credenciales de bases de datos, claves API, etc., justo a tiempo para que las aplicaciones las usen, con políticas de tiempo de vida (TTL).
  • Auditoría completa.
  • Integración con sistemas de autenticación: LDAP, GitHub, etc.

La integración con Kubernetes se realiza a menudo mediante el Vault Agent Injector o el Vault Kubernetes Auth Method. Esto permite que los pods se autentiquen con Vault y recuperen secretos sin necesidad de que estos sean almacenados en un Secret de Kubernetes, aumentando significativamente la seguridad.

Operadores de Configuración y Secretos

Algunos ecosistemas y herramientas ofrecen sus propios operadores para gestionar la configuración o los secretos, como por ejemplo:

  • External Secrets Operator: Permite integrar Secrets de proveedores externos (AWS Secrets Manager, Azure Key Vault, Google Secret Manager) directamente en Kubernetes, creando Secrets de K8s a partir de ellos.
  • Kubernetes Configuration Operator: (Menos común, pero existen soluciones personalizadas) Operadores que monitorizan ConfigMaps o Secrets y realizan acciones específicas, como reiniciar pods o ejecutar scripts, cuando estos cambian.

Conclusión ✨

La gestión de la configuración y los secretos es un pilar fundamental en la construcción de aplicaciones modernas en Kubernetes. Los ConfigMaps y Secrets son herramientas nativas y poderosas que, cuando se utilizan correctamente, mejoran la flexibilidad, la reutilización y, lo más importante, la seguridad de tus despliegues.

Desde inyectar simples variables de entorno hasta montar volúmenes de archivos sensibles, Kubernetes ofrece las primitivas necesarias para satisfacer una amplia gama de requisitos. Al combinar estas herramientas con buenas prácticas de seguridad y, cuando sea necesario, soluciones avanzadas como Sealed Secrets o HashiCorp Vault, puedes construir una infraestructura verdaderamente robusta y preparada para la producción.

Dominar estos conceptos te permitirá manejar de manera eficiente y segura las complejidades de la configuración de aplicaciones en un entorno de orquestación de contenedores.

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!