Skip to main content
CloudNativePG (CNPG) is the Kubernetes operator for PostgreSQL, covering the full lifecycle from bootstrapping to monitoring, with high availability, automated failover, and backup management.

What Radar Shows

Cluster Detail View:
  • Phase, instances ready/desired, primary instance, image version
  • Instance node distribution (which K8s nodes run each PostgreSQL instance)
  • Storage configuration: data size, storage class, WAL storage
  • Backup configuration: destination, retention policy, last successful backup, recovery point
  • Monitoring: PodMonitor integration, custom query ConfigMaps
  • Replication settings (for replica clusters), with per-instance role and timeline ID
  • PostgreSQL parameters
  • Health detection (AlertBanner for degraded clusters, failover/switchover in progress)
  • WAL archiving failure - a first-class AlertBanner driven by the ContinuousArchiving condition. This is the classic silent CNPG incident: the cluster keeps serving traffic normally while the recovery point stops advancing. The condition proves the last archive attempt failed, so Radar reports “archiving failing since <time> - the recovery point may not be advancing” and deliberately does not claim an exact RPO
  • Last-backup failure - driven by the LastBackupSucceeded condition. CNPG also sets this condition False with reason BackupStarted while a backup is merely in flight; Radar ignores that state rather than alerting on every backup run
Backup Detail View:
  • Phase, backup method, duration, start/stop timestamps
  • Cluster reference with clickable link
  • Destination path and server name
  • Backup target
  • Failure detection (AlertBanner with error message)
ScheduledBackup Detail View:
  • Cron schedule, last/next schedule timestamps
  • Suspension detection (AlertBanner when paused)
  • Backup configuration: cluster reference, method, owner reference settings
Pooler Detail View:
  • Type (read-write/read-only) with colored badge, pool mode
  • Instances scheduled/desired (not readiness - see below)
  • Cluster reference with clickable link
  • PgBouncer parameters
  • Degraded state detection (AlertBanner when not all instances are scheduled)
Note Pooler.status.instances counts pods trying to be scheduled, not ready pods - a Pooler whose PgBouncer pods are all Pending still reports the full count. Radar therefore labels the healthy state Scheduled rather than Ready; actual readiness lives on the Deployment CNPG generates for the Pooler (same name, same namespace). Resource Browser: Smart columns show status, instance counts (with degraded highlighting), primary instance, image tag, storage size, cluster reference, and schedule expressions.

Phase classification

Cluster phases are full English sentences (Cluster is unrecoverable and needs manual intervention), not enum tokens, and are matched on equality. They are bucketed as healthy / transient / failing / terminal / attention; terminal phases outrank instance counts, so an unrecoverable cluster whose pods happen to still be Ready is still rendered red. An unrecognized phase from a newer CNPG minor surfaces verbatim as unknown rather than being guessed at. Backup phases are lowercase tokens. walArchivingFailing is treated as a cluster-level signal, not an ordinary backup failure - archiving is broken upstream of that Backup, so the whole recovery window is affected. The taxonomy is defined twice - TypeScript for the badge, Go for the issue detector - and pinned by TestCNPGPhaseTaxonomyMatchesFrontend, which fails if the two drift.

Backup: in-tree vs the barman-cloud plugin

In-tree spec.backup.barmanObjectStore is deprecated as of CNPG 1.26. Clusters migrated to the barman-cloud plugin keep their config in an ObjectStore CR (barmancloud.cnpg.io/v1), and CNPG stops populating status.lastSuccessfulBackup / firstRecoverabilityPoint by design. Radar detects the plugin from spec.plugins[], names the ObjectStore and resolved server key, and says so explicitly - rather than rendering an empty backup section that reads identically to “no backups configured”. The ObjectStore itself is rendered: destination and credential provider (never the credentials), retention, and status.serverRecoveryWindow per PostgreSQL server - firstRecoverabilityPoint, lastSuccessfulBackupTime, lastFailedBackupTime. Note the field names differ from the Cluster’s (lastSuccessfulBackupTime, not lastSuccessfulBackup); reading the Cluster’s spelling off an ObjectStore silently yields nothing. Two states carry the weight. A failure newer than the last success means the window has stopped advancing while its oldest point still ages out under retention - shrinking from both ends, so it is called out rather than left to be inferred from two timestamps. An ObjectStore with an empty serverRecoveryWindow is reported as holding nothing restorable rather than as healthy: on the plugin path the Cluster publishes no recovery point of its own, so a green badge here would be the only claim on screen and it would be wrong. Backup and ScheduledBackup with spec.method: plugin name the plugin and link to the ObjectStore they write into, and suppress the in-tree destinationPath / serverName rows, which are never populated on that path.

Declarative objects: Database, Publication, Subscription

CNPG can manage PostgreSQL-side objects from Kubernetes. All three report through status.applied, and it has three values, not two: true, false with the operator’s message, and absent - meaning not reconciled yet. Absent is rendered as pending rather than failed; treating it as failure condemns every object in its first seconds. The names in these specs are PostgreSQL names, not Kubernetes names: a Publication demo-app-pub declares dbname: demo_app, and the Database CR that owns demo_app is called demo-app. Radar resolves them back to the CRs so the reference is a link rather than a dead string, and falls back to plain text when nothing matches. The Database detail runs the lookup in the other direction, listing what publishes from and subscribes into it - a link the API only models one way. databaseReclaimPolicy (and its publication/subscription twins) decides whether deleting the manifest drops the real object. delete is called out as destructive; CNPG defaults to retain, and defaulting the other way in the UI would warn about data loss that is not going to happen. A declared object the operator could not apply raises an Issue (CNPGDeclarativeNotApplied, warning) carrying the operator’s own message. This is the one CNPG failure with no other signal: the CR exists, the cluster is healthy, every count is green, and the database simply is not there. Only applied: false raises it - an absent applied means not yet reconciled, and reporting that would flag every declarative object for the first seconds of its life.

Image catalogs

ImageCatalog and ClusterImageCatalog pin one PostgreSQL image per major version. A Cluster that references one carries no spec.imageName at all; the resolved image lives in status.image, so anything reading spec alone shows a dash where an image is running. A cluster asking for a major the catalog does not list reports “incomplete or invalid image catalog” and stops - and that is invisible from the cluster side, where the reference looks fine. The catalog page lists the clusters pinned to it and separates out those asking for a version it does not carry.

Cluster Audit checks

Deliberately narrow: the absence of a ScheduledBackup does not prove a cluster is unprotected (on-demand Backups, volume snapshots and external schedulers all exist), so the finding asserts only that no schedule is declared, at posture severity. All three spec.method values - barmanObjectStore, volumeSnapshot and plugin - count as a declared schedule. Suspended schedules count as present, since suspension is deliberate operator intent. The check does not run at all unless a synced cluster-wide ScheduledBackup informer backs the inventory, because absence would otherwise be unprovable.

Supported CRDs

Limitations:
  • The image-catalog and backup views describe what the cluster reports. A ScheduledBackup’s cron is CloudNativePG’s six-field form (seconds first) and is shown verbatim rather than translated, because reading it as a five-field expression would state the wrong time.