Crunchy Data PostgreSQL Operator (PGO) — Production Operations Guide
·45 min read·PostgreSQL
Crunchy Data PostgreSQL Operator (PGO) — Production Operations Guide
Scope: This guide assumes PGO is already installed and the operator pod is running in the postgres-operator namespace. It focuses on deploying, operating, and troubleshooting PostgresCluster resources in production. Official reference: https://access.crunchydata.com/documentation/postgres-operator/latest
Table of Contents
Introduction
Deploying a PostgreSQL Cluster
Understanding Every Important CRD
PostgreSQL Configuration
Patroni Configuration
Resource Management
Storage
Backup Management
Restore Operations
Disaster Recovery
High Availability Operations
Scaling
Day-2 Operations
Monitoring
Troubleshooting Guide
Production Best Practices
Appendix
1. Introduction
1.1 Prerequisites (brief)
A Kubernetes cluster (v1.24+) with a working CSI storage provisioner (e.g. Rook-Ceph, EBS, GCE PD).
PGO installed and its pgo deployment Running in the postgres-operator namespace, with CRDs registered (postgresclusters.postgres-operator.crunchydata.com, pgupgrades..., pgadmins...).
kubectl and (optionally) the kubectl-pgo plugin configured against the target cluster.
A dedicated namespace per environment/application (e.g. db-ns) — PGO does not require clusters to live in its own namespace.
1.2 PGO Architecture Overview
PGO is a Kubernetes Operator: a controller that watches PostgresCluster custom resources and reconciles the actual cluster state (Pods, Services, PVCs, Secrets, Jobs) to match the declared spec. It runs as a single Deployment (pgo) with cluster-wide or namespace-scoped RBAC, using the standard controller-runtime reconcile loop (watch → diff → apply).
flowchart LR
A[PostgresCluster CR] -->|watched by| B[PGO Controller]
B --> C[StatefulSet-like Instance Pods]
B --> D[Patroni DCS ConfigMaps/Endpoints]
B --> E[Services]
B --> F[Secrets]
B --> G[pgBackRest Repo Host/Jobs]
B --> H[Monitoring Exporter Sidecar]
C --> I[(PVCs)]
G --> J[(Backup Repo: PVC/S3/GCS/Azure)]
Patroni (running inside each instance pod) independently manages leader election, replication topology, and failover using the Kubernetes Endpoints/ConfigMap (or Kubernetes-native DCS) as its distributed configuration store.
PGO continuously reconciles drift — manual edits to generated objects (e.g. a raw StatefulSet) will be reverted on the next reconcile loop; always change the PostgresCluster spec instead.
1.5 High Availability Architecture
PGO’s HA model layers Patroni on top of Kubernetes:
Each instance in spec.instances[].replicas becomes a Postgres pod running Patroni as PID 1’s supervisor for postgres.
Patroni members register themselves in a distributed configuration store (DCS) — by default Kubernetes Endpoints/Leases, no external etcd required.
On primary failure, Patroni performs leader election among healthy, sufficiently caught-up replicas and promotes one automatically.
Readiness/liveness probes gate traffic — the -primary and -replicas Services always route to the current roles, not to fixed pod names.
1.6 Patroni Overview
Patroni is the HA orchestrator embedded in every Postgres container PGO deploys. It watches the DCS for leader keys, performs periodic health checks (ttl, loop_wait), and issues pg_ctl promote/demote actions as needed. All Patroni behavior is configured under spec.patroni.dynamicConfiguration in the PostgresCluster spec (see Section 5).
1.7 pgBackRest Overview
pgBackRest is PGO’s built-in backup/restore/WAL-archiving tool. Every cluster gets at least one pgBackRest repository (spec.backups.pgbackrest.repos[]), which can be a PVC, S3, GCS, or Azure Blob target. pgBackRest handles full/differential/incremental backups, retention, and point-in-time recovery (PITR) via continuous WAL archiving.
1.8 Service Topology
Service
Selector/Purpose
<cluster>-ha
Points to the current Patroni leader (primary) — read/write
<cluster>-replicas
Points to all ready replicas — read-only load balancing
<cluster>-pgbouncer
Connection-pooled endpoint if pgBouncer is enabled
<cluster>-exporter (via pod)
Prometheus metrics endpoint (port 9187)
<cluster>-pods (headless)
Direct pod DNS for internal Patroni/replication traffic
1.9 Secrets Generated
Secret
Contents
<cluster>-pguser-<username>
Username, password, connection URI/host/port/dbname for each declared user
<cluster>-cluster-cert
Server TLS certificate/key + CA (or the customTLSSecret you provide)
<cluster>-replication-cert
Replication user TLS material
<cluster>-pgbackrest
pgBackRest configuration and repo credentials
<cluster>-monitoring
Exporter credentials
1.10 PVC Layout
PVC
Attached To
Purpose
<cluster>-instance-*-data (or named per dataVolumeClaimSpec)
Instance pod
PGDATA
<cluster>-instance-*-wal
Instance pod (if walVolumeClaimSpec set)
Dedicated WAL volume
<cluster>-repo1
pgBackRest repo host pod
Local backup repository (if using volume repo type)
1.11 Important Kubernetes Resources Created
StatefulSets/Deployments (per-instance pods), Services, Secrets, ConfigMaps, PersistentVolumeClaims, Jobs/CronJobs (backups, repo-host init, pgBackRest stanza-create), Endpoints/Leases (Patroni DCS), and optionally PodDisruptionBudgets if you add them manually (PGO does not create PDBs by default — see Section 16).
2. Deploying a PostgreSQL Cluster
Below is a fully-featured example PostgresCluster manifest. Replace placeholder names, credentials, and storage classes for your environment. Generic names used: cluster appdb, database appdb, user appuser, namespace db-ns.
apiVersion:v1kind:Secretmetadata:name:appdb-pguser-appusernamespace:db-nslabels:postgres-operator.crunchydata.com/cluster:appdbpostgres-operator.crunchydata.com/pguser:appusertype:OpaquestringData:user:appuserpassword:"CHANGE_ME_STRONG_PASSWORD"dbname:appdb---apiVersion:v1kind:Secretmetadata:name:appdb-s3-credsnamespace:db-nstype:OpaquestringData:repo1-s3-key:"CHANGE_ME_S3_ACCESS_KEY"repo1-s3-key-secret:"CHANGE_ME_S3_SECRET_KEY"---apiVersion:postgres-operator.crunchydata.com/v1beta1kind:PostgresClustermetadata:name:appdbnamespace:db-nslabels:pg-cluster:appdbenvironment:productionannotations:team:platform-engineeringspec:postgresVersion:16image:registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.4-2# ---- Instances (primary instance set + optional additional sets) ----instances:-name:instance1replicas:3priorityClassName:"postgres-critical"labels:workload:primary-setmetadata:annotations:custom.io/backup-tier:"gold"resources:requests:cpu:"2"memory:"4Gi"limits:cpu:"4"memory:"8Gi"tolerations:-key:"dedicated"operator:"Equal"value:"database"effect:"NoSchedule"nodeAffinity:{}affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:-topologyKey:kubernetes.io/hostnamelabelSelector:matchLabels:postgres-operator.crunchydata.com/cluster:appdbpostgres-operator.crunchydata.com/instance-set:instance1nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:-matchExpressions:-key:dboperator:Invalues:["enabled"]topologySpreadConstraints:-maxSkew:1topologyKey:topology.kubernetes.io/zonewhenUnsatisfiable:ScheduleAnywaylabelSelector:matchLabels:postgres-operator.crunchydata.com/cluster:appdbdataVolumeClaimSpec:accessModes:["ReadWriteOnce"]storageClassName:rook-ceph-blockresources:requests:storage:50GiwalVolumeClaimSpec:accessModes:["ReadWriteOnce"]storageClassName:rook-ceph-block-fastresources:requests:storage:10Gi# Optional second instance set (e.g. dedicated to reporting replicas)-name:instance2replicas:1resources:requests:cpu:"1"memory:"2Gi"limits:cpu:"2"memory:"4Gi"dataVolumeClaimSpec:accessModes:["ReadWriteOnce"]storageClassName:rook-ceph-blockresources:requests:storage:50Gi# ---- Users and Databases ----users:-name:appuserdatabases:["appdb"]options:"CREATEROLE"-name:readonlyuserdatabases:["appdb"]options:"NOSUPERUSERNOCREATEDBNOCREATEROLE"# ---- TLS (custom certs; omit to let PGO generate its own) ----customTLSSecret:name:appdb-cluster.tlscustomReplicationTLSSecret:name:appdb-replication.tls# ---- Service Configuration ----service:type:ClusterIPmetadata:annotations:service.beta.kubernetes.io/custom-annotation:"true"# ---- pgBouncer (connection pooling) ----proxy:pgBouncer:replicas:2image:registry.developers.crunchydata.com/crunchydata/crunchy-pgbouncer:ubi8-1.22-2resources:requests:cpu:"0.5"memory:"256Mi"limits:cpu:"1"memory:"512Mi"config:global:pool_mode:transactionmax_client_conn:"1000"default_pool_size:"50"# ---- Monitoring (pgMonitor exporter) ----monitoring:pgmonitor:exporter:image:registry.developers.crunchydata.com/crunchydata/crunchy-postgres-exporter:ubi8-5.1.1-0resources:requests:cpu:"0.1"memory:"128Mi"limits:cpu:"0.2"memory:"256Mi"# ---- Patroni Configuration ----patroni:leaderLeaseDurationSeconds:30syncPeriodSeconds:10port:8008dynamicConfiguration:synchronous_mode:falsepostgresql:parameters:max_connections:"300"shared_buffers:"2GB"effective_cache_size:"6GB"work_mem:"16MB"maintenance_work_mem:"512MB"wal_level:"replica"wal_buffers:"16MB"checkpoint_timeout:"15min"checkpoint_completion_target:"0.9"max_wal_size:"4GB"min_wal_size:"1GB"random_page_cost:"1.1"effective_io_concurrency:"200"default_statistics_target:"100"autovacuum:"on"autovacuum_max_workers:"4"log_min_duration_statement:"500"log_checkpoints:"on"log_connections:"on"log_disconnections:"on"# ---- Backups (pgBackRest) ----backups:pgbackrest:image:registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.53-2configuration:-secret:name:appdb-s3-credsglobal:repo1-retention-full:"7"repo1-retention-full-type:countrepo2-retention-full:"4"repos:-name:repo1schedules:full:"01**0"differential:"01**1-6"volume:volumeClaimSpec:accessModes:["ReadWriteOnce"]storageClassName:rook-ceph-blockresources:requests:storage:100Gi-name:repo2schedules:full:"02**0"s3:bucket:appdb-backupsendpoint:s3.ap-southeast-1.amazonaws.comregion:ap-southeast-1# ---- Restore configuration (for cloning/PITR — omit on first deploy) ----# dataSource:# postgresCluster:# clusterName: appdb-source# repoName: repo1# options:# - --type=time# - --target=2026-07-20 12:00:00+06# ---- Init SQL (runs once against the initial database) ----databaseInitSQL:name:appdb-init-sqlkey:init.sql
Companion ConfigMap for databaseInitSQL:
1
2
3
4
5
6
7
8
9
apiVersion:v1kind:ConfigMapmetadata:name:appdb-init-sqlnamespace:db-nsdata:init.sql:|CREATE EXTENSION IF NOT EXISTS pg_stat_statements;CREATE SCHEMA IF NOT EXISTS reporting;
Field-by-field notes
Field
Purpose
spec.postgresVersion / spec.image
Pin exact PostgreSQL major version and container image digest for reproducibility
spec.instances[].replicas
Number of Patroni-managed pods in that instance set (1 primary + N-1 replicas, dynamically elected)
Deploys a pooling layer in front of Postgres. Use when the application opens many short-lived connections (typical for web backends) to avoid exhausting max_connections.
3.3 pgBackRest (spec.backups.pgbackrest)
Controls backup repositories, retention, schedules, and restore options. Supports multiple repos[] for redundancy (e.g. local + S3).
3.4 Monitoring (spec.monitoring.pgmonitor)
Deploys the postgres_exporter sidecar exposing Prometheus-format metrics on port 9187 per instance pod.
3.5 Secrets
PGO auto-generates and continuously reconciles password/TLS Secrets unless you provide customTLSSecret or pre-seed a pguser Secret (as shown in Section 2) with the postgres-operator.crunchydata.com/pguser label so PGO adopts it instead of generating a random password.
3.6 Services
Auto-created per cluster; do not manually edit — override via spec.service.metadata for annotations/type instead.
3.7 Jobs
PGO creates Kubernetes Jobs for: pgbackrest stanza-create (initial repo setup), scheduled/manual backups, and restore operations. These appear and complete, then are cleaned up according to Kubernetes’ default job history.
3.8 StatefulSets
Each instance pod runs under a StatefulSet-like construct that guarantees stable network identity (<cluster>-<instance>-<suffix>-0) — required for Patroni’s DCS bookkeeping and PVC binding.
3.9 Patroni Configuration Object
Lives entirely under spec.patroni. See Section 5 for detail.
3.10 PostgreSQL Configuration Object
Lives under spec.patroni.dynamicConfiguration.postgresql.parameters — PGO delegates all postgresql.conf management to Patroni’s dynamic configuration rather than a static file.
4. PostgreSQL Configuration
All tunables are set via spec.patroni.dynamicConfiguration.postgresql.parameters as strings. Changes are applied via Patroni’s REST API and, for parameters requiring a restart (e.g. shared_buffers), Patroni schedules a rolling restart automatically.
Parameter
Purpose
shared_buffers
Postgres’s dedicated shared memory cache; typically 25% of instance memory
work_mem
Per-operation sort/hash memory; too high with many connections can OOM the pod
maintenance_work_mem
Memory for VACUUM, CREATE INDEX, etc.
effective_cache_size
Planner hint for total OS+Postgres cache available; ~50-75% of memory
max_connections
Hard cap on backend connections; pair with pgBouncer to keep this modest
wal_level
replica (default, required for streaming replication) or logical for logical replication
wal_buffers
WAL write buffer, usually auto (-1) or 16MB
checkpoint_timeout / max_wal_size / min_wal_size
Control checkpoint frequency and WAL retention window
Enables synchronous replication (zero data loss on failover, higher write latency)
synchronous_mode_strict
Use with caution
Blocks all writes if no sync replica is available — only for strict RPO=0 requirements
leaderLeaseDurationSeconds (ttl)
Yes, with care
Lower = faster failure detection but more risk of false-positive failovers on transient network blips
maximum_lag_on_failover
Yes
Prevents promoting a replica that’s too far behind (in bytes)
retry_timeout
Yes
How long Patroni retries a failed DCS/API operation
Replication slots (use_slots)
Yes
Keeps WAL available for replicas; monitor disk usage to avoid WAL bloat if a replica goes offline for long
Bootstrap initdb options
Only at cluster creation
Changing after cluster creation has no effect — must be set at first apply
Raw DCS keys / postgresql.conf
Avoid manual edits
Always go through spec.patroni.dynamicConfiguration; PGO will revert manual ConfigMap edits
Failover vs Switchover: Failover is automatic (triggered by Patroni detecting primary failure). Switchover is a planned, manual role swap (see Section 11) and should always be used for maintenance instead of forcing a failover.
CPU requests/limits: Request should reflect steady-state usage; limit provides burst headroom. Avoid setting CPU limits equal to requests for latency-sensitive OLTP (throttling causes replication stalls).
Memory requests/limits: Should be equal or very close — Postgres does not tolerate OOM-kills gracefully (can corrupt shared memory state and trigger a crash-recovery cycle).
HugePages: Supported via standard Kubernetes resources.limits["hugepages-2Mi"] plus setting huge_pages: try or on in postgresql.parameters; reduces TLB pressure for large shared_buffers.
Ephemeral storage: Set resources.requests/limits["ephemeral-storage"] if using emptyDir-backed temp space; monitor pg_stat_activity temp file usage.
Storage resizing / volume expansion: Increase dataVolumeClaimSpec.resources.requests.storage and reapply — requires a storage class with allowVolumeExpansion: true. Expansion is online for most CSI drivers (including Rook-Ceph RBD) but always verify in a non-prod cluster first.
Instance/replica scaling: See Section 12.
Trade-offs: Larger shared_buffers/CPU limits improve throughput but increase blast radius of node pressure; conservative requests improve schedulability but risk noisy-neighbor throttling.
7. Storage
Persistent Volumes: One PV per PVC, dynamically provisioned by your CSI driver based on storageClassName.
Storage Classes: Must support ReadWriteOnce; allowVolumeExpansion: true recommended. Common: rook-ceph-block, gp3 (EBS), pd-ssd (GCE), managed-premium (Azure).
WAL storage: Use walVolumeClaimSpec on a fast, low-latency class separate from PGDATA to isolate write-ahead log I/O.
Backup storage options:
Backend
Repo Field
Use Case
PVC (volume)
repos[].volume
Fast local restores, no cloud dependency
AWS S3
repos[].s3
Off-site, durable, cheap long-term retention
MinIO
repos[].s3 + repo1-s3-uri-style: path in global
Self-hosted S3-compatible storage
GCS
repos[].gcs
GCP-native clusters
Azure Blob
repos[].azure
Azure-native clusters
Multiple repositories: Configure repo1, repo2, etc. under spec.backups.pgbackrest.repos[] — pgBackRest can write to all simultaneously and restore from any.
Repository failover: If repo1 (e.g. local PVC) is unavailable, target repo2 explicitly during restore with --repo=2 in the restore options.
9.4 Restore from S3/MinIO or another cluster’s remote repository
Same dataSource.postgresCluster block; point repoName at the S3/MinIO-backed repo (e.g. repo2), and ensure the new cluster’s namespace has access to the same S3 credentials Secret referenced in spec.backups.pgbackrest.configuration.
Step-by-step:
Confirm the source repo has a valid, complete backup (pgbackrest info).
Create the target PostgresCluster manifest with matching postgresVersion and a dataSource.postgresCluster block.
Apply and monitor: kubectl -n db-ns get pods -w.
Verify recovery completed: psql -c "select pg_is_in_recovery();" should return f once promoted.
10. Disaster Recovery
10.1 DR Architecture
flowchart TB
P[Primary Cluster - Site A] -->|pgBackRest WAL archive + full/diff backups| R1[repo1: Local PVC]
P -->|off-site copy| R2[repo2: S3 - Site B Region]
R2 -->|restore/PITR| DR[DR Cluster - Site B]
Cross-cluster recovery: A DR cluster in a different namespace/region restores from the same repo2 (S3) using dataSource.postgresCluster pointing at the primary’s cluster name and repo.
Off-site backups: Always configure at least one cloud (s3/gcs/azure) repo in addition to local PVC, so a full-site outage doesn’t destroy all backups.
Cluster cloning: Use the same restore-to-new-cluster pattern (Section 9.1) for creating staging/QA copies from production backups.
Recommended DR strategy: Combine (a) a warm standby cluster using spec.standby.enabled: true streaming from the primary over a NodePort/LoadBalancer, and (b) periodic S3 backups for cold-start recovery if the standby itself is unavailable.
RPO/RTO considerations:
Strategy
RPO
RTO
Streaming standby (async)
Seconds to low minutes
Minutes (manual switchover)
Streaming standby (sync)
~0
Minutes
PITR from S3 backups only
Up to last WAL archive push interval
Tens of minutes to hours (restore time scales with data size)
10.2 Testing DR Procedures
Regularly (quarterly minimum) perform a full restore-to-new-cluster drill in an isolated namespace using production backups, and time the process to validate your RTO assumptions.
11. High Availability Operations
11.1 Automatic Failover
Triggered by Patroni when the leader misses its lease renewal. No manual action needed; verify with:
1
kubectl -n db-ns exec-it appdb-instance1-0 -- patronictl list
Storage scaling: Increase dataVolumeClaimSpec.resources.requests.storage; requires allowVolumeExpansion: true on the StorageClass.
Rolling updates / zero-downtime upgrades: PGO rolls instance pods one at a time by default, always keeping quorum; monitor with kubectl get pods -w during any spec change that forces a restart (image, resources, config requiring restart).
13. Day-2 Operations
Task
Command / Method
Add a database
Add to existing user’s databases: [] list in spec and reapply
Add a user
Add entry to spec.users[] and reapply
Rotate password
Delete the pguser secret matching the user; PGO regenerates a new password on next reconcile: kubectl delete secret appdb-pguser-appuser -n db-ns
Rotate certificates
Delete customTLSSecret/customReplicationTLSSecret (if operator-managed) to force regeneration, or supply new cert Secrets
Symptoms: Multi-Attach error, rbd image is still being used.
Root causes: Stale VolumeAttachment after ungraceful node loss; stale Ceph RBD watcher.
Diagnostics: kubectl get volumeattachments -A | grep <pvc-uid>.
Resolution: Cordon affected node → scale StatefulSet to 0 → delete stale VolumeAttachment → scale back up → uncordon. If still stuck, blacklist the stale Ceph RBD watcher via rbd status/ceph osd blacklist add.
Prevention: Always drain nodes gracefully before maintenance; avoid force-deleting pods.
15.6 Replication lag
Symptoms: patronictl list shows large Lag in MB on a replica.
Root causes: Network latency, high primary write load, disk I/O contention, long-running queries on the replica.
Diagnostics: patronictl list; pg_stat_replication on the primary.
Resolution: Reinitialize the lagging replica: patronictl reinit <cluster> <member> --force; temporarily scale down replicas to let one catch up, then scale back up.
Prevention: Size replicas identically to the primary; monitor lag continuously and alert above a threshold.
Root causes: Stale cached password after rotation; expired custom certs; CA mismatch between primary and standby.
Resolution: Recreate the pguser Secret to force regeneration; ensure customTLSSecret/customReplicationTLSSecret share a common CA across all clusters expected to replicate.
Symptoms: High CPU/memory usage; WAL directory growing unbounded; disk full alerts.
Root causes: Long-running/unindexed queries; replication slot retaining WAL for an offline replica; insufficient max_wal_size; runaway autovacuum contention.
Diagnostics: pg_stat_activity, pg_replication_slots, du -sh on WAL directory, kubectl top pod.
Resolution: Kill offending queries (pg_terminate_backend); drop stale replication slots; increase disk/WAL volume size; tune checkpoint_timeout/max_wal_size.
15.12 Stuck reconciliations
Symptoms: Spec changes don’t take effect; PGO seems idle.
Root causes: Conflicting manual edits to generated objects; controller error looping (check pgo pod logs).
Resolution: kubectl logs deploy/pgo -n postgres-operator; revert manual edits to owned objects; as a last resort, delete and let PGO recreate the specific generated resource (never delete the PostgresCluster itself unless intentionally decommissioning).
16. Production Best Practices
High availability: Minimum 3 instances per critical cluster; enforce pod anti-affinity and topology spread across zones; add a PodDisruptionBudget (minAvailable: 2) since PGO does not create one automatically.
Security: Always enable TLS (custom or operator-managed); restrict NetworkPolicy to only required namespaces; avoid superuser accounts for application users; rotate credentials on a schedule.
Backups: At least one off-site (S3/GCS/Azure) repo in addition to local PVC; alert on backup staleness; periodically test restores.
Disaster recovery: Maintain a documented, tested DR runbook; know your RPO/RTO targets and validate them quarterly.
Monitoring: Wire pgMonitor + Prometheus + Grafana into existing alerting; alert on replication lag, backup age, and pod restarts.
Resource sizing: Set memory requests == limits; leave CPU limits with headroom above requests for burst.
Scheduling: Use priorityClassName for critical clusters; taint/toleration dedicated DB nodes to avoid noisy neighbors.
Storage: Prefer separate WAL volumes on fast storage; enable allowVolumeExpansion.
Networking: Use ClusterIP internally; expose via Ingress/LoadBalancer only when required, never expose Patroni’s REST API (8008) externally.
Upgrades: Test minor image upgrades and major version upgrades (PGUpgrade) in staging first; always take a fresh backup immediately before any upgrade.
GitOps workflows: Store PostgresCluster manifests in version control; apply via ArgoCD/Flux; never hand-edit live cluster objects.
Secrets management: Integrate with an external secrets manager (Vault, Sealed Secrets, External Secrets Operator) rather than committing plaintext credentials.
17. Appendix
Common kubectl commands
1
2
3
4
5
6
kubectl -n db-ns get postgrescluster
kubectl -n db-ns describe postgrescluster appdb
kubectl -n db-ns get pods -l postgres-operator.crunchydata.com/cluster=appdb
kubectl -n db-ns get pvc
kubectl -n db-ns get secrets
kubectl -n db-ns logs appdb-instance1-0 -c database
Patroni commands
1
2
3
4
5
patronictl list
patronictl switchover --master <leader> --candidate <replica> --force
patronictl failover --candidate <replica>
patronictl reinit <cluster> <member> --force
patronictl history
A comprehensive step-by-step guide to deploying a highly available PostgreSQL 17 cluster with Pgpool-II 4.5, including streaming replication, watchdog, virtual IP failover, and ...