CNPG-Backup/docs/recovery-procedure.md

11 KiB
Raw Permalink Blame History

Procedimiento de Recuperación – CNPG-Backup

Este documento describe los pasos exactos para restaurar un cluster PostgreSQL usando los backups creados por la estrategia CloudNativePG definida en este repositorio.

Escenario común de recuperación

Evento Acciones típicas
Corrupción del cluster Restaurar de un backup completo más WALs recientes
Pérdida del nodo primario Escalar o restaurar en un nodo diferente
Pérdida de datos accidental Point-In-Time Recovery (PITR) a un timestamp antes del incidente
Migración a otro cluster Restaurar un backup completo (cold) sin WALs

Requisitos previos

  • El plugin Barman Cloud (barman-cloud.cloudnative-pg.io) debe estar instalado en el cluster:
    kubectl apply -f https://github.com/cloudnative-pg/cnpg-i/releases/download/v0.5.0/manifest.yaml
    
  • Las credenciales de ObjectStore (object-store-creds) deben existir en el namespace donde se restaurará.
  • El bucket (cnpg-backups) debe ser accesible desde el namespace del nuevo cluster.

Guía rápida de recuperación (comando único)

Para recuperar un cluster de múltiples nodos completo:

kubectl cnpg restore pg-backup \
  --backup=latest \
  --namespace=default \
  --target='2026-09-01 12:00:00' \
  --sudo-recovery

(El timestamp --target es opcional – omitirlo restaurará desde el backup más reciente)

Paso a paso

1. Identificar un backup válido

Listar todos los recursos Backup ordenados por CreationTimestamp.

kubectl get backups -o wide

Salida esperada (columnas relevantes):

NAME           AGE     CLUSTER   METHOD   PHASE     STARTED_AT           COMPLETION     DESTINATION
backup-1       2h      pg-backup plugin   completed 2026-09-06T02:00:00Z 2026-09-06T02:05:00Z s3://cnpg-backups/pg-backup/
backup-2       30m     pg-backup plugin   completed 2026-09-06T01:00:00Z 2026-09-06T01:03:00Z s3://cnpg-backups/pg-backup/

¿Cómo usarlo?

  • backup-1 – la restauración más reciente (recomendada para RTO mínimo).
  • backup-2 – una restauración intermedia para una recuperação al punto en el tiempo más antigua.

2. Restaurar desde el backup completo más reciente

Cuando se necesita un cluster nuevo (ej. reemplazo de nodos o reconstrucción post-falla) y no hay necesidad de recuperar un punto específico:

# Opción A – Usar el comando cnpg RESTOURE (recomendado)

kubectl cnpg restore pg-backup \
  --backup=backup-1 \
  --namespace=default \
  --recovery-conf='application_name=restored_cluster'

# Opción B – Aplicar un recurso YAML de Cluster con bootstrap.recovery

cat <<EOF | kubectl apply -f -
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg-restored
  namespace: default
spec:
  instances: 3
  imageName: ghcr.io/cloudnative-pg/postgresql:18.1-minimal-trixie
  bootstrap:
    recovery:
      backup:
        name: backup-1
        # si el backup está en otro namespace, especifique el namespace aquí:
        # namespace: default
      recoveryTarget:
        # por defecto, restaurar al momento del backup
        # Opcionalmente, restaurar a un timestamp más antiguo:
        targetTimeStamp: "2026-09-05T10:30:00Z"
        # Opcionalmente, restaurar en un timestamp específico sin incluir el tiempo:
        # targetTimeline: "2"
  storage:
    size: 50Gi
    storageClass: standard
  resources:
    requests:
      cpu: "500m"
      memory: "256Mi"
    limits:
      cpu: "2"
      memory: "1Gi"
  backup:
    target: "prefer-standby"
    barmanObjectStore:
      objectStore:
        name: pg-backup-store
  plugins:
    - name: barman-cloud.cloudnative-pg.io
      isWALArchiver: true
      parameters:
        barmanObjectName: pg-backup-store
        serverName: pg-backup
EOF

3. Restaurar al Punto en el Tiempo (PITR)

Cuando se necesita recuperar de un backup y replayear WALs hasta un timestamp específico:

kubectl cnpg restore pg-backup \
  --backup=backup-2 \
  --namespace=default \
  --target='2026-09-05 14:30:00' \
  --recovery-conf='application_name=pitr_cluster' \
  --sudo-recovery

Explicación de los parámetros:

Parámetro Función
--backup=backup-2 Usar este backup como punto de partida para la restauración completa.
--target='2026-09-05 14:30:00' Restaurar todos los WALs desde el backup hasta este timestamp (inclusive).
--recovery-conf='application_name=pitr_cluster' Agregar application_name al archivo postgresql.conf del cluster restaurado – útil para identificar el cluster en el servidor.
--sudo-recovery Usar un namespace de recuperación privilegiado (si no se especifica, el comando será ejecutado en el namespace actual).

¿Cómo se especifica una restauración PITR mediante YAML?

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg-pitr
  namespace: default
spec:
  instances: 1  # Puede ser 1 inicialmente y escalar después
  imageName: ghcr.io/cloudnative-pg/postgresql:18.1-minimal-trixie
  bootstrap:
    recovery:
      backup:
        name: backup-2  # El backup base completo del que se partirá
      recoveryTarget:
        targetTimeStamp: "2026-09-05T14:30:00Z"  # El timestamp exacto al que se quiere restaurar
        # También se puede usar targetImmediate (true) para restaurar a la instancia más reciente
        # targetImmediate: true
        # Si el backup no contiene WALs hasta el timestamp, es necesario incluir un backup más reciente:
        # recoveryWalSource: "latest"
  storage:
    size: 20Gi   # Comienzo pequeño; escalar si es necesario
    storageClass: standard
  resources:
    requests:
      cpu: "500m"
      memory: "256Mi"
  backup:
    target: "prefer-standby"
    barmanObjectStore:
      objectStore:
        name: pg-backup-store
  plugins:
    - name: barman-cloud.cloudnative-pg.io
      isWALArchiver: true
      parameters:
        barmanObjectName: pg-backup-store
        serverName: pg-backup

4. Ver el estado de una restauración

Ambos kubectl cnpg restore y crear un recurso Cluster con bootstrap.recovery serán administrados por el operador CloudNativePG.

# Monitorear el progreso – también funciona para restauraciones desde CLI
kubectl get cluster pg-restored -w

# Ver detalles completos
kubectl describe cluster pg-restored

# Seguir eventos bajo el evento del administrador
kubectl get events --field-selector involvedObject.name=pg-restored

# Una vez que el cluster esté listo:

kubectl get pod -l cnpg.io/cluster=pg-restored
kubectl exec -it <pg-pod> -- psql -U <user> -d <db>

5. Verificación y pruebas de restauración

Después de una restauración exitosa, realice estas verificaciones:

  1. Conexión y datos básicos

    kubectl exec -it $(kubectl get pod -l cnpg.io/cluster=pg-restored -o jsonpath='{.items[0].metadata.name}') -- psql -U app_user -d app_db -c "SELECT COUNT(*) FROM my_table;"
    
  2. Corrupción de WALs

    kubectl exec -it $(kubectl get pod -l cnpg.io/cluster=pg-restored -o jsonpath='{.items[0].metadata.name}') -- pg_verifybackup -D /var/lib/postgresql/data/temporary_backup_path
    

    (El pg_verifybackup es provisto por CloudNativePG y puede ser ejecutado en un contenedor que acceda al backup)

  3. Puntuación de disponibilidad

    kubectl exec -it $(kubectl get pod -l cnpg.io/cluster=pg-restored -o jsonpath='{.items[0].metadata.name}') -- psql -U app_user -d postgres -c "SELECT pg_is_in_recovery();"
    

    Debe devolver f (ya que el cluster restaurado estará en modo de recuperación hasta que se reanude el streaming de WALs).

6. Limpiar un cluster restaurado innecesario

Una vez verificado que el cluster restaurado está funcionando como se espera, se puede eliminar el cluster original si se planea reemplazarlo completamente:

kubectl delete cluster pg-backup --timeout=300s

Luego, renombre o reemplace el cluster restaurado (pg-restored) en el DNS/servicio de la aplicación si es necesario.

Políticas de retención y cómo afectan a la recuperación

  • Backups base (data.retentionPolicy): 7 days → los backups más antiguos de 7 días serán eliminados automáticamente por Barman Cloud. Asegúrese de recuperar todo lo necesario antes de que la retención elimine el backup.
  • WAL archives (wal.retentionPolicy): 14 days → los WALs más antiguos de 14 días serán eliminados. Si se necesita una restauración PITR más antigua, solicite una extensión temporal del backup del object store o mantenga una réplica secundaria separada en otro bucket.

Frecuencia de restauración recomendada

Tasa de cambio Retención recomendada de WAL Frecuencia de backup base
Alta (< 5 min) 7 días Cada 6 h (opcional)
Media (15–30 min) 14 días Diario (midnight)
Baja (> 2 h) 30 días Diario (mediodía)

Los valores por defecto en este repositorio (01-objectstore.yaml) están configurados para una frecuencia media de cambio con retención diaria y de WALs.

Casos de error comunes y soluciones

Síntoma Causa probable Solución
ERROR: file "pg_ident.conf" not found El backup se tomó de un cluster con configuración de autentificación personalizada Copie pg_ident.conf desde el backup original en el nuevo cluster (o restaure el backup completo del cluster original)
FATAL: password authentication failed for user "app" Las credenciales de autenticación no están presentes en el nuevo cluster Aplique el Secret postgresql-superuser o cree una nueva contraseña con kubectl create secret generic ...
RESTORE FAILED: WAL file not found in the object store El WAL necesario para la restauración PITR fue eliminado por la retención Aumente el plazo de retención de WALs en 01-objectstore.yaml o use un backup más reciente como punto de partida para la restauración.

Resumen rápido (cheat-sheet)

# Listar backups
kubectl get backups -o wide

# Restaurar al backup más reciente
kubectl cnpg restore pg-backup --backup=latest

# Restaurar al timestamp específico (PITR)
kubectl cnpg restore pg-backup --backup=backup-2 --target='2026-09-05 14:30:00'

# Monitorear la restauración
kubectl get cluster pg-restored -w
kubectl describe cluster pg-restored

# Probar la conexión después de la restauración
kubectl exec -it <pg-pod> -- psql -U app_user -d app_db -c "SELECT version();"

Referencias

Este procedimiento se actualiza cuando se usan nuevas versiones del plugin Barman Cloud o del operador CloudNativePG.