In traditional Kubernetes operator setups, every Cluster custom resource (CR) explicitly hardcodes its own container image tag or SHA256 digest. As a fleet grows to dozens or hundreds of PostgreSQL instances across multiple environments, this design introduces severe operational friction for Database Administrators (DBAs):
Configuration Drift & Maintenance Toil: When a critical security patch or minor PostgreSQL version releases (e.g., updating PostgreSQL 16.14 to 16.15), DBAs must update every single Cluster manifest individually across repositories and GitOps pipelines.
Supply Chain Security Risks: Allowing individual development teams to specify arbitrary container tags or mutable tags (like :16 or :latest) bypasses security controls, introducing unvetted container images into production.
Extension Distribution Overhead: Bundling extensions (like pgvector or PostGIS) across different PostgreSQL major versions usually requires custom container images or complex image builds per cluster.
How CNPG Image Catalog solves this
ImageCatalog (namespaced) and ClusterImageCatalog (cluster-scoped)decouple the database lifecycle from cluster definition. DBAs publish a single, centralized catalog containing approved, SHA256-pinned container images and extension definitions mapped to PostgreSQL major versions. Applications simply request major: 16 or major: 17. When the DBA updates the central catalog image digest, CloudNativePG automatically triggers controlled, rolling updates across all referencing clusters.
Important: Minor Upgrades vs. Major Upgrades
It is vital to distinguish how CloudNativePG handles minor vs. major version changes:
- Minor Upgrades (e.g., 16.4 -> 16.5):Updating the container image SHA digest under major: 16 in your catalog triggers an online, zero-downtime rolling update. The underlying data directory remains untouched because minor releases share identical disk formats.
- Major Upgrades (e.g., 16 -> 17):Changing the cluster’s requested version from major: 16 to major: 17 in the Cluster manifest triggers an offline in-place pg_upgrade process.
CNPG will temporarily shut down the cluster to transform the data files on disk to the new major version format before re-cloning replicas. Always schedule a maintenance window for major version jumps!
Step-by-Step Implementation Guide
Here is a practical walkthrough for configuring, referencing, and updating PostgreSQL container images across your fleet using CloudNativePG Image Catalogs.
Step 1: Define a Centralized ClusterImageCatalog
As a DBA, create a cluster-scoped ClusterImageCatalog that maps PostgreSQL major versions to enterprise-approved, SHA256-pinned container images across versions 16, 17, and 18.
# catalog-enterprise.yaml apiVersion: postgresql.cnpg.io/v1 kind: ClusterImageCatalog metadata: name: postgresql-enterprise spec: images: - major: 16 image: ghcr.io/cloudnative-pg/postgresql:16.15-202609210816-minimal-trixie@sha256:0b3082c00f138c3d859bf495bccf77785a61ca03f876a72ca6826a6d9df5f528 - major: 17 image: ghcr.io/cloudnative-pg/postgresql:17.11-202609210816-minimal-trixie@sha256:cfc42005357630d2c0bfca095c93a6abe44884486acb0de2e5e511a087b7eb15 - major: 18 image: ghcr.io/cloudnative-pg/postgresql:18.6-202609210816-minimal-trixie@sha256:0fae0cb527912426a889ec0b21b9733e5b76fdc6ad8909914a6e8a6c8ba4f64bApply the catalog to your Kubernetes cluster:
kubectl apply -f catalog-enterprise.yamlStep 2: Reference the Catalog in Application Clusters
Developers define their database clusters by referencing the central catalog and choosing only the major PostgreSQL version. Notice that spec.imageName is completely omitted.
# app-db-cluster.yaml apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: payment-service-db namespace: production spec: instances: 3 imageCatalogRef: apiGroup: postgresql.cnpg.io kind: ClusterImageCatalog name: postgresql-enterprise major: 16 storage: size: 5GiDeploy the database:
kubectl apply -f app-db-cluster.yamlStep 3: Trigger a Zero-Downtime Patch Fleet Upgrade
When PostgreSQL releases a patch (e.g., updating PostgreSQL 16.15 to 16.16), you do not edit any application Cluster manifests. Instead, update the single catalog file:
# Update the SHA256 digest or tag for major: 16 in catalog-enterprise.yaml spec: images: - major: 16 image: ghcr.io/cloudnative-pg/postgresql:16.16@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855Apply the updated catalog:
kubectl apply -f catalog-enterprise.yamlWhat Happens Next?
CloudNativePG detects the image SHA change in postgresql-enterprise.
The operator initiates a controlled rolling update across all Cluster resources referencing postgresql-enterprise at major: 16.
Replicas are updated first, one by one. Once healthy, a graceful switchover happens for the primary instance, ensuring minimal service disruption.
Lessons Learned & Production Pro-Tips
- Always Pin SHA256 Digests in Catalogs
Never use mutable container tags (such as :16 or :latest) inside your ClusterImageCatalog. Pinning explicit SHA256 digests guarantees byte-for-byte reproducibility across environments and protects against compromised or overwritten registry tags.
- Pair Catalog Updates with Maintenance Windows
Updating an ImageCatalog instantly triggers rolling upgrades across all associated database clusters. In production environments, pair catalog updates with CNPG maintenance window configurations or set primaryUpdateStrategy: unsupervised carefully so automated pod restarts do not trigger during peak traffic hours.
- Choose the Right Catalog Scope (ClusterImageCatalog vs. ImageCatalog)
Use ClusterImageCatalog for organization-wide standard baseline images managed centrally by DBA teams.Use ImageCatalog (namespaced) when specific engineering teams require custom PostgreSQL images (e.g., custom C extensions or experimental builds) isolated to their own namespace.
- Major Version Validation is Up to You
CloudNativePG trusts the declared major number inside the catalog and does not perform runtime version detection against the container binaries. Ensure your CI/CD build pipeline validates that an image tagged under major: 16 actually runs PostgreSQL 16.x binaries to prevent container boot loops.
The post Stop Hardcoding Image Tags: How CNPG Image Catalogs Streamline PostgreSQL Fleet Upgrades appeared first on CYBERTEC PostgreSQL | Services & Support.