Cerramos el módulo con la lección que convierte a Rutas Norte en una plataforma en la que se puede confiar. Ya tenemos los datos fuera del contenedor, en un volumen que sobrevive al pod, expandible y con snapshots. Pero la lección anterior terminó con una advertencia que lo relativiza todo: un snapshot vive en el mismo sistema de almacenamiento que el original, así que no sobrevive a la pérdida de una zona, al borrado de una cuenta ni a una corrupción descubierta tres semanas tarde. Una copia de seguridad de verdad es otra cosa: sale del clúster, va a un sistema independiente, incluye también los objetos de la API, se coordina con la aplicación para ser consistente, tiene retención definida y —esto es lo único innegociable— se prueba restaurándola. En esta lección construirás las dos piezas que Rutas Norte necesita: el volcado lógico programado de postgres-reservas y la copia de la plataforma completa con Velero, y harás el simulacro de desastre borrando un entorno entero para recuperarlo con cronómetro.
Contenido
- Qué hay que salvar realmente en un clúster
- Snapshot no es copia de seguridad: la regla 3-2-1
- RPO y RTO aplicados a Rutas Norte con números
- Copia lógica:
pg_dumpdesde un Job programado - Compresión, cifrado y restauración del volcado
- Velero: qué hace y cómo está construido
- Instalación y primera copia de un namespace
- Hooks
preypost: la copia consistente - Copias programadas con retención
- Restaurar en otro namespace
- El simulacro de desastre
- Qué no se restaura solo y el runbook mínimo
- Retención, coste y datos personales
- Qué hay que salvar realmente en un clúster
La primera pregunta no es "cómo hago copias" sino "de qué". En un clúster de Kubernetes hay tres cosas distintas, y cada una necesita una técnica diferente:
| Qué | Dónde vive | Técnica | ¿Ya lo tenemos? |
|---|---|---|---|
| Los manifiestos (Deployments, Services, Ingress, NetworkPolicies…) | En Git, como fuente de verdad | Control de versiones | Sí: k8s/base y k8s/entornos/... |
| El estado de la API (objetos reales, incluidos los creados fuera de Git: Secrets, PVC, certificados de cert-manager, anotaciones puestas por controladores) | En etcd | Copia de objetos de la API (Velero) o copia de etcd | No |
| Los datos de los volúmenes | En los PV | Volcado lógico y/o snapshot exportado | No |
Tres observaciones que orientan todo lo demás. Git no basta: los manifiestos permiten recrear la forma de la plataforma, pero no contienen los Secrets (que dejamos deliberadamente fuera de Git en 03-02), ni los certificados emitidos por cert-manager (04-05), ni por supuesto los datos. La copia de etcd es cosa del administrador del clúster, no del equipo de aplicación, y en un clúster gestionado ni siquiera tienes acceso a etcd: por eso el enfoque práctico para Rutas Norte es copiar objetos de la API por namespace, que además es portable entre clústeres. Y lo verdaderamente irreemplazable son los datos: un Deployment se recrea en segundos; una reserva vendida y cobrada, no.
- Snapshot no es copia de seguridad: la regla 3-2-1
Retomamos la advertencia de 05-05 y le damos forma operativa con la regla clásica, que sigue siendo el mejor resumen. 3-2-1: al menos 3 copias de los datos, en 2 soportes o sistemas distintos, con 1 de ellas fuera del emplazamiento principal. Aplicada a Rutas Norte:
| Elemento | Cuenta como | Cumple |
|---|---|---|
El volumen de postgres-reservas en producción |
La copia 1 (el original) | — |
| Snapshots CSI diarios y previos a cambios | La copia 2, mismo sistema | 3 parcial, 2 no, 1 no |
Volcados pg_dump en un PVC del clúster |
La copia 3, mismo clúster | 3 sí, 2 parcial, 1 no |
| Copias Velero en un almacén de objetos en otra región | 1 sí |
La cuarta fila es la que convierte el conjunto en una estrategia: sin ella, todo lo demás desaparece junto con la infraestructura que protege. Dos refuerzos que hoy se consideran obligatorios: la inmutabilidad —el almacén de objetos en modo bloqueo (Object Lock / WORM), para que ni siquiera unas credenciales robadas puedan borrar o cifrar las copias— y la separación de credenciales: la cuenta que escribe las copias no debe poder borrarlas, y el destino debe estar en otra cuenta o suscripción.
- RPO y RTO aplicados a Rutas Norte con números
Dos siglas que hay que separar bien porque se confunden constantemente:
| RPO (Recovery Point Objective) | RTO (Recovery Time Objective) | |
|---|---|---|
| Pregunta | ¿Cuántos datos podemos perder? | ¿Cuánto tiempo podemos estar caídos? |
| Lo determina | La frecuencia de las copias | La velocidad de la restauración |
Y ahora los números, que es lo que convierte la conversación en algo útil. Rutas Norte vende unas 60 reservas por hora en día laborable normal, y unas 400 en puente o inicio de vacaciones, con picos de 700.
| Frecuencia de copia (RPO) | Perdidas en día normal | Perdidas en puente | Coste operativo |
|---|---|---|---|
| 24 h (copia nocturna) | hasta 1.440 | hasta 9.600 | Mínimo |
| 6 h | hasta 360 | hasta 2.400 | Bajo |
| 1 h | hasta 60 | hasta 400 | Medio |
| 5 min (WAL archivado continuo) | ~5 | ~33 | Alto |
Cada fila implica una conversación de negocio, no técnica: ¿cuánto cuesta perder 9.600 reservas? No es solo el importe; es reconstruir a mano, atender reclamaciones, clientes que se presentan en la estación sin billete y daño reputacional en plena temporada alta.
Decisión de Rutas Norte:
| Entorno | RPO objetivo | RTO objetivo | Cómo se consigue |
|---|---|---|---|
rutas-norte-pro |
1 hora (15 min en temporada alta) | 2 horas | Volcado lógico horario + Velero con snapshot + WAL archivado (pendiente) |
rutas-norte-pre |
24 h | 8 h | Velero nocturno |
rutas-norte-dev |
Sin objetivo | Mejor esfuerzo | Se recrea desde Git |
El RTO medido en el ejercicio de 05-05 —del orden de dos minutos en local— era el de restaurar un volumen. El RTO real de un desastre incluye detectar, decidir, restaurar, verificar y reabrir el servicio. Por eso hay que medirlo con un simulacro (apartado 11), no estimarlo.
- Copia lógica:
pg_dump desde un Job programado
pg_dump desde un Job programadoLa copia lógica es un fichero con las instrucciones necesarias para reconstruir la base de datos. Sus ventajas frente a un snapshot de bloques son decisivas:
Volcado lógico (pg_dump) |
Snapshot de bloques | |
|---|---|---|
| Consistencia | Garantizada: se ejecuta en una transacción | Crash-consistent salvo coordinación |
| Verificable | Sí: si se restaura, los datos son coherentes | No demuestra nada por sí mismo |
| Portable a otra versión, otro clúster, otro proveedor | Sí | No |
| Permite restaurar una sola tabla | Sí | No |
| Tamaño | Pequeño (comprime muy bien) | El del volumen |
| Velocidad en bases grandes | Lenta | Instantánea |
No compiten: se complementan. El snapshot es rápido para deshacer; el volcado es la copia que de verdad demuestra que los datos están bien.
Primero, el volumen donde se escriben los volcados: k8s/base/copias-postgres-pvc.yaml, un PVC llamado copias-postgres de 50 GiB, ReadWriteOnce, con las etiquetas habituales más app.kubernetes.io/component: copias-de-seguridad. Va en la clase rutasnorte-rapida (con Retain) porque si se pierden las copias, la red de seguridad desaparece.
Y ahora el CronJob. Nota: el objeto CronJob se estudia a fondo en 06-03; aquí lo usamos como herramienta, quedándonos con lo imprescindible para leerlo.
# k8s/entornos/pro/cronjob-copia-postgres.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: copia-postgres-reservas
namespace: rutas-norte-pro
labels:
app: copia-postgres-reservas
app.kubernetes.io/component: copias-de-seguridad
app.kubernetes.io/part-of: rutas-norte
entorno: pro
spec:
schedule: "0 * * * *" # cada hora en punto (RPO de 1 h)
timeZone: "Europe/Madrid"
concurrencyPolicy: Forbid # nunca dos volcados a la vez
successfulJobsHistoryLimit: 3 # y failedJobsHistoryLimit: 5
jobTemplate:
spec:
backoffLimit: 2
activeDeadlineSeconds: 3600 # si tarda mas de 1 h, algo va mal
template:
metadata:
labels: { app: copia-postgres-reservas, entorno: pro }
spec:
restartPolicy: Never
serviceAccountName: copias-postgres # SA propia (03-06)
securityContext: { runAsNonRoot: true, runAsUser: 999, fsGroup: 999 }
containers:
- name: pg-dump
image: postgres:16.4
env:
- { name: PGHOST, value: postgres-reservas } # el Service (02-05)
- name: PGUSER
valueFrom:
secretKeyRef: { name: postgres-reservas-credenciales, key: username }
- name: PGPASSWORD
valueFrom:
secretKeyRef: { name: postgres-reservas-credenciales, key: password }
- name: PGDATABASE
valueFrom:
secretKeyRef: { name: postgres-reservas-credenciales, key: database }
command:
- /bin/bash
- -c
- |
set -euo pipefail
DESTINO="/copias/reservas-$(date +%Y%m%d-%H%M%S).dump"
# -Fc: formato comprimido de PostgreSQL; permite restaurar
# tablas sueltas. -Z6: nivel de compresion (0-9).
pg_dump -Fc -Z6 --no-owner --no-privileges -f "${DESTINO}"
# Verificacion basica: el volcado se puede LEER.
pg_restore --list "${DESTINO}" > /dev/null
echo "[$(date -Is)] volcado correcto: $(du -h ${DESTINO} | cut -f1)"
# Retencion local: 72 h en el PVC. La larga va al almacen
# de objetos con Velero (apartado 9).
find /copias -name 'reservas-*.dump' -mmin +4320 -print -delete
volumeMounts:
- { name: copias, mountPath: /copias }
resources:
requests: { cpu: 200m, memory: 256Mi }
limits: { cpu: "1", memory: 1Gi }
volumes:
- name: copias
persistentVolumeClaim: { claimName: copias-postgres }Las decisiones que hay dentro, una a una:
concurrencyPolicy: Forbid: si un volcado tarda más de una hora, el siguiente no arranca. Dospg_dumpsimultáneos duplicarían la carga sobre la base de datos justo cuando ya va lenta.set -euo pipefaily la verificación conpg_restore --list: sin lo primero, unpg_dumpfallido puede dejar un fichero truncado y el Job terminar enCompleted, dándote copias que no valen; lo segundo comprueba que el volcado es al menos legible. La verificación de verdad es restaurarlo (apartado 11).--no-owner --no-privileges: el volcado no arrastra propietarios ni permisos, lo que permite restaurarlo en otro clúster con otro usuario. Y con la ServiceAccount propia (03-06) el pod solo tiene lo que necesita, mientras que la retención local de 72 h convierte el PVC en la copia caliente para restaurar rápido; la retención larga vive fuera del clúster.
Y hay que recordar las NetworkPolicies de 04-06: el pod del CronJob es nuevo en el namespace y deny-all lo bloqueará. Hay que autorizar explícitamente su conversación:
# k8s/entornos/pro/np-06-copias-postgres.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: copias-postgres-egress
namespace: rutas-norte-pro
spec:
podSelector:
matchLabels: { app: copia-postgres-reservas }
policyTypes: [Egress]
egress:
- to:
- podSelector: { matchLabels: { app: postgres-reservas } }
ports: [{ protocol: TCP, port: 5432 }]
- to: # DNS, o nada resuelve
- namespaceSelector:
matchLabels: { kubernetes.io/metadata.name: kube-system }
podSelector: { matchLabels: { k8s-app: kube-dns } }
ports:
- { protocol: UDP, port: 53 }
- { protocol: TCP, port: 53 }Verificación:
kubectl apply -f k8s/base/copias-postgres-pvc.yaml
kubectl apply -f k8s/entornos/pro/cronjob-copia-postgres.yaml
kubectl apply -f k8s/entornos/pro/np-06-copias-postgres.yaml
# Lanzar una ejecucion manual sin esperar a la hora en punto
kubectl create job --from=cronjob/copia-postgres-reservas \
copia-manual-$(date +%s) -n rutas-norte-pro
kubectl logs -n rutas-norte-pro -l app=copia-postgres-reservas --tail=20
# [2026-08-05T12:00:41+02:00] volcado correcto: 412M
- Compresión, cifrado y restauración del volcado
Cifrado
El formato -Fc comprime pero no cifra. Y ese fichero contiene el nombre, el DNI, el teléfono y el correo de todos los clientes de Rutas Norte: es exactamente el tipo de artefacto que no puede quedar en claro en ningún soporte. La solución práctica es cifrar con una clave pública cuya clave privada no está en el clúster:
# En el contenedor del CronJob, sustituyendo el pg_dump -f por una tuberia:
pg_dump -Fc -Z6 --no-owner --no-privileges \
| age -r "$CLAVE_PUBLICA_COPIAS" -o "${DESTINO}.age"La variable CLAVE_PUBLICA_COPIAS llega por secretKeyRef desde un Secret copias-clave-publica. Y ahí está el punto importante: en el clúster solo vive la clave pública, así que quien comprometa el clúster puede escribir copias pero no puede leerlas. La clave privada se custodia fuera (gestor de secretos corporativo, caja fuerte), y su procedimiento de acceso debe estar documentado, porque una copia que nadie puede descifrar el día del desastre no es una copia.
Restauración
Se lanza un pod auxiliar con la imagen postgres:16.4 que monte el PVC copias-postgres en /copias (con kubectl run ... --overrides o un Job de un solo uso), y desde dentro:
# 1. Localizar el volcado
ls -lh /copias/
# 2. Restaurar sobre una base de datos NUEVA (nunca sobre la de produccion)
export PGHOST=postgres-reservas PGUSER=rutasnorte PGPASSWORD=...
createdb reservas_restaurada
pg_restore -d reservas_restaurada --no-owner --jobs=4 \
/copias/reservas-20260805-120003.dump
# 3. Verificar ANTES de tocar nada real
psql -d reservas_restaurada -c "SELECT count(*), max(fecha) FROM reservas;"
# count | max
# --------+------------
# 184392 | 2026-12-28Restaura siempre a una base de datos nueva y verifica antes de sustituir. Restaurar directamente sobre la base de producción con --clean es la forma más rápida de convertir un incidente recuperable en uno irreversible.
Opciones de pg_restore que ahorran tiempo el día malo:
--jobs=4 restaura en paralelo y reduce mucho el RTO en bases grandes; --table=reservas restaura una sola tabla, que es el caso más común (alguien borró una tabla); --schema-only y --data-only separan estructura y datos; y --list con --use-list permiten inspeccionar el contenido y restaurar solo una parte.
- Velero: qué hace y cómo está construido
El volcado lógico protege los datos de la base. No protege los Secrets, ni los PVC, ni los Ingress, ni los certificados, ni el resto de objetos del namespace. Para eso está Velero, la herramienta estándar de copia y migración de recursos de Kubernetes.
Velero hace tres cosas. Copia los objetos de la API de un namespace (o del clúster entero), filtrados por etiquetas o por tipo, a un almacén de objetos (S3, Azure Blob, GCS, MinIO). Copia los datos de los volúmenes por dos vías: pidiendo snapshots al driver CSI, o copiando fichero a fichero con Kopia/Restic al mismo almacén de objetos, que es lo que de verdad saca los datos del sistema de almacenamiento. Y restaura todo eso, en el mismo clúster o en otro, con reasignación de namespaces y filtros.
flowchart TB
subgraph CLUSTER["Cluster de Kubernetes"]
API["kube-apiserver"]
SRV["Deployment velero (controlador)<br/>+ plugins de objetos y CSI"]
NA["DaemonSet node-agent<br/>(copia de ficheros con Kopia)"]
PVCS[("PVC de rutas-norte-pro")]
end
OBJ[("Almacen de objetos<br/>s3://rutasnorte-copias<br/>OTRA REGION, inmutable")]
SNAP[("Snapshots CSI<br/>mismo sistema de almacenamiento")]
SRV -->|"lee objetos"| API
SRV -->|"manifiestos + metadatos"| OBJ
SRV -->|"VolumeSnapshot"| SNAP
NA -->|"datos fichero a fichero"| OBJ
PVCS --- NA
La distinción que hay que tener clara desde el principio:
| Método de volumen | Dónde acaban los datos | ¿Sobrevive a perder la región? | Velocidad |
|---|---|---|---|
Snapshots CSI (--snapshot-volumes) |
En el mismo sistema de almacenamiento | No | Muy rápida |
Ficheros (--default-volumes-to-fs-backup) |
En el almacén de objetos | Sí | Lenta |
Para Rutas Norte: snapshots CSI para lo diario (rápido, para deshacer) y copia al almacén de objetos para la copia semanal de larga retención, que es la que cumple el "1" de la regla 3-2-1.
- Instalación y primera copia de un namespace
Para practicar en minikube usaremos MinIO como almacén de objetos compatible con S3, desplegado en el propio clúster. En producción sería un bucket real en otra región y otra cuenta.
# 1. CLI de Velero (descarga la release y mueve el binario a /usr/local/bin)
velero version --client-only
# 2. Credenciales del almacen (en produccion, de una cuenta que NO pueda borrar)
printf '[default]\naws_access_key_id=minio\naws_secret_access_key=minio123\n' \
> credenciales-velero
# 3. Instalar el servidor en el cluster
velero install --provider aws \
--plugins velero/velero-plugin-for-aws:v1.11.0,velero/velero-plugin-for-csi:v0.7.0 \
--bucket rutasnorte-copias --secret-file ./credenciales-velero \
--use-node-agent --features=EnableCSI \
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio.velero.svc:9000 \
--snapshot-location-config region=minio
kubectl get pods -n velero
velero backup-location get # PHASE debe decir AvailableLa primera copia, del namespace de preproducción:
velero backup create pre-completa-$(date +%Y%m%d) \
--include-namespaces rutas-norte-pre --default-volumes-to-fs-backup \
--ttl 168h0m0s --labels entorno=pre,tipo=manual
velero backup describe pre-completa-20260805 --detailsName: pre-completa-20260805 Phase: Completed TTL: 168h0m0s
Resource List:
apps/v1/Deployment: 5 v1/Service: 5 v1/ConfigMap: 7
v1/Secret: 4 v1/ServiceAccount: 6 v1/PersistentVolumeClaim: 2
networking.k8s.io/v1/Ingress: 2 networking.k8s.io/v1/NetworkPolicy: 6
Backup Volumes (Pod Volume Backups - kopia):
postgres-reservas-.../datos: Completed (18.4GB)Fíjate en lo que ha capturado: los Secrets, que no están en Git; los PVC; las NetworkPolicies; los ServiceAccounts. Y los datos del volumen, 18,4 GB copiados fichero a fichero al almacén de objetos.
Las dos variantes de volúmenes son --snapshot-volumes=false (solo objetos de la API: rapidísimo, pero sin datos) y --snapshot-volumes=true (snapshots CSI: rápido, pero los datos se quedan en el mismo sistema de almacenamiento).
- Hooks
pre y post: la copia consistente
pre y post: la copia consistenteAquí resolvemos el problema de consistencia que dejamos abierto en 05-05. Los hooks de Velero ejecutan un comando dentro del contenedor antes y después de copiar el volumen, lo que permite dejar la base de datos en un estado coherente.
Se declaran como anotaciones en el pod, o en el propio backup. La forma declarativa, en el podTemplate del Deployment:
metadata:
labels: { app: postgres-reservas, entorno: pro }
annotations:
# ANTES de copiar el volumen: modo copia de PostgreSQL
pre.hook.backup.velero.io/container: postgres
pre.hook.backup.velero.io/command: >-
["/bin/bash","-c",
"psql -U rutasnorte -d reservas -c \"SELECT pg_backup_start('velero', true);\" &&
psql -U rutasnorte -d reservas -c 'CHECKPOINT;'"]
pre.hook.backup.velero.io/timeout: 3m
# DESPUES: salir del modo copia SIEMPRE, haya ido bien o mal
post.hook.backup.velero.io/container: postgres
post.hook.backup.velero.io/command: >-
["/bin/bash","-c",
"psql -U rutasnorte -d reservas -c 'SELECT pg_backup_stop();'"]
post.hook.backup.velero.io/timeout: 3mQué hace cada uno. pg_backup_start (nombre a partir de PostgreSQL 15; antes era pg_start_backup) pone el servidor en modo copia: fuerza un checkpoint y garantiza que los ficheros del directorio de datos formen un conjunto restaurable, aunque sigan llegando escrituras. Y pg_backup_stop cierra ese modo: es imprescindible que se ejecute siempre, porque una base de datos que se queda en modo copia acumula WAL sin liberar y acaba llenando el disco; por eso el hook post se ejecuta aunque la copia falle.
Alternativa más simple y a menudo preferible para bases medianas: el hook pre hace directamente un pg_dump a un emptyDir que Velero también copia. Sacrifica algo de tiempo a cambio de una copia lógica verificable.
| Nivel | Cómo | Consistencia | Coste |
|---|---|---|---|
| Sin hooks | Copia directa del volumen | Crash-consistent | Nulo |
Hooks pg_backup_start/stop |
Modo copia de PostgreSQL | Consistente a nivel de aplicación | Bajo |
Hook con pg_dump |
Volcado lógico dentro de la copia | Consistente y verificable | Medio |
velero backup create pro-consistente-$(date +%Y%m%d) \
--include-namespaces rutas-norte-pro --default-volumes-to-fs-backup
velero backup logs pro-consistente-20260805 | grep -i hook
# level=info msg="Running exec hook" hookPhase=pre pod=.../postgres-reservas-...
# level=info msg="Running exec hook" hookPhase=post pod=.../postgres-reservas-...
- Copias programadas con retención
Una copia manual sirve para aprender; lo que protege es una programación con retención automática, que Velero resuelve con Schedule y el TTL, que borra la copia y sus datos al expirar.
# Diaria de produccion con snapshots: rapida, retencion corta (7 dias)
velero schedule create pro-diaria --schedule="0 2 * * *" \
--include-namespaces rutas-norte-pro --snapshot-volumes=true \
--ttl 168h0m0s --labels entorno=pro,tipo=diaria
# Semanal al almacen de objetos: lenta, retencion larga (90 dias)
velero schedule create pro-semanal --schedule="0 3 * * 0" \
--include-namespaces rutas-norte-pro --default-volumes-to-fs-backup \
--ttl 2160h0m0s --labels entorno=pro,tipo=semanal
# Preproduccion (14 dias)
velero schedule create pre-diaria --schedule="0 4 * * *" \
--include-namespaces rutas-norte-pre --default-volumes-to-fs-backup \
--ttl 336h0m0s
velero schedule get # las tres, en estado EnabledEl calendario resultante de Rutas Norte:
| Copia | Frecuencia | Método | Retención | Protege de |
|---|---|---|---|---|
Volcado pg_dump (CronJob) |
Cada hora | Lógico, a PVC | 72 h | Error humano en los datos, reciente |
Velero pro-diaria |
Diaria | Snapshots CSI | 7 días | Fallo de despliegue, borrado de objetos |
Velero pro-semanal |
Semanal | Ficheros al almacén | 90 días | Pérdida de zona, cuenta, corrupción antigua |
| Snapshot manual | Antes de cada cambio con riesgo | CSI | 72 h | Migración fallida |
Solo la fila pro-semanal cumple el "1" de la regla 3-2-1. Las demás son comodidad y velocidad.
Vigilancia obligatoria: una copia que falla en silencio es peor que no tener copias, porque genera confianza infundada. Se detecta con velero backup get | grep -v Completed y se investiga con velero backup describe <nombre> --details y velero backup logs <nombre> | grep -i error. Esa comprobación debe ser una alerta automática, no una revisión manual; se monta con las herramientas de 07-04.
- Restaurar en otro namespace
Restaurar sobre el namespace original en producción es la operación más delicada. La práctica correcta es restaurar primero en otro sitio y verificar:
velero restore create verificacion-$(date +%s) \
--from-backup pro-semanal-20260802030012 \
--namespace-mappings rutas-norte-pro:rutas-norte-verificacion \
--include-resources deployments,services,configmaps,secrets,persistentvolumeclaims \
--wait
velero restore describe verificacion-1754392011 --details
kubectl get all,pvc -n rutas-norte-verificacionPhase: Completed
Warnings:
rutas-norte-verificacion: could not restore, Ingress "tienda-web" already existsOpciones de restauración que se usan a diario:
| Opción | Para qué |
|---|---|
--namespace-mappings origen:destino |
Restaurar en otro namespace: verificación, o clonar pre a partir de pro |
--include-resources / --exclude-resources / --selector |
Restaurar solo lo necesario: ciertos tipos, o un solo componente |
--existing-resource-policy=update |
Sobrescribir lo que ya existe (por defecto no lo hace) |
--restore-volumes=false |
Solo los objetos, sin datos |
Y el aviso que ahorra un susto: por defecto Velero NO sobrescribe los objetos que ya existen. Si restauras sobre un namespace vivo, verás un montón de avisos "already exists" y creerás que la restauración falló, cuando lo que ha hecho es protegerte. Para una recuperación real, el namespace destino debe estar vacío o hay que usar --existing-resource-policy=update conscientemente.
- El simulacro de desastre
Una copia no probada no es una copia. Esta es la práctica obligatoria del módulo, y en Rutas Norte se ejecuta cada trimestre sobre rutas-norte-pre, con cronómetro y con acta.
# --- ESTADO PREVIO: documentar lo que debe volver ---
kubectl get all,pvc,secret,ingress,networkpolicy -n rutas-norte-pre --no-headers | wc -l
kubectl exec -n rutas-norte-pre deploy/postgres-reservas -- \
psql -U rutasnorte -d reservas -c "SELECT count(*) FROM reservas;" | tee inventario-previo.txt
curl -s -o /dev/null -w "%{http_code}\n" https://pre.rutasnorte.example/
# --- COPIA DE PARTIDA ---
velero backup create simulacro-$(date +%Y%m%d) \
--include-namespaces rutas-norte-pre --default-volumes-to-fs-backup --wait
# --- EL DESASTRE ---
T0=$(date +%s); kubectl delete namespace rutas-norte-pre
# --- RECUPERACION ---
velero restore create recuperacion-$(date +%s) \
--from-backup simulacro-20260805 --wait
kubectl wait --for=condition=available --timeout=900s deployment --all -n rutas-norte-pre
# --- VERIFICACION: no basta con que los pods esten Running ---
kubectl get all,pvc -n rutas-norte-pre
kubectl exec -n rutas-norte-pre deploy/postgres-reservas -- \
psql -U rutasnorte -d reservas -c "SELECT count(*) FROM reservas;" # -> 184392
curl -s -o /dev/null -w "%{http_code}\n" https://pre.rutasnorte.example/ # -> 200
echo "RTO MEDIDO: $(( ($(date +%s) - T0) / 60 )) minutos" # -> 23 minutosEl acta del simulacro debe recoger, como mínimo: fecha y responsable, copia utilizada, RTO medido, RPO efectivo (el tiempo transcurrido entre la copia y el desastre), qué no volvió solo, incidencias y acciones derivadas. En el segundo ejercicio la redactarás entera.
El apartado "qué no volvió solo" es el más valioso del acta. Es literalmente imposible de conocer sin hacer el simulacro, y es lo que convierte una recuperación teórica en una recuperación real.
- Qué no se restaura solo y el runbook mínimo
| Elemento | Por qué no vuelve | Qué hay que hacer |
|---|---|---|
| Certificados TLS | cert-manager los reemite; si se restaura el Secret antiguo puede estar caducado | Dejar que se reemitan; vigilar los límites de tasa de Let's Encrypt (04-05) |
| IP del LoadBalancer y registros DNS | Se asignan IP nuevas al recrear el Service, y el DNS vive fuera del clúster | Reservar IP estáticas y actualizar www y api de rutasnorte.example, contando con la propagación |
| Secretos externos | Tokens de la pasarela de pagos, del proveedor SMTP: pueden haber rotado | Regenerar desde el gestor de secretos corporativo |
| Cortafuegos, grupos de seguridad y objetos de otros namespaces | Los primeros son de la nube, no del clúster; los segundos no entran si la copia era de un solo namespace | Infraestructura como código, y copiar también ingress-nginx, cert-manager y velero |
| Recursos de clúster (StorageClasses, ClusterIssuers, ClusterRoles) | No entran en una copia de namespace, y sin ellos los PV no se aprovisionan | --include-cluster-resources=true, y crear las StorageClasses antes de restaurar |
Runbook mínimo de recuperación de Rutas Norte
Un documento corto, en el repositorio, que alguien de guardia a las tres de la mañana pueda seguir sin pensar:
RUNBOOK: recuperacion de rutas-norte-pro
Responsable de guardia: [email protected] | Ultima prueba: 2026-08-05
0. DECLARAR EL INCIDENTE. Abrir canal, anotar hora T0, avisar a atencion al
cliente. NO improvisar: si hay dudas sobre el alcance, ir al paso 1 igual.
1. EVALUAR el alcance
kubectl get nodes; kubectl get all -n rutas-norte-pro; velero backup get
-> Solo datos corruptos? -> paso 3 | Namespace destruido? -> paso 4
-> Cluster perdido? -> paso 5
2. CONTENER. Escalar a 0 lo que pueda seguir escribiendo datos malos:
kubectl scale deploy api-reservas worker-notificaciones -n rutas-norte-pro --replicas=0
3. RESTAURACION LOGICA (RTO ~30 min)
Volcado mas reciente en el PVC copias-postgres -> pg_restore a reservas_restaurada
VERIFICAR recuento y fecha maxima -> renombrar bases de datos -> arrancar
4. RESTAURACION DEL NAMESPACE (RTO ~45 min)
velero restore create --from-backup <ultima Completed>
Comprobar: pods Ready, PVC Bound, Ingress con IP, certificado valido
Actualizar DNS si la IP del LoadBalancer ha cambiado
5. CLUSTER NUEVO (RTO ~4 h)
Crear cluster -> addons (ingress-nginx, cert-manager, csi, velero)
Crear StorageClasses ANTES de restaurar
velero restore create --include-cluster-resources=true
Regenerar secretos externos (pagos, SMTP) y actualizar DNS
6. VERIFICAR EL NEGOCIO, no solo los pods: recuento y fecha maxima de
reservas, compra de un billete de prueba de extremo a extremo, y
https://www.rutasnorte.example y https://api.rutasnorte.example -> 200
7. CERRAR: anotar T_fin, RTO y RPO reales, y abrir el post-mortem.
- Retención, coste y datos personales
Coste
Las copias cuestan dinero, y sin retención automática el gasto crece sin freno. Con postgres-reservas en unos 20 GiB, los 72 volcados horarios ocupan unos 30 GiB (comprimen a ~410 MB cada uno), los 7 snapshots diarios unos 25 GiB por ser incrementales, y las 13 copias semanales unos 260 GiB en el almacén de objetos. Palancas para ajustarlo: usar clases de almacenamiento frías para lo antiguo, aprovechar la deduplicación de Kopia, y no copiar lo que se puede regenerar (redis-cache no entra en ninguna copia, por lo decidido en 05-03).
Datos personales
Y aquí está lo que no puede quedar como detalle técnico. Las copias de seguridad de Rutas Norte contienen datos personales de clientes: nombre, DNI, teléfono y correo de cada persona que ha comprado un billete. Eso significa que cada copia es un tratamiento de datos personales con los mismos deberes que el sistema original, y en algunos aspectos más exigentes, porque las copias se multiplican, se replican y se olvidan.
Los requisitos mínimos que Rutas Norte aplica:
| Requisito | Cómo se implementa aquí |
|---|---|
| Cifrado en reposo y en tránsito | Volcados cifrados con age (clave privada fuera del clúster); almacén de objetos con cifrado del lado del servidor y acceso por HTTPS; volúmenes con encrypted: "true" en la StorageClass (05-04); tráfico interno segmentado por NetworkPolicies (04-06) |
| Control de acceso | ServiceAccount dedicada y RBAC mínimo (08-01); credenciales del almacén con permisos de solo escritura |
| Plazo de borrado definido | TTL en cada Schedule de Velero; find -mmin +4320 -delete en el CronJob. Sin retención automática, las copias son eternas y eso es incumplimiento |
| Ámbito geográfico | El bucket de copias debe estar en una región prevista y declarada. Copiar a otra región para resistir desastres no puede sacar los datos del ámbito legal permitido |
| Registro de accesos y derecho de supresión | Auditoría de quién descarga o restaura una copia (08-06); y si un cliente ejerce su derecho de borrado, hay que decidir y documentar qué ocurre con las copias que lo contienen |
| Entornos no productivos | Un clon de producción en pre o en un portátil de desarrollo son datos reales en un entorno menos protegido. Anonimizar o pseudonimizar |
ADVERTENCIA DE CUMPLIMIENTO NORMATIVO
Todo lo anterior es arquitectura técnica, no asesoramiento legal. Los plazos de retención, la ubicación geográfica de las copias, el tratamiento del derecho de supresión sobre datos ya copiados, la base legal del tratamiento y las obligaciones ante una brecha de seguridad deben ser revisados y aprobados por el responsable de cumplimiento normativo y de protección de datos de la organización antes de poner en marcha esta configuración en producción. Los valores de este curso (72 horas, 7 días, 90 días) son ejemplos didácticos elegidos para ilustrar la mecánica de la retención, no recomendaciones legales: el plazo correcto depende de la normativa aplicable, del sector y de la finalidad declarada de cada tratamiento, y conservar datos personales más tiempo del necesario es tan incumplimiento como no protegerlos.
Errores Comunes y Consejos
| Error | Síntoma | Solución |
|---|---|---|
| Confiar en snapshots como única copia | Pérdida total si cae la zona o la cuenta | Copia en almacén de objetos, otra región, otra cuenta |
| No probar nunca la restauración | Se descubre el día del desastre que la copia no vale | Simulacro trimestral con acta |
| Restaurar directamente sobre producción | Un incidente recuperable se vuelve irreversible | Restaurar a base o namespace nuevos y verificar |
Copias que fallan en silencio, o sin set -euo pipefail en el volcado |
Ficheros truncados, Jobs en Completed y confianza infundada durante meses |
Fallar ruidosamente, verificar el volcado y alertar sobre estados distintos de Completed |
| Volcados sin cifrar, o copiar producción a desarrollo sin anonimizar | Datos personales en claro en un PVC, un bucket o un entorno poco protegido | Cifrado con clave pública (privada fuera del clúster); anonimizar o pseudonimizar |
| Sin retención | Coste creciente e incumplimiento normativo | TTL en los Schedules y limpieza en el CronJob |
| Olvidar los recursos de clúster | La restauración falla por StorageClasses inexistentes | --include-cluster-resources=true; crear clases antes |
| Olvidar las NetworkPolicies con el CronJob | El volcado no conecta con la base de datos | Autorizar su egress explícitamente (04-06) |
Hook pre sin hook post |
La base se queda en modo copia y llena el disco de WAL | El post debe ejecutarse siempre |
Creer que el RTO es el tiempo de velero restore |
El simulacro real da el triple | Medir de extremo a extremo, incluidos DNS y verificación |
Consejos:
- Automatiza la verificación, no solo la copia. Un Job semanal que restaure el último volcado en un namespace de pruebas y compare el recuento de filas convierte "creemos que tenemos copias" en "sabemos que tenemos copias".
- Documenta el RPO y el RTO reales, no los deseados, y revísalos tras cada simulacro. Son el dato que necesita el negocio para decidir cuánto invertir.
- La copia debe poder restaurarse sin la persona que la configuró. Si el procedimiento vive en la cabeza de alguien, no existe: escríbelo en el runbook, en el repositorio. Y cuando dudes entre gastar en copias o en cualquier otra cosa, gasta en copias: es el único componente de la plataforma cuya ausencia no se nota hasta que es demasiado tarde.
Ejercicios
Ejercicio 1: el volcado programado
En rutas-norte-dev, monta la cadena completa de copia lógica:
- Crea el PVC
copias-postgresde 5 GiB en la claserutasnorte-rapida. - Adapta el CronJob del apartado 4 a
dev, conschedule: "*/10 * * * *"para no esperar una hora. - Lanza una ejecución manual y comprueba en los registros que el volcado se ha creado y verificado.
- Borra la tabla
reservasy restáurala a una base de datos nueva desde el volcado, sin tocar la original. - Comprueba que los datos coinciden y explica por qué es importante restaurar a una base nueva.
Ejercicio 2: simulacro de desastre en rutas-norte-pre
Ejecuta el simulacro completo del apartado 11 sobre rutas-norte-pre (créalo con los cinco componentes si no lo tienes) y redacta el acta con: inventario previo, copia usada, RTO medido, RPO efectivo, qué no volvió solo, incidencias y acciones derivadas.
Compara después el RTO medido con el objetivo de 8 horas fijado para pre en el apartado 3 y razona si la política es adecuada o hay que cambiarla.
Ejercicio 3: diseñar la estrategia de rutas-norte-pro
El comité de dirección de Rutas Norte pregunta: "si mañana perdemos el centro de datos entero, ¿cuánto tardamos en volver a vender y cuántas reservas perdemos?". Prepara la respuesta en forma de documento breve:
- A. Tabla de qué se copia, con qué método, frecuencia, retención y de qué protege cada copia.
- B. RPO y RTO comprometidos, con el número de reservas perdidas en el peor caso (puente, 400 reservas/hora).
- C. Los tres elementos que no se restauran solos y quién es responsable de cada uno.
- D. Un apartado sobre datos personales que incluya qué contienen las copias, cómo se protegen y qué debe validar el responsable de cumplimiento normativo.
Soluciones
Ejercicio 1
# 1, 2 y 3. El PVC y el CronJob del apartado 4, con namespace rutas-norte-dev,
# 5Gi y schedule "*/10 * * * *". Despues, ejecucion manual:
kubectl apply -f k8s/entornos/dev/copias-postgres-pvc.yaml
kubectl create job --from=cronjob/copia-postgres-reservas \
copia-prueba -n rutas-norte-dev
kubectl wait --for=condition=complete job/copia-prueba -n rutas-norte-dev --timeout=300s
kubectl logs job/copia-prueba -n rutas-norte-dev
# [2026-08-05T13:10:04+02:00] volcado correcto: 12K
# 4: el desastre y la restauracion, desde un pod con el PVC de copias montado
kubectl exec -n rutas-norte-dev deploy/postgres-reservas -- \
psql -U rutasnorte -d reservas -c "DROP TABLE reservas;"
# Dentro de ese pod auxiliar:
createdb reservas_restaurada
pg_restore -d reservas_restaurada --no-owner /copias/reservas-20260805-131002.dump
psql -d reservas_restaurada -c "SELECT count(*) FROM reservas;" # -> 5
# 5: promover la restauracion, ya verificada
psql -d postgres -c "ALTER DATABASE reservas RENAME TO reservas_danyada;"
psql -d postgres -c "ALTER DATABASE reservas_restaurada RENAME TO reservas;"Por qué a una base nueva. Tres razones. Primera, si el volcado estuviera corrupto o incompleto, restaurar encima con --clean habría destruido lo que quedaba: te quedarías sin lo dañado y sin la copia. Segunda, la base dañada es la evidencia para el post-mortem: sin ella no sabrás qué pasó ni desde cuándo. Y tercera, permite comparar antes de cortar: recuento de filas, fecha máxima, integridad referencial. La sustitución final es un renombrado de dos segundos, así que el ahorro de tiempo de restaurar encima es despreciable frente al riesgo.
Ejercicio 2
velero backup create simulacro-pre-$(date +%Y%m%d) \
--include-namespaces rutas-norte-pre --default-volumes-to-fs-backup --wait
T0=$(date +%s)
kubectl delete namespace rutas-norte-pre
velero restore create rec-$(date +%s) --from-backup simulacro-pre-20260805 --wait
kubectl wait --for=condition=available --timeout=900s deployment --all -n rutas-norte-pre
kubectl exec -n rutas-norte-pre deploy/postgres-reservas -- \
psql -U rutasnorte -d reservas -c "SELECT count(*), max(fecha) FROM reservas;"
echo "RTO: $(( ($(date +%s) - T0) / 60 )) minutos"Acta tipo:
| Campo | Valor |
|---|---|
| Fecha / responsable | 2026-08-05 / [email protected] |
| Copia usada | simulacro-pre-20260805, fs-backup, 18,4 GB |
| RTO medido / RPO efectivo | 23 min (borrado → primer 200 OK verificado) / 47 min |
| Objetos restaurados | 5 Deployments, 5 Services, 2 Ingress, 6 NetworkPolicies, 4 Secrets, 2 PVC |
| No volvió solo | El certificado TLS (reemitido en 4 min por cert-manager); la IP del Service LoadBalancer cambió; el Secret del SMTP se restauró con un token ya rotado |
| Incidencias | Los PVC tardaron 6 min en aprovisionarse y montarse: el 40 % del RTO |
| Acciones | (1) IP estática reservada para el Ingress; (2) rotación del token SMTP documentada en el runbook; (3) evaluar --snapshot-volumes para bajar el tiempo de los PVC |
Valoración de la política: el RTO objetivo de pre era de 8 horas y el medido es de 23 minutos, así que se cumple con enorme margen. Pero la conclusión útil es otra: el mismo procedimiento aplicado a producción no daría 23 minutos, porque en pro el volumen es diez veces mayor, hay que actualizar DNS con su propagación, regenerar secretos externos y verificar el negocio de extremo a extremo. La acción correcta es repetir el simulacro sobre una copia de producción restaurada en un namespace aparte, que es lo que da el número real de las 2 horas comprometidas.
Ejercicio 3
A. Qué se copia:
| Qué | Método | Frecuencia | Retención | Protege de |
|---|---|---|---|---|
| Manifiestos | Git | Cada cambio | Ilimitada | Error de configuración |
Datos de postgres-reservas |
pg_dump -Fc cifrado a PVC |
Cada hora (15 min en temporada alta) | 72 h | Error humano reciente en los datos |
Objetos + volúmenes de rutas-norte-pro |
Velero + snapshots CSI | Diaria 02:00 | 7 días | Borrado de objetos, despliegue fallido |
| Objetos, volúmenes y recursos de clúster | Velero + fs-backup a otra región, con --include-cluster-resources |
Semanal domingo 03:00 | 90 días | Pérdida de zona, de cuenta, corrupción antigua; reconstrucción en clúster nuevo |
| Volumen antes de cada cambio con riesgo | Snapshot CSI | Bajo demanda | 72 h | Migración de esquema fallida |
B. Compromisos:
| Escenario | RPO | Reservas perdidas (puente) | RTO |
|---|---|---|---|
| Corrupción de datos detectada rápido | 1 h | hasta 400 | ~30 min |
| Namespace destruido | 24 h (o 1 h con el volcado) | hasta 400 | ~45 min |
| Pérdida del centro de datos | 7 días en el peor caso, 24 h en el habitual | hasta 67.200 | ~4 h |
La última fila es la respuesta a la pregunta del comité, y es incómoda a propósito: la copia que sobrevive a perder el centro de datos es la semanal, de modo que en el peor caso se perderían hasta siete días de reservas. Si eso no es aceptable —y no debería serlo—, hay dos inversiones que lo arreglan: pasar la copia externa a diaria (RPO de 24 h) y, sobre todo, archivar el WAL de PostgreSQL de forma continua a un almacén de objetos externo, que llevaría el RPO a minutos. Es la mejora prioritaria del plan.
C. Lo que no se restaura solo:
| Elemento | Responsable | Acción |
|---|---|---|
DNS de www.rutasnorte.example y api.rutasnorte.example |
Plataforma | Actualizar registros e IP; contar con la propagación |
Secretos externos: clave de pagos.proveedorexterno.example y token SMTP |
Seguridad | Regenerar desde el gestor corporativo y reaplicar |
| Infraestructura: nodos, red, cortafuegos, StorageClasses, ingress-nginx, cert-manager | Plataforma | Infraestructura como código; crear las StorageClasses antes de restaurar |
D. Datos personales:
Las copias contienen nombre, DNI, teléfono y correo de todos los clientes que han comprado un billete, además del historial completo de reservas. Protecciones aplicadas: cifrado en reposo de los volcados con clave pública (privada custodiada fuera del clúster), cifrado del bucket, cifrado en tránsito, credenciales de solo escritura para el proceso de copia, acceso a la restauración limitado por RBAC y registrado, retención automática por TTL y anonimización obligatoria de cualquier clon destinado a entornos no productivos.
Lo que debe validar el responsable de cumplimiento normativo, antes de poner nada de esto en producción:
- Que los plazos de retención (72 h, 7 días, 90 días) son los legalmente correctos para esta finalidad, ni más ni menos.
- Que la región del almacén de copias está dentro del ámbito geográfico permitido y declarado.
- El procedimiento ante el derecho de supresión: qué se hace con las copias que ya contienen los datos de quien lo ejerce, y cómo se documenta.
- La base legal del tratamiento y su reflejo en el registro de actividades, incluyendo las copias como tratamiento.
- El protocolo de notificación de brechas si una copia se ve comprometida.
- Las condiciones del encargado del tratamiento con el proveedor de la nube que aloja las copias.
Este documento es una propuesta técnica y no sustituye esa revisión.
Conclusión
Rutas Norte es ya una plataforma en la que se puede confiar. Sabes qué hay que salvar —los manifiestos, que ya están en Git; el estado de la API, con los Secrets y los PVC que Git no contiene; y los datos de los volúmenes, lo único verdaderamente irreemplazable— y que cada uno exige una técnica distinta. Tienes interiorizada la regla 3-2-1 y sabes que, de todas las copias de Rutas Norte, solo la semanal al almacén de objetos de otra región cumple el "1"; las demás son comodidad y velocidad. Y manejas RPO y RTO con números concretos: a 400 reservas por hora en un puente, una copia diaria significa perder hasta 9.600 reservas, y eso convierte una discusión técnica en una decisión de negocio que alguien tiene que tomar y firmar.
Has construido las dos piezas. La copia lógica: un CronJob horario que ejecuta pg_dump -Fc, verifica el volcado con pg_restore --list, lo cifra con una clave pública cuya privada no vive en el clúster, aplica retención local y —detalle que se olvida siempre— tiene su propia NetworkPolicy para atravesar el deny-all de producción. Y la copia de la plataforma con Velero: su arquitectura de controlador, node-agent y plugins; las dos vías para los volúmenes, con la diferencia decisiva de que solo la copia al almacén de objetos saca de verdad los datos del sistema de almacenamiento; los hooks pre y post con pg_backup_start/pg_backup_stop que resuelven la consistencia que dejamos abierta en 05-05, y la advertencia de que el post debe ejecutarse siempre so pena de llenar el disco de WAL; los Schedule con TTL que hacen la retención automática; y la restauración con --namespace-mappings para verificar antes de tocar nada real.
Y has hecho lo que separa una copia de una copia útil: el simulacro. Borrar rutas-norte-pre entero y recuperarlo con cronómetro, midiendo un RTO real y descubriendo la lista de lo que no vuelve solo —el certificado, la IP del LoadBalancer, el DNS, los secretos externos, los recursos de clúster—, que es literalmente imposible de conocer sin ejecutarlo. De ahí sale el runbook que alguien de guardia puede seguir a las tres de la mañana. Junto a todo ello queda la advertencia que no es técnica: las copias contienen datos personales de clientes, deben cifrarse, tener plazo de borrado, no salir del ámbito legal previsto, y la política de retención y el tratamiento de esos datos deben ser revisados y aprobados por el responsable de cumplimiento normativo antes de llevar nada de esto a producción.
Con esto termina el módulo 5. La deuda que arrastrábamos desde el módulo 2 está saldada por completo: postgres-reservas guarda sus datos en un volumen que sobrevive al pod, aprovisionado dinámicamente por una StorageClass con Retain, expandible en caliente, con snapshots antes de cada cambio arriesgado y con copias verificadas dentro y fuera del clúster.
Queda un techo que hemos encontrado tres veces y siempre hemos aplazado con la misma frase. En 05-03 descubriste que un Deployment tiene una sola plantilla, de modo que todas sus réplicas piden el mismo PVC y por eso postgres-reservas está condenado a replicas: 1 con strategy: Recreate. Una base de datos de producción necesita más: identidad estable, arranque ordenado y un volumen propio por réplica. Eso lo da el volumeClaimTemplate de los StatefulSets, y con él arranca el módulo 6, Conceptos Avanzados: StatefulSets, DaemonSets, Jobs y CronJobs —donde por fin llega informes-ocupacion, el sexto componente de la plataforma—, init containers y sidecars, planificación con afinidad y taints, recursos personalizados y operadores. Empezamos por StatefulSets.
Curso de Kubernetes
Módulo 1: Introducción a Kubernetes
- ¿Qué es Kubernetes?
- Arquitectura de Kubernetes
- Conceptos y Terminología Clave
- Configuración de un Clúster de Kubernetes
- La CLI de Kubernetes: kubectl
- Objetos, Manifiestos YAML y el Modelo Declarativo
- El Proyecto del Curso: la Plataforma Rutas Norte
Módulo 2: Componentes Principales de Kubernetes
- Pods
- ReplicaSets
- Deployments
- Actualizaciones, Rollbacks y Estrategias de Despliegue
- Servicios
- Namespaces
- Etiquetas, Selectores y Anotaciones
Módulo 3: Gestión de Configuración y Secretos
- ConfigMaps
- Secrets
- Variables de Entorno
- Cuotas y Límites de Recursos
- LimitRanges y Clases de Calidad de Servicio (QoS)
- ServiceAccounts y Acceso a la API desde los Pods
Módulo 4: Redes en Kubernetes
- Redes de Clúster
- Tipos de Servicios
- DNS Interno y Descubrimiento de Servicios
- Controladores de Ingress
- TLS y Gestión de Certificados con cert-manager
- Políticas de Red
Módulo 5: Almacenamiento en Kubernetes
- Volúmenes
- Volúmenes Persistentes
- Reclamaciones de Volúmenes Persistentes
- Clases de Almacenamiento
- Aprovisionamiento Dinámico, Expansión y Snapshots
- Copias de Seguridad y Restauración de Datos
Módulo 6: Conceptos Avanzados de Kubernetes
- StatefulSets
- DaemonSets
- Trabajos y CronJobs
- Init Containers, Sidecars y Patrones Multi-Contenedor
- Planificación: Afinidad, Taints y Tolerations
- Definiciones de Recursos Personalizados (CRDs)
- Operadores y el Patrón Controlador
Módulo 7: Monitoreo y Registro
- Verificaciones de Salud y Sondas
- Servidor de Métricas y kubectl top
- Monitoreo con Prometheus
- Visualización y Alertas con Grafana y Alertmanager
- Registro Centralizado con Elasticsearch, Fluentd y Kibana (EFK)
- Depuración de Aplicaciones y Eventos del Clúster
Módulo 8: Seguridad en Kubernetes
- Control de Acceso Basado en Roles (RBAC)
- Contextos de Seguridad y Endurecimiento del Contenedor
- Políticas de Seguridad de Pods y Pod Security Standards
- Seguridad de Red
- Seguridad de Imágenes
- Auditoría, Escaneo y Gestión de Vulnerabilidades
Módulo 9: Escalado y Rendimiento
- Autoescalado Horizontal de Pods
- Autoescalado Vertical de Pods
- Autoescalado de Clúster
- Escalado por Eventos y Métricas Personalizadas con KEDA
- Alta Disponibilidad: PodDisruptionBudgets y Topología
- Ajuste de Rendimiento
Módulo 10: Ecosistema y Herramientas de Kubernetes
- Minikube y Entornos Locales con kind
- Kubeadm
- Helm
- Kustomize
- GitOps con Argo CD y Flux
- Kubernetes Gestionado: EKS, AKS y GKE
Módulo 11: Estudios de Caso y Aplicaciones del Mundo Real
- Despliegue de una Aplicación Web
- Ejecución de Aplicaciones con Estado
- CI/CD con Kubernetes
- Estrategias de Despliegue: Blue-Green y Canary
- Gestión Multi-Clúster
- Operación en Producción: Incidencias, Runbooks y Costes
