281 lines
11 KiB
Markdown
281 lines
11 KiB
Markdown
# 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](https://cloudnative-pg.io/plugin-barman-cloud/) (`barman-cloud.cloudnative-pg.io`) debe estar instalado en el cluster:
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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.
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
# 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:
|
||
|
||
```bash
|
||
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?**
|
||
|
||
```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.
|
||
|
||
```bash
|
||
# 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**
|
||
```bash
|
||
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**
|
||
```bash
|
||
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**
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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)
|
||
|
||
```bash
|
||
# 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
|
||
|
||
- [Documentación de CloudNativePG – Backups](https://cloudnative-pg.io/docs/current/backup/)
|
||
- [Documentación del plugin Barman Cloud – Retención](https://cloudnative-pg.io/plugin-barman-cloud/docs/retention/)
|
||
- [CloudNativePG – Recuperación PITR](https://cloudnative-pg.io/docs/current/recovery/)
|
||
|
||
Este procedimiento se actualiza cuando se usan nuevas versiones del plugin Barman Cloud o del operador CloudNativePG. |