Capitulo 7: ConfigMaps y Secrets
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
| Tipo | Uso |
|---|---|
Opaque | Datos genericos (passwords, tokens) |
kubernetes.io/dockerconfigjson | Credenciales de registry privado |
kubernetes.io/tls | Certificados 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:
- Sealed Secrets (Bitnami): cifra los Secrets con una clave publica. Solo el controller en el cluster puede descifrarlos. Seguros para commitear en Git.
- External Secrets Operator: sincroniza Secrets desde proveedores externos (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager).
- SOPS (Mozilla): cifra archivos YAML/JSON con claves GPG o KMS.
Otras practicas:
- Usar RBAC para restringir quien puede leer Secrets.
- Habilitar cifrado en reposo en etcd (K3s lo soporta con
--secrets-encryption). - Rotar credenciales periodicamente.
- No montar Secrets innecesarios en pods.
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 —>