Skip to content

4. Image catalog

Goal: declare which PostgreSQL image your cluster runs, using a ClusterImageCatalog — the modern, pinned, fleet-friendly way introduced in CloudNativePG 1.29.

Why not just hard-code imageName?

You can put imageName: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie directly in the Cluster. But an image catalog is better for reproducible infra:

  • It maps a major version (e.g. 18) to a specific, pinned, signed image in one place.
  • Multiple clusters can share one catalog; updating the catalog rolls them all (controlled by spread-upgrade settings).
  • It separates "which Postgres major version" (in the Cluster) from "which exact image" (in the catalog).
flowchart LR
    cl["Cluster<br/>imageCatalogRef:<br/>major: 18"] -->|looks up major 18| cat["ClusterImageCatalog<br/>18 → postgresql:18.3-system-trixie"]
    cat --> img[("ghcr.io/.../postgresql:18.3-system-trixie")]

ImageCatalog vs ClusterImageCatalog

  • ImageCatalog is namespaced (usable by Clusters in the same namespace).
  • ClusterImageCatalog is cluster-wide (usable from any namespace).

We use a ClusterImageCatalog so the catalog is reusable and lives outside the database namespace.

Step 4.1 — Create the catalog

Save as image-catalog.yaml:

image-catalog.yaml
apiVersion: postgresql.cnpg.io/v1
kind: ClusterImageCatalog
metadata:
  name: postgresql
spec:
  images:
    - major: 18
      image: ghcr.io/cloudnative-pg/postgresql:18.3-system-trixie   # (1)!
  1. 18.3 is the current PostgreSQL 18 minor and the default operand in CNPG 1.29. The system-trixie flavor is the default (Debian 13 "trixie" base). Pin a digest in production for full immutability; the tag is fine for learning.
kubectl apply -f image-catalog.yaml
kubectl get clusterimagecatalog postgresql -o yaml | grep -A3 images

How the Cluster references it (preview)

  imageCatalogRef:
    apiGroup: postgresql.cnpg.io
    kind: ClusterImageCatalog
    name: postgresql
    major: 18

Operand image flavors (quick reference)

The community publishes several flavors of the operand image:

Flavor Notes
system Default; broad set of locales/extensions. Used here.
standard Middle ground.
minimal Smallest; fewer built-ins.

Tag shape is <pgMajor>.<pgMinor>-<flavor>-<debianCodename>, e.g. 18.3-system-trixie. The community also ships ready-made catalog manifests you can apply instead of writing your own.

What could go wrong

  • Mismatched major between the catalog and the Cluster's imageCatalogRef.major → the operator cannot resolve an image.
  • Wrong architecture image — not a concern here since all nodes are amd64 and the multi-arch image includes amd64.
  • Floating tags in production — fine for learning, but pin to an image digest (@sha256:...) for true reproducibility later.

Where to go deeper

Next: Secrets & ObjectStore (R2) — wiring up the backup destination.