docs: add recovery procedure documentation
This commit is contained in:
parent
4db9f14285
commit
93d861d7a7
281
docs/recovery-procedure.md
Normal file
281
docs/recovery-procedure.md
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
# 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.
|
||||||
Loading…
Reference in New Issue
Block a user