Workstation Logo
Productos
Labs de IAAgentes OpenAIAgentes ClaudeGrok BotWorkstation CRM (WSL CRM)MarketingTodos los Productos
Soluciones IA
Estaciones de Trabajo IAAI SME PackagesIA PrivadaClústeres GPUIA en el BordeLaboratorio IA EmpresarialIA por Industria
Servicios
Modernización de plataformaIngeniería digitalFundamentos de datos e IAOperaciones autónomasConsultoría de IAAutomatización DevOpsCiberseguridadDesarrollo de softwareCreación de agentesConfiguración MLOps
Sobre Nosotros
SociosHistorias de Clientes
Artículos
Documentación
WSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7
Blog
ContáctenosLogin
Workstation

Estaciones de trabajo de IA, software multiagente de IA, infraestructura de GPU y soluciones de agentes inteligentes para empresas modernas.

Contáctenos

Soluciones de IA

Estaciones de Trabajo IAAI SME PackagesIA PrivadaClústeres GPUIA en el BordeLaboratorio IA EmpresarialIA por Industria

Productos

Todos los ProductosWSL CRM y ERPMarketingAgentes OpenAIWSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7

Empresa

Sobre NosotrosPor qué WorkstationSociosHistorias de ClientesPreciosContacto

Recursos

ArtículosDocumentaciónBlogBuscarMapa del Sitio
Oficina Reino Unido
77-79 Marlowes, Hemel Hempstead HP1 1LFCómo llegar: tome la salida 20 de la M25, Outer LondonN.º de empresa: 11641870Lun - Vie: 9:00 - 18:00 GMT
+44 7515 356 146
Oficina Bélgica
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683Lun - Vie: 9:00 - 18:00 CET
+32 492 45 67 46
Oficina India
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841

© 2026 Workstation AI. Todos los derechos reservados.

PrivacidadCookiesTérminos de ServicioMapa del sitio web

Loading blog...

Home / Blog
DatabaseKubernetesDevOpsBackend

Alta disponibilidad de PostgreSQL con PGO de datos crujientes: implementación empresarial de Kubernetes

Enterprise PostgreSQL HA con Crunchy Data PGO en Kubernetes

Balinder Walia12 de abril de 202630 min read

La ejecución de PostgreSQL en producción en Kubernetes exige más que un StatefulSet con un volumen persistente. Necesita conmutación por error automatizada, copia de seguridad continua y recuperación en un punto en el tiempo, agrupación de conexiones, cifrado TLS, monitoreo y la capacidad de implementar de manera consistente entre proveedores de nube y bare metal. Crunchy Data PGO (Postgres Operador) v5 ofrece todo esto a través de un único recurso personalizado nativo de Kubernetes, elPostgresClusterCRD, respaldado por componentes probados en batalla: Patroni para HA basada en consenso, pgBackRest para respaldo empresarial, PgBouncer para agrupación de conexiones y pgMonitor para observabilidad compatible con Prometheus.

Esta guía cubre todo lo necesario para llevar un clúster PostgreSQL administrado por PGO desde la implementación inicial hasta la operación de nivel de producción en AWS EKS, Azure AKS, GCP GKE y k3s bare metal con Rancher. Cada sección incluye valores concretos de YAML, Helm y procedimientos operativos que puede adaptar a su entorno.

Datos crujientes Arquitectura PGO v5

PGO v5 es una reescritura completa del operador Crunchy Postgres. Reemplaza los anteriores pgcluster/pgreplica/pgpolicy CRD con un único recursoPostgresClusterque describe de forma declarativa cada aspecto de una implementación PostgreSQL. El operador observa los cambios en este recurso y concilia los objetos Kubernetes subyacentes (StatefulSets, Services, ConfigMaps, Secrets, Jobs) para que coincidan con el estado deseado.

La arquitectura se basa en cuatro pilares.Patronise ejecuta como sidecar en cada módulo PostgreSQL y gestiona la elección del líder, la topología de replicación y la conmutación por error automática mediante el consenso distribuido nativo de Kubernetes.pgBackRestmaneja copias de seguridad completas, diferenciales e incrementales, además de archivado WAL continuo en almacenamiento de objetos (S3, GCS, Azure Blob) o PVC locales.PgBouncerproporciona una agrupación de conexiones liviana que protege a PostgreSQL de tormentas de conexiones.pgMonitorexpone métricas PostgreSQL a través de un sidecar exportador Prometheus para la integración con su pila de observabilidad existente.

Arquitectura PGO de datos crujientesMódulo de operador PGOPostgresClúster CRDInstancia primariaStatefulSet (1 módulo)Patroni LíderExportador de pgMonitorInstancias de réplicaStatefulSet (N pods)Patroni RéplicasReplicación de transmisiónpgBackRest RepositorioS3 / GCS / Azure BlobCompleto + Diferencial + IncrArchivo WALWALAgrupador de PgBouncerImplementación de(2+ pods)Prometheus + GrafanapgMonitor MétricasMódulos de aplicacionesConexión a través de PgBouncerPrimarioRéplicasCopia de seguridadAgrupadorMonitoreo

El operador en sí no tiene estado: todo el estado persistente reside en el clúster PostgreSQL y su repositorio de respaldo. Esto significa que puede actualizar o reiniciar el operador sin afectar las bases de datos en ejecución. El bucle de reconciliación del operador es idempotente: aplicar la misma especificaciónPostgresClustervarias veces produce el mismo conjunto de objetos Kubernetes.

Instalación de PGO v5

PGO v5 se puede instalar a través de Helm o manifiestos kubectl directos. Se prefiere el enfoque Helm para la producción porque se integra claramente con los flujos de trabajo de GitOps y proporciona actualizaciones controladas por versiones.

# Add the Crunchy Data Helm repository
helm repo add crunchydata https://charts.crunchydata.com
helm repo update

# Install PGO into its own namespace
helm install pgo crunchydata/pgo \
  --namespace postgres-operator \
  --create-namespace \
  --set controllerImages.cluster=registry.crunchydata.com/crunchydata/postgres-operator:ubi8-5.7.2-0 \
  --set relatedImages.postgres_16=registry.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.6-1 \
  --set relatedImages.pgbackrest=registry.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.54.1-0 \
  --set relatedImages.pgbouncer=registry.crunchydata.com/crunchydata/crunchy-pgbouncer:ubi8-1.23.1-0 \
  --set relatedImages.pgexporter=registry.crunchydata.com/crunchydata/crunchy-postgres-exporter:ubi8-0.16.0-0

Para entornos aislados, refleje las imágenes requeridas en su registro interno y actualice los valores derelatedImagesen consecuencia. PGO solo extraerá imágenes especificadas en los valores Helm o la especificaciónPostgresCluster; nunca accede a registros externos en tiempo de ejecución a menos que esté configurado explícitamente para hacerlo.

# Verify the operator is running
kubectl get pods -n postgres-operator
NAME                                READY   STATUS    RESTARTS   AGE
pgo-controller-manager-7d8f9b6c4-xk2pt   1/1     Running   0          45s

PostgresCluster CRD Especificación

ElPostgresClusterCRD es la superficie declarativa única para toda su implementación PostgreSQL. A continuación se muestra una especificación lista para producción que demuestra las secciones clave. Cada sección se analiza en detalle en partes posteriores de esta guía.

apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
  name: production-db
  namespace: databases
spec:
  postgresVersion: 16
  image: registry.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.6-1

  instances:
    - name: pgha1
      replicas: 3
      resources:
        requests:
          cpu: "2"
          memory: 8Gi
        limits:
          cpu: "4"
          memory: 16Gi
      dataVolumeClaimSpec:
        storageClassName: gp3-csi
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 100Gi
      walVolumeClaimSpec:
        storageClassName: gp3-csi
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 20Gi
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - topologyKey: kubernetes.io/hostname
              labelSelector:
                matchLabels:
                  postgres-operator.crunchydata.com/cluster: production-db
      tolerations:
        - key: "workload"
          operator: "Equal"
          value: "database"
          effect: "NoSchedule"

  backups:
    pgbackrest:
      image: registry.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.54.1-0
      configuration:
        - secret:
            name: pgbackrest-s3-creds
      global:
        repo1-retention-full: "7"
        repo1-retention-diff: "14"
        repo1-path: /pgbackrest/production-db/repo1
        repo1-s3-uri-style: path
      repos:
        - name: repo1
          schedules:
            full: "0 2 * * 0"         # Sunday 2am
            differential: "0 2 * * 1-6" # Mon-Sat 2am
            incremental: "0 */4 * * *"  # Every 4 hours
          s3:
            bucket: mycompany-pg-backups
            endpoint: s3.eu-west-1.amazonaws.com
            region: eu-west-1

  proxy:
    pgBouncer:
      image: registry.crunchydata.com/crunchydata/crunchy-pgbouncer:ubi8-1.23.1-0
      replicas: 2
      resources:
        requests:
          cpu: 500m
          memory: 256Mi
        limits:
          cpu: "1"
          memory: 512Mi
      config:
        global:
          pool_mode: transaction
          max_client_conn: "1000"
          default_pool_size: "25"
          min_pool_size: "5"
          reserve_pool_size: "5"
          reserve_pool_timeout: "3"

  monitoring:
    pgmonitor:
      exporter:
        image: registry.crunchydata.com/crunchydata/crunchy-postgres-exporter:ubi8-0.16.0-0
        resources:
          requests:
            cpu: 100m
            memory: 128Mi

  patroni:
    dynamicConfiguration:
      synchronous_mode: true
      postgresql:
        parameters:
          shared_buffers: 2GB
          effective_cache_size: 6GB
          work_mem: 32MB
          maintenance_work_mem: 512MB
          max_connections: 200
          wal_buffers: 64MB
          checkpoint_completion_target: 0.9
          random_page_cost: 1.1
          effective_io_concurrency: 200
          min_wal_size: 1GB
          max_wal_size: 4GB
          max_worker_processes: 8
          max_parallel_workers_per_gather: 4
          max_parallel_workers: 8
          log_min_duration_statement: 500
          log_checkpoints: "on"
          log_connections: "on"
          log_disconnections: "on"
          log_lock_waits: "on"

  users:
    - name: appuser
      databases: ["appdb"]
      options: "NOSUPERUSER"
    - name: readonly
      databases: ["appdb"]
      options: "NOSUPERUSER"

  databaseInitSQL:
    name: init-sql-configmap
    key: init.sql

Esta especificación crea un clúster PostgreSQL 16 de tres instancias con datos y volúmenes WAL separados, copias de seguridad respaldadas por S3 en un cronograma completo/diferencial/incremental, agrupación de conexiones PgBouncer en modo de transacción, exportación de métricas Prometheus y replicación sincrónica de Patroni. La regla antiafinidad del pod garantiza que las tres instancias aterricen en diferentes nodos Kubernetes.

HA basado en Patroni y conmutación por error automática

Patroni es el marco HA integrado en cada pod PostgreSQL administrado por PGO. Utiliza Kubernetes API como su almacén de configuración distribuida (DCS); no se requiere un etcd o un clúster ZooKeeper por separado. Patroni monitorea continuamente el estado del PostgreSQL primario y de las réplicas. Cuando la principal deja de responder, Patroni inicia una conmutación por error automática: promueve la réplica más actualizada a principal y reconfigura las réplicas restantes para seguir al nuevo líder.

El proceso de conmutación por error en PGO funciona de la siguiente manera. Patroni en cada pod tiene un bloqueo de líder en Kubernetes (a través de objetos Endpoints u ConfigMap). El primario actual debe renovar este bloqueo en un intervalo configurable (TTL predeterminado de 10 segundos, espera de bucle de 3 segundos). Si el primario no se renueva (porque falló, el nodo murió o la red lo dividió), una réplica que esté más cercana a la posición WAL del primario adquirirá el bloqueo y se promocionará a sí misma. Todo el proceso normalmente se completa en 10 a 30 segundos.

El modo de replicación síncrona, habilitado a través desynchronous_mode: trueen la configuración Patroni, garantiza cero pérdida de datos (RPO = 0) a costa de una latencia de escritura ligeramente mayor. En modo síncrono, una transacción no se reconoce al cliente hasta que al menos una réplica haya confirmado la recepción del WAL. Si no hay una réplica sincrónica disponible, Patroni desactiva temporalmente el modo sincrónico para mantener la disponibilidad; puede anular esto consynchronous_mode_strict: truesi prefiere sacrificar la disponibilidad por coherencia.

# Check Patroni cluster status
kubectl exec -it production-db-pgha1-0 -n databases -- patronictl list

+----------------------------+-------------------+---------+---------+----+-----------+
| Member                     | Host              | Role    | State   | TL | Lag in MB |
+----------------------------+-------------------+---------+---------+----+-----------+
| production-db-pgha1-0      | 10.244.0.15       | Leader  | running |  3 |           |
| production-db-pgha1-1      | 10.244.1.22       | Replica | running |  3 |         0 |
| production-db-pgha1-2      | 10.244.2.18       | Replica | running |  3 |         0 |
+----------------------------+-------------------+---------+---------+----+-----------+

# Manual switchover (planned, zero downtime)
kubectl exec -it production-db-pgha1-0 -n databases -- \
  patronictl switchover --master production-db-pgha1-0 --candidate production-db-pgha1-1 --force

# Manual failover (forced, for emergencies)
kubectl exec -it production-db-pgha1-1 -n databases -- \
  patronictl failover --candidate production-db-pgha1-1 --force

PGO configura automáticamente los servicios Kubernetes para rastrear al líder Patroni. El servicioproduction-db-primarysiempre apunta al pod que actualmente tiene el bloqueo líder, por lo que las aplicaciones que se conectan a través de este servicio experimentan una conmutación por error perfecta con solo un breve restablecimiento de la conexión.

pgBackRest Copia de seguridad y restauración

pgBackRest es el motor de respaldo integrado en PGO. Admite tres tipos de copia de seguridad (completa, diferencial e incremental), además de archivado WAL continuo para recuperación en un momento dado (PITR). Comprender cómo encajan es esencial para diseñar una estrategia de respaldo que equilibre el costo de almacenamiento, la velocidad del respaldo y el tiempo de recuperación.

pgBackRest Arquitectura de copia de seguridadPostgreSQL PrimarioArchivos de datos(PGDATA)Segmentos WALpg_wal/ directoriopgBackRest AgenteArchivo WAL continuoCopias de seguridad programadaspgBackRest RepositorioS3 / GCS / Azure Blob / PVCCopia de seguridad completaCopia completaDiferencialDesde el últimocompletoIncremental (desde el último)Archivo WAL000000030000000A000000030000000B000000030000000C... continuo ...habilita PITRLínea de tiempo de recuperación en un momento dadoCompletoDom 2 a.m.DiferencialDiferencialDiferencialDiferencialDiferencialCompletoDom 2 a.m.Flujo WAL continuo →Objetivo PITRRestaurar en cualquier momentoCopia de seguridad completaDiferencialTransmisión WALDestino de recuperación

Una copia de seguridad completa decopia todo el directorio de datos de PostgreSQL y es la base para todos los demás tipos de copias de seguridad. Una copia de seguridad diferencialcopia solo las páginas que cambiaron desde la última copia de seguridad completa. Una copia de seguridad incrementalcopia solo las páginas que cambiaron desde la última copia de seguridad de cualquier tipo. Durante la restauración, pgBackRest encadena automáticamente las copias de seguridad requeridas; por ejemplo, la restauración desde una incremental requiere la incremental más la diferencial anterior (o completa) más la copia de seguridad completa, más cualquier segmento WAL necesario para alcanzar el punto de recuperación de destino.

Configuración del programa de respaldo

La programación de la copia de seguridad se define en la secciónreposde la configuración de pgBackRest dentro de la especificaciónPostgresCluster. Un programa de producción sólido normalmente ejecuta copias de seguridad semanales completas, diferenciales diarias y incrementales más frecuentes.

backups:
  pgbackrest:
    global:
      repo1-retention-full: "4"        # Keep 4 full backups
      repo1-retention-full-type: count
      repo1-retention-diff: "14"       # Keep 14 differentials
    repos:
      - name: repo1
        schedules:
          full: "0 2 * * 0"            # Weekly full: Sunday 2am
          differential: "0 2 * * 1-6"  # Daily diff: Mon-Sat 2am
          incremental: "0 */6 * * *"   # Every 6 hours
        s3:
          bucket: mycompany-pg-backups
          endpoint: s3.eu-west-1.amazonaws.com
          region: eu-west-1

Copia de seguridad y restauración manual

# Trigger a manual full backup
kubectl annotate postgrescluster production-db -n databases \
  postgres-operator.crunchydata.com/pgbackrest-backup="$(date +%s)" \
  --overwrite

# Check backup status
kubectl exec -it production-db-pgha1-0 -n databases -- \
  pgbackrest info --stanza=db

# Restore to a specific point in time
# First, update the PostgresCluster spec:
spec:
  backups:
    pgbackrest:
      restore:
        enabled: true
        repoName: repo1
        options:
          - --type=time
          - --target="2026-04-12 08:30:00+00"
          - --target-action=promote

# Apply the restore annotation
kubectl annotate postgrescluster production-db -n databases \
  postgres-operator.crunchydata.com/pgbackrest-restore="$(date +%s)" \
  --overwrite

Durante una restauración PITR, PGO apaga todas las instancias PostgreSQL, restaura desde la copia de seguridad diferencial o completa más cercana, reproduce segmentos WAL hasta el tiempo objetivo y luego inicia el clúster. Toda la operación la organiza el operador; no se necesita intervención manual en módulos individuales.

Agrupación de conexiones PgBouncer

PostgreSQL crea un nuevo proceso para cada conexión de cliente. A escala (cientos o miles de módulos de aplicaciones, cada uno de los cuales mantiene grupos de conexiones), este modelo falla. PgBouncer se ubica entre su aplicación y PostgreSQL, multiplexando muchas conexiones de clientes a través de una cantidad menor de conexiones de servidor.

PGO implementa PgBouncer como una implementación separada con su propio servicio. El servicioproduction-db-pgbounceres a lo que deben conectarse sus aplicaciones, no directamente al servicio principal PostgreSQL. PgBouncer admite tres modos de grupo:

  • Agrupación de sesiones: se asigna una conexión de servidor a un cliente durante la vida útil de la conexión del cliente. Más seguro, pero menos eficiente.
  • Agrupación de transacciones: se asigna una conexión de servidor solo durante la duración de una transacción. Más eficiente para cargas de trabajo web. Este es el valor predeterminado recomendado.
  • Agrupación de declaraciones: se asigna una conexión de servidor para una sola declaración. Solo funciona para cargas de trabajo simples y no transaccionales.
proxy:
  pgBouncer:
    replicas: 3
    config:
      global:
        pool_mode: transaction
        max_client_conn: "2000"
        default_pool_size: "30"
        min_pool_size: "10"
        reserve_pool_size: "10"
        reserve_pool_timeout: "3"
        server_idle_timeout: "300"
        server_lifetime: "3600"
        client_idle_timeout: "600"
        tcp_keepalive: "1"
        tcp_keepidle: "30"
        tcp_keepintvl: "10"
        tcp_keepcnt: "3"
    affinity:
      podAntiAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              topologyKey: kubernetes.io/hostname
              labelSelector:
                matchLabels:
                  postgres-operator.crunchydata.com/role: pgbouncer

Tenga en cuenta la configuración detcp_keepalive: son fundamentales cuando PgBouncer se ejecuta detrás de un equilibrador de carga en la nube o el servicio Kubernetes. Sin medidas de mantenimiento agresivas, los componentes intermedios de la red pueden interrumpir silenciosamente las conexiones inactivas, lo que provoca errores de aplicación en el siguiente intento de consulta.

pgMonitor y Prometheus/Grafana Monitoreo

La integración de monitoreo de

PGO implementa un sidecarcrunchy-postgres-exporteren cada módulo PostgreSQL. Este exportador extrae las vistas de estadísticas internas de PostgreSQL y las expone como métricas Prometheus en el puerto 9187. El exportador cubre más de 150 métricas listas para usar, incluidas conexiones, retraso de replicación, tasas de transacciones, tasas de aciertos de caché, estadísticas de tablas e índices, contención de bloqueo y tasas de generación de WAL.

# ServiceMonitor for Prometheus Operator auto-discovery
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: postgres-monitoring
  namespace: databases
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      postgres-operator.crunchydata.com/cluster: production-db
      postgres-operator.crunchydata.com/crunchy-postgres-exporter: "true"
  endpoints:
    - port: exporter
      interval: 15s
      scrapeTimeout: 10s

Crunchy Data proporciona un conjunto de paneles Grafana prediseñados que puede importar directamente. Estos cubren la descripción general de PostgreSQL, el estado de replicación, el estado de la copia de seguridad de pgBackRest, las estadísticas de PgBouncer y el uso de recursos a nivel de pod. Importarlos a través del aprovisionamiento del panel de Grafana o manualmente desde el repositorio de ejemplos de Crunchy Data.

# Install Grafana dashboards as ConfigMaps
kubectl create configmap grafana-pg-overview \
  --from-file=pg-overview.json=dashboards/pg-overview.json \
  -n monitoring
kubectl label configmap grafana-pg-overview grafana_dashboard=1 -n monitoring
Reglas de alerta crítica

para PostgreSQL

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: postgres-alerts
  namespace: databases
  labels:
    release: kube-prometheus-stack
spec:
  groups:
    - name: postgresql-health
      rules:
        - alert: PostgresReplicationLagHigh
          expr: ccp_replication_lag_size_bytes > 104857600
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "Replica {{ $labels.pod }} lag exceeds 100MB"

        - alert: PostgresConnectionsExhausted
          expr: ccp_connection_stats_active / ccp_connection_stats_max_connections > 0.85
          for: 2m
          labels:
            severity: critical
          annotations:
            summary: "PostgreSQL connections above 85% capacity"

        - alert: PostgresDeadlockDetected
          expr: rate(ccp_stat_database_deadlocks[5m]) > 0
          for: 1m
          labels:
            severity: warning
          annotations:
            summary: "Deadlocks detected in {{ $labels.datname }}"

        - alert: PostgresCacheHitRatioLow
          expr: ccp_stat_database_blks_hit / (ccp_stat_database_blks_hit + ccp_stat_database_blks_read) < 0.95
          for: 10m
          labels:
            severity: warning
          annotations:
            summary: "Cache hit ratio below 95% for {{ $labels.datname }}"

        - alert: PgBackRestStaleBackup
          expr: time() - ccp_backrest_last_full_backup_time_since_completion_seconds > 604800
          for: 1h
          labels:
            severity: critical
          annotations:
            summary: "No full backup in the last 7 days"

AWS Implementación de EKS

La implementación de PGO en AWS EKS requiere configurar el controlador CSI de EBS para volúmenes persistentes y funciones de IAM para cuentas de servicio (IRSA) para el acceso a la copia de seguridad de S3. Este enfoque evita almacenar credenciales AWS de larga duración en secretos Kubernetes.

# Install the EBS CSI driver (required for gp3 volumes)
eksctl create addon --name aws-ebs-csi-driver --cluster my-cluster --region eu-west-1 \
  --service-account-role-arn arn:aws:iam::111122223333:role/AmazonEKS_EBS_CSI_DriverRole

# Create a gp3 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gp3-csi
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  iops: "3000"
  throughput: "125"
  encrypted: "true"
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
# IAM policy for pgBackRest S3 access
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::mycompany-pg-backups",
        "arn:aws:s3:::mycompany-pg-backups/*"
      ]
    }
  ]
}

# Create an IRSA-enabled service account
eksctl create iamserviceaccount \
  --name pgbackrest-sa \
  --namespace databases \
  --cluster my-cluster \
  --attach-policy-arn arn:aws:iam::111122223333:policy/PGBackRestS3Policy \
  --approve

En la especificaciónPostgresCluster, haga referencia al depósito y la región de S3. PGO utilizará las credenciales de la cuenta de servicio del pod (a través de IRSA) automáticamente; no se necesitan claves de acceso explícitas.

backups:
  pgbackrest:
    repos:
      - name: repo1
        s3:
          bucket: mycompany-pg-backups
          endpoint: s3.eu-west-1.amazonaws.com
          region: eu-west-1

Para lograr resiliencia multi-AZ, asegúrese de que sus grupos de nodos EKS abarquen al menos tres zonas de disponibilidad y utilice las restricciones de distribución de topología que se mostraron anteriormente para distribuir los pods PostgreSQL entre ellos.

Azure Implementación de AKS

Azure AKS utiliza discos administrados para almacenamiento persistente y Azure Blob Storage para copias de seguridad de pgBackRest. La clase de almacenamiento recomendada utiliza Premium SSD v2 o Premium LRS para cargas de trabajo de bases de datos.

# StorageClass for Azure Premium SSD
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: azure-premium-ssd
provisioner: disk.csi.azure.com
parameters:
  skuName: Premium_LRS
  kind: Managed
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true

---
# pgBackRest with Azure Blob Storage
backups:
  pgbackrest:
    configuration:
      - secret:
          name: pgbackrest-azure-creds
    global:
      repo1-azure-account: mystorageaccount
      repo1-retention-full: "7"
    repos:
      - name: repo1
        schedules:
          full: "0 2 * * 0"
          differential: "0 2 * * 1-6"
        azure:
          container: pg-backups

---
# Secret with Azure credentials
apiVersion: v1
kind: Secret
metadata:
  name: pgbackrest-azure-creds
  namespace: databases
stringData:
  azure.conf: |
    [global]
    repo1-azure-key=BASE64_STORAGE_ACCOUNT_KEY

Para Workload Identity (el equivalente Azure de AWS IRSA), configure el clúster de AKS con el emisor OIDC y cree una credencial de identidad federada para la cuenta de servicio pgBackRest. Esto elimina la necesidad de almacenar las claves de las cuentas en secreto.

Implementación de

GCP GKE

GKE utiliza disco persistente (pd-ssd) para almacenamiento y GCS para copias de seguridad de pgBackRest. GKE Workload Identity asigna cuentas de servicio Kubernetes a cuentas de servicio de Google Cloud para una autenticación segura y sin clave.

# StorageClass for GKE SSD Persistent Disk
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: pd-ssd
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true

---
# pgBackRest with GCS
backups:
  pgbackrest:
    configuration:
      - secret:
          name: pgbackrest-gcs-creds
    repos:
      - name: repo1
        gcs:
          bucket: mycompany-pg-backups

---
# GCS service account key secret
apiVersion: v1
kind: Secret
metadata:
  name: pgbackrest-gcs-creds
  namespace: databases
stringData:
  gcs-key.json: |
    {
      "type": "service_account",
      "project_id": "my-project",
      ...
    }
# Enable Workload Identity on GKE
gcloud container clusters update my-cluster \
  --workload-pool=my-project.svc.id.goog

# Create and bind IAM service account
gcloud iam service-accounts create pgbackrest-gcs \
  --display-name="pgBackRest GCS Access"

gcloud projects add-iam-policy-binding my-project \
  --member="serviceAccount:pgbackrest-gcs@my-project.iam.gserviceaccount.com" \
  --role="roles/storage.objectAdmin"

gcloud iam service-accounts add-iam-policy-binding \
  pgbackrest-gcs@my-project.iam.gserviceaccount.com \
  --role="roles/iam.workloadIdentityUser" \
  --member="serviceAccount:my-project.svc.id.goog[databases/production-db-pgbackrest]"

Recuperación ante desastres en varias regiones

PGO admite clústeres en espera para la recuperación ante desastres entre regiones. Un clúster en espera reproduce continuamente WAL desde el repositorio pgBackRest del clúster primario, manteniendo una copia activa que puede promoverse a primario independiente en caso de una falla regional.

DR multirregional con clústeres en espera PGORegión A (primaria)por ejemplo, AWS eu-west-1 / Azure Europa occidentalPostgreSQL PrimarioLectura/EscrituraPatroni LíderRéplicas(2)Sólo lecturaReplicación de sincronizaciónArchivo WALpgRepositorio BackRest (S3/GCS/Blob)Replicación entre regiones habilitadaS3 entre regionesReplicaciónRegión B (en espera)por ejemplo, AWS us-east-1 / Azure East USPostgreSQL Clúster en esperaReproducción WAL continua desde RepoSólo lectura (modo de espera)pgBackRest Repo (Región B)Replicado de la Región AWAL RepeticiónConmutación por error/PromociónModo síncronoRPO ≈ minutos (envío WAL)RTO ≈ 5-15 minutosAsíncrono (predeterminado)RPO ≈ segundos-minutosRTO ≈ 5-15 minutosEl clúster en esperase puede promover a primario independiente mediante el cambio de especificaciones del clúster Postgres
# Standby cluster in Region B
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
  name: production-db-standby
  namespace: databases
spec:
  postgresVersion: 16
  image: registry.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.6-1

  standby:
    enabled: true
    repoName: repo1

  instances:
    - name: pgha1
      replicas: 2
      dataVolumeClaimSpec:
        storageClassName: gp3-csi
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 100Gi

  backups:
    pgbackrest:
      image: registry.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.54.1-0
      configuration:
        - secret:
            name: pgbackrest-s3-creds
      repos:
        - name: repo1
          s3:
            bucket: mycompany-pg-backups
            endpoint: s3.us-east-1.amazonaws.com
            region: us-east-1

Para promover el clúster en espera durante un desastre, configurestandby.enabled: falseen la especificación y aplique el cambio. PGO promueve el standby a un grupo primario independiente. Esta promoción es irreversible: deberá reconstruir la relación de replicación desde cero después de que se recupere la región primaria original.

Despliegue de metal desnudo k3s/Rancher

La ejecución de PGO en k3s sin sistema operativo con administración Rancher requiere atención cuidadosa al almacenamiento y las redes, ya que no tiene discos administrados por el proveedor de la nube ni balanceadores de carga.

k3s / Implementación de Rancher PGO (metal desnudo)Servidor de gestión ganaderoClústerk3s (3 servidores + N nodos de agente)Operador PGOAgente Nodo 1PostgreSQL Primario+ Exportador de pgMonitorLonghorn PVC (datos + WAL)pgBackRest Repositorio (PVC local)Agente Nodo 2PostgreSQL Réplica 1+ Exportador de pgMonitorLonghorn PVC (datos + WAL)Cápsula PgBouncerAgente Nodo 3PostgreSQL Réplica 2+ Exportador de pgMonitorLonghorn PVC (datos + WAL)Cápsula PgBouncerEquilibrador de cargaMetalLB — Expone pg-primary:5432 + pgbouncer:5432PrimarioRéplicasBocina largaCopia de seguridadPgBouncerMetalLBOperador

Almacenamiento de cuerno largo

Longhorn es un sistema de almacenamiento en bloques distribuido y liviano para Kubernetes que es ideal para entornos bare metal. Replica volúmenes en múltiples nodos para mayor durabilidad y admite instantáneas, copias de seguridad y expansión de volúmenes.

# Install Longhorn via Helm
helm repo add longhorn https://charts.longhorn.io
helm repo update

helm install longhorn longhorn/longhorn \
  --namespace longhorn-system \
  --create-namespace \
  --set defaultSettings.defaultReplicaCount=3 \
  --set defaultSettings.storageOverProvisioningPercentage=100 \
  --set defaultSettings.storageMinimalAvailablePercentage=15

---
# Longhorn StorageClass for PostgreSQL
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-pg
provisioner: driver.longhorn.io
parameters:
  numberOfReplicas: "3"
  staleReplicaTimeout: "2880"
  fsType: ext4
  dataLocality: best-effort
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Retain

MetalLB para equilibrio de carga

# Install MetalLB
helm repo add metallb https://metallb.github.io/metallb
helm install metallb metallb/metallb --namespace metallb-system --create-namespace

---
# Configure IP address pool
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: pg-pool
  namespace: metallb-system
spec:
  addresses:
    - 192.168.1.200-192.168.1.210
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: pg-l2
  namespace: metallb-system
spec:
  ipAddressPools:
    - pg-pool

Con MetalLB configurado, los servicios de PGO de tipoLoadBalancerrecibirán direcciones IP de su grupo, lo que hará que los puntos finales primarios PostgreSQL y PgBouncer sean directamente accesibles desde su red sin reenvío manual de puertos.

pgBackRest con PVC local o NFS para Bare Metal

# For environments without S3/GCS/Azure Blob, use a PVC-based repo
backups:
  pgbackrest:
    repos:
      - name: repo1
        schedules:
          full: "0 2 * * 0"
          differential: "0 2 * * 1-6"
        volume:
          volumeClaimSpec:
            storageClassName: longhorn-pg
            accessModes: ["ReadWriteOnce"]
            resources:
              requests:
                storage: 200Gi

Para entornos aislados, también puede configurar un repositorio pgBackRest secundario que envía copias de seguridad a un recurso compartido NFS o una instancia MinIO que se ejecuta localmente, proporcionando una copia de seguridad fuera del clúster sin dependencias de la nube.

TLS/SSL Configuración de cifrado

PGO genera certificados TLS autofirmados para todas las comunicaciones internas de forma predeterminada: las instancias PostgreSQL, la replicación, pgBackRest y PgBouncer se comunican a través de canales cifrados sin ninguna gestión manual de certificados. Sin embargo, para entornos de producción normalmente querrá utilizar certificados firmados por la CA de su organización.

# Create a TLS secret with your CA-signed certificates
kubectl create secret tls production-db-tls \
  --cert=server.crt \
  --key=server.key \
  -n databases

kubectl create secret generic production-db-ca \
  --from-file=ca.crt=ca.crt \
  -n databases

---
# Reference in PostgresCluster spec
spec:
  customTLSSecret:
    name: production-db-tls
  customReplicationTLSSecret:
    name: production-db-replication-tls

PGO configura PostgreSQL conssl = ony establece los parámetrosssl_cert_file,ssl_key_fileyssl_ca_fileapropiados. PgBouncer está configurado de manera similar para requerir TLS para conexiones de clientes y para usar TLS cuando se conecta a backends PostgreSQL.

# Enforce TLS for all client connections via pg_hba.conf
spec:
  patroni:
    dynamicConfiguration:
      postgresql:
        pg_hba:
          - hostssl all all 0.0.0.0/0 scram-sha-256
          - hostssl replication all 0.0.0.0/0 scram-sha-256

Configuración personalizada de PostgreSQL

PGO expone la configuración de PostgreSQL a través de la sección de configuración dinámica de Patroni. Este es el enfoque recomendado porque Patroni garantiza que todas las instancias mantengan una configuración consistente y maneja los reinicios cuando sea necesario.

patroni:
  dynamicConfiguration:
    postgresql:
      parameters:
        # Memory
        shared_buffers: 4GB
        effective_cache_size: 12GB
        work_mem: 64MB
        maintenance_work_mem: 1GB
        huge_pages: "try"

        # WAL
        wal_buffers: 128MB
        min_wal_size: 2GB
        max_wal_size: 8GB
        checkpoint_completion_target: 0.9
        wal_compression: lz4

        # Query Planning
        random_page_cost: 1.1
        effective_io_concurrency: 200
        default_statistics_target: 200

        # Parallelism
        max_worker_processes: 16
        max_parallel_workers_per_gather: 4
        max_parallel_workers: 8
        max_parallel_maintenance_workers: 4

        # Connections
        max_connections: 200
        idle_in_transaction_session_timeout: 60000
        statement_timeout: 300000

        # Logging
        log_min_duration_statement: 250
        log_checkpoints: "on"
        log_connections: "on"
        log_disconnections: "on"
        log_lock_waits: "on"
        log_temp_files: 0
        log_autovacuum_min_duration: 0

        # Autovacuum Tuning
        autovacuum_max_workers: 5
        autovacuum_naptime: 30
        autovacuum_vacuum_cost_limit: 800
        autovacuum_vacuum_scale_factor: 0.02
        autovacuum_analyze_scale_factor: 0.01

Estos parámetros suponen un nodo con 16 núcleos CPU y 32 GB de RAM dedicados a PostgreSQL. Ajusteshared_buffersa aproximadamente el 25% de la RAM disponible yeffective_cache_sizea aproximadamente el 75%. La configuración de WAL y de puntos de control está optimizada para cargas de trabajo con mucha escritura: reduzcamax_wal_sizepara sistemas con mucha lectura donde la frecuencia de los puntos de control importa menos.

Gestión de usuarios y bases de datos

PGO administra usuarios y bases de datos PostgreSQL de forma declarativa a través de la secciónusersde la especificaciónPostgresCluster. Cuando agrega un usuario, PGO crea la función en PostgreSQL, genera una contraseña aleatoria y almacena las credenciales en un secreto Kubernetes.

users:
  - name: appuser
    databases: ["appdb"]
    options: "NOSUPERUSER NOCREATEDB NOCREATEROLE"
  - name: readonly
    databases: ["appdb"]
    options: "NOSUPERUSER NOCREATEDB NOCREATEROLE"
  - name: migrations
    databases: ["appdb"]
    options: "NOSUPERUSER CREATEDB"
  - name: monitoring
    databases: ["postgres"]
    options: "NOSUPERUSER LOGIN"

---
# Access credentials from the generated secret
kubectl get secret production-db-pguser-appuser -n databases -o jsonpath='{.data.password}' | base64 -d

# The secret also contains a full connection URI
kubectl get secret production-db-pguser-appuser -n databases -o jsonpath='{.data.uri}' | base64 -d
# postgresql://appuser:PASSWORD@production-db-primary.databases.svc:5432/appdb

Para otorgar acceso de solo lectura, use la funcióndatabaseInitSQLpara ejecutar SQL en la creación del clúster que crea una función de solo lectura y le otorga SELECT en todas las tablas.

# init.sql ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: init-sql-configmap
  namespace: databases
data:
  init.sql: |
    -- Read-only role for reporting users
    ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
    GRANT CONNECT ON DATABASE appdb TO readonly;
    GRANT USAGE ON SCHEMA public TO readonly;
    GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;

    -- Extensions
    CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
    CREATE EXTENSION IF NOT EXISTS pgcrypto;
    CREATE EXTENSION IF NOT EXISTS pg_trgm;

Actualizaciones continuas y actualizaciones de versiones principales

PGO maneja actualizaciones de versiones menores mediante actualizaciones continuas. Cuando cambia la etiqueta de imagen en la especificaciónPostgresClustera una versión de parche más reciente, PGO actualiza las instancias una a la vez, comenzando con las réplicas y terminando con la primaria (lo que activa un cambio de Patroni para minimizar el tiempo de inactividad).

# Minor version upgrade: change the image tag
spec:
  image: registry.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.7-0

Las actualizaciones de la versión principal (por ejemplo, PostgreSQL 15 a 16) requierenpg_upgrade, que PGO organiza a través de unPGUpgradeCRD separado.

apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PGUpgrade
metadata:
  name: production-db-upgrade
  namespace: databases
spec:
  postgresClusterName: production-db
  fromPostgresVersion: 15
  toPostgresVersion: 16
  image: registry.crunchydata.com/crunchydata/crunchy-upgrade:ubi8-5.7.2-0

El proceso de actualización cierra el clúster existente, ejecutapg_upgrade --linkpara realizar una actualización local utilizando enlaces físicos (minimizando la copia de datos), verifica la actualización e inicia el clúster en la nueva versión. Realice siempre una copia de seguridad completa antes de iniciar una actualización de versión principal y pruebe primero el procedimiento en un clúster que no sea de producción.

# Pre-upgrade checklist
# 1. Take a full backup
kubectl annotate postgrescluster production-db -n databases \
  postgres-operator.crunchydata.com/pgbackrest-backup="$(date +%s)" \
  --overwrite

# 2. Verify backup completed
kubectl exec -it production-db-pgha1-0 -n databases -- pgbackrest info --stanza=db

# 3. Shutdown the cluster (set replicas to 0 or use PGO shutdown annotation)
kubectl annotate postgrescluster production-db -n databases \
  postgres-operator.crunchydata.com/shutdown="$(date +%s)" \
  --overwrite

# 4. Apply the PGUpgrade resource
kubectl apply -f pg-upgrade.yaml

# 5. Update the PostgresCluster spec with the new version and image
# 6. Remove the shutdown annotation to start the upgraded cluster
Recomendaciones de ajuste de producción de

La ejecución de PGO en producción requiere atención a varias áreas operativas más allá de la implementación inicial.

Rendimiento de almacenamiento

  • Datos separados y volúmenes WAL: Utilice siemprewalVolumeClaimSpecpara colocar WAL en un PVC dedicado. Esto evita que la actividad WAL con mucha escritura compita con la E/S de datos.
  • Utilice almacenamiento con alto IOPS: gp3 (AWS), Premium SSD v2 (Azure), pd-ssd (GCP) o Longhorn con respaldo NVMe en metal desnudo. Los patrones de E/S aleatorios de PostgreSQL exigen almacenamiento de baja latencia.
  • Expansión de volumen: Asegúrese de que su StorageClass tengaallowVolumeExpansion: true. PGO puede ampliar los PVC de forma no disruptiva en proveedores de almacenamiento compatibles.
Presupuestos de interrupción de pods

PGO crea automáticamente PDB para sus instancias PostgreSQL, pero verifique que sean apropiados para sus requisitos de HA.

# Check PDBs
kubectl get pdb -n databases
NAME                    MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
production-db-pgha1     1               N/A               2                     7d

Solicitudes y límites de recursos

  • Establezca las solicitudes de memoria iguales a los límites para los pods de bases de datos para evitar muertes de OOM y garantizar una clase de QoS garantizada.
  • Configure las solicitudes CPU de manera conservadora y limite más alto para permitir la explosión durante las operaciones de vacío o mantenimiento.
  • Monitoree el uso real a través de métricas de pgMonitor y ajuste trimestralmente.

Gestión de conexión

  • Conéctese siempre a través de PgBouncer, no directamente a PostgreSQL.
  • Configuremax_connectionsen PostgreSQL en un valor que tenga en cuenta el tamaño del grupo de PgBouncer más las conexiones del sistema (replicación, monitoreo, superusuario).
  • Utilice el modo de agrupación de transacciones para aplicaciones web. Cambie a la agrupación de sesiones solo si su aplicación utiliza declaraciones preparadas o estado de nivel de sesión (por ejemplo, comandosSET, tablas temporales).

Validación de copia de seguridad

  • Pruebe las restauraciones con regularidad creando un clúster de clonación a partir de la copia de seguridad y ejecutando pruebas de humo a nivel de aplicación.
  • Supervise la alertaPgBackRestStaleBackuppara garantizar que las copias de seguridad se completen según lo programado.
  • Valide PITR restaurando marcas de tiempo específicas y verificando la coherencia de los datos.
# Clone cluster for backup validation
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
  name: backup-validation
  namespace: databases
spec:
  postgresVersion: 16
  image: registry.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.6-1
  dataSource:
    postgresCluster:
      clusterName: production-db
      repoName: repo1
      options:
        - --type=time
        - --target="2026-04-12 06:00:00+00"
  instances:
    - name: pgha1
      replicas: 1
      dataVolumeClaimSpec:
        storageClassName: gp3-csi
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 100Gi
  backups:
    pgbackrest:
      repos:
        - name: repo1
          volume:
            volumeClaimSpec:
              accessModes: ["ReadWriteOnce"]
              resources:
                requests:
                  storage: 50Gi

Políticas de red

# Restrict PostgreSQL traffic to known namespaces
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: postgres-network-policy
  namespace: databases
spec:
  podSelector:
    matchLabels:
      postgres-operator.crunchydata.com/cluster: production-db
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              app-access: database
        - podSelector:
            matchLabels:
              postgres-operator.crunchydata.com/cluster: production-db
      ports:
        - port: 5432
          protocol: TCP
        - port: 9187
          protocol: TCP
Lista de verificación de monitoreo

  • Retraso de replicación: Alerta cuando alguna réplica supera los 100 MB o 60 segundos de retraso.
  • Saturación de conexión: Alerta cuando las conexiones activas superan el 80% demax_connections.
  • Anomalías en la tasa de transacciones: Base de referencia de su TPS y alerta sobre desviaciones significativas.
  • Uso del disco: alerta en umbrales del 70 % y 85 % con runbooks de expansión de volumen.
  • Actualización de la copia de seguridad: alerta cuando la última copia de seguridad completa es anterior a su ventana de RPO.
  • Contención de bloqueo: alerta sobre bloqueos prolongados (> 30 segundos) que pueden indicar errores en la aplicación.
  • Estado del autovacuum: alerta cuando las mesas no se han aspirado en más de 24 horas.
Runbook de recuperación ante desastres

Un plan de recuperación ante desastres sólo es útil si ha sido probado. El siguiente runbook describe los procedimientos clave para recuperarse de escenarios de fallas comunes.

Fallo de módulo único

Patroni y Kubernetes manejan esto automáticamente. Si el módulo principal falla, Patroni promueve una réplica en un plazo de 10 a 30 segundos. Kubernetes reinicia el pod fallido, que se vuelve a unir como una réplica.

Fallo de nodo único

Si un nodo que ejecuta un pod PostgreSQL muere, Kubernetes reprograma el pod en un nodo en buen estado. El pod se conecta a su PVC existente (si el almacenamiento está conectado a la red) o se restaura desde la copia de seguridad (si se utilizó almacenamiento local). Las reglas antiafinidad de pods garantizan que las instancias restantes continúen atendiendo tráfico.

Pérdida completa del clúster

Si se pierde todo el clúster Kubernetes, implemente un nuevo clúster, instale PGO y cree un nuevoPostgresClustercon undataSourceapuntando al repositorio de respaldo. PGO restaura la última copia de seguridad y reproduce WAL en el punto disponible más reciente.

Conmutación por error regional

Si se pierde la región principal, promueva el clúster en espera configurandostandby.enabled: false. Actualice su DNS o balanceador de carga para que apunte a la nueva región principal. Una vez que se recupere la región original, puede reconstruir la relación de espera a la inversa.

# Promote standby cluster
kubectl patch postgrescluster production-db-standby -n databases --type merge \
  -p '{"spec":{"standby":{"enabled":false}}}'

# Verify the cluster is now an independent primary
kubectl exec -it production-db-standby-pgha1-0 -n databases -- patronictl list
Referencia rápida de comandos operativos de

# Cluster status
kubectl get postgrescluster -n databases
kubectl describe postgrescluster production-db -n databases

# Patroni status
kubectl exec -it production-db-pgha1-0 -n databases -- patronictl list
kubectl exec -it production-db-pgha1-0 -n databases -- patronictl history

# Connect to PostgreSQL
kubectl exec -it production-db-pgha1-0 -n databases -- psql -U postgres

# Backup info
kubectl exec -it production-db-pgha1-0 -n databases -- pgbackrest info --stanza=db

# Manual backup
kubectl annotate postgrescluster production-db -n databases \
  postgres-operator.crunchydata.com/pgbackrest-backup="$(date +%s)" --overwrite

# Restart PostgreSQL (rolling)
kubectl annotate postgrescluster production-db -n databases \
  postgres-operator.crunchydata.com/restart="$(date +%s)" --overwrite

# Logs
kubectl logs production-db-pgha1-0 -n databases -c database
kubectl logs production-db-pgha1-0 -n databases -c pgbackrest
kubectl logs production-db-pgha1-0 -n databases -c exporter

# PgBouncer status
kubectl exec -it $(kubectl get pod -l postgres-operator.crunchydata.com/role=pgbouncer -n databases -o name | head -1) -n databases -- psql -U pgbouncer pgbouncer -c "SHOW POOLS;"

# Scale replicas
kubectl patch postgrescluster production-db -n databases --type merge \
  -p '{"spec":{"instances":[{"name":"pgha1","replicas":5}]}}'

Conclusión

Crunchy Data PGO transforma PostgreSQL en Kubernetes de una carga operativa a un sistema declarativo manejable. ElPostgresClusterCRD captura toda la implementación (instancias, replicación, respaldo, agrupación, monitoreo, TLS) en un único recurso controlado por versión. Patroni proporciona conmutación por error automática probada en batalla. pgBackRest ofrece respaldo de nivel empresarial con recuperación en un momento dado a cualquier almacén de objetos en la nube. PgBouncer maneja la agrupación de conexiones que exige el modelo de proceso por conexión de PostgreSQL a escala. Y pgMonitor introduce las métricas que necesita en Prometheus y Grafana para obtener visibilidad operativa.

Los patrones de implementación en AWS EKS, Azure AKS, GCP GKE y k3s bare metal comparten la misma especificación centralPostgresCluster: lo que cambia es la clase de almacenamiento, la configuración del repositorio de respaldo y la capa de red. Esta coherencia es el valor real de un enfoque basado en operadores: su equipo aprende una herramienta, un modelo operativo y un conjunto de runbooks que funcionan en todas partes.

Comience con un clúster de tres instancias, PgBouncer en modo de agrupación de transacciones, un programa de respaldo diferencial completo semanal y diario y las alertas principales Prometheus. Valide su procedimiento de restauración de copias de seguridad el primer día, no cuando lo necesite por primera vez. Amplíe a clústeres en espera de múltiples regiones, replicación sincrónica y ajuste avanzado a medida que crecen sus requisitos de disponibilidad y madurez operativa. El operador maneja la mecánica; su responsabilidad es comprender la arquitectura lo suficientemente bien como para realizar las compensaciones adecuadas para su carga de trabajo.