Skip to content

Commit f4501f8

Browse files
committed
feat: image catalog artifacts
Signed-off-by: Gabriele Bartolini <[email protected]>
1 parent 6995028 commit f4501f8

File tree

5 files changed

+293
-0
lines changed

5 files changed

+293
-0
lines changed
119 KB
Loading
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
---
2+
title: "CNPG Recipe 22 - Leveraging the New Supply Chain and Image Catalogs"
3+
date: 2025-10-06T12:23:56+02:00
4+
description: "Leverage a new, fully-controlled software supply chain and streamlined Image Catalogs for safer, simpler, and more declarative management of PostgreSQL on Kubernetes"
5+
tags:
6+
- postgresql
7+
- postgres
8+
- kubernetes
9+
- k8s
10+
- data on kubernetes
11+
- dok
12+
- cloudnativepg
13+
- cnpg
14+
- supply chain
15+
- container images
16+
- image catalogs
17+
- sbom
18+
- security
19+
- devsecops
20+
- upgrades
21+
- extensions
22+
- snyk
23+
- cosign
24+
- sigstore
25+
- tutorial
26+
- guide
27+
cover: cover.jpg
28+
thumb: thumb.jpg
29+
draft: false
30+
---
31+
32+
_This CNPG Recipe explores the latest enhancements to CloudNativePG's software
33+
supply chain and image management. Learn how our new, fully controlled build
34+
process—complete with Snyk scanning, image signing, and SBOMs—delivers smaller,
35+
more secure PostgreSQL images. We also detail how to leverage the newly
36+
streamlined image catalogs for simplified, declarative cluster management and
37+
safer fleet-wide upgrades in Kubernetes._
38+
39+
<!--more-->
40+
41+
---
42+
43+
The container image is the most fundamental building block of a database in
44+
Kubernetes. Managing its source, version, and the security of its supply chain
45+
is critical for your data services. That's why I'm thrilled to announce a
46+
foundational improvement in how we build and source the official [PostgreSQL
47+
operand images](https://github.com/cloudnative-pg/postgres-containers) for
48+
**CloudNativePG**.
49+
50+
This evolution significantly enhances security and reliability, improves the
51+
user experience around image management, and paves a more modular future for
52+
PostgreSQL on Kubernetes.
53+
54+
In line with this, we have also converted our [PostGIS container images](https://github.com/cloudnative-pg/postgis-containers)
55+
to follow the same high standards as the main PostgreSQL images.
56+
57+
## Taking Full Control of Our PostgreSQL Images
58+
59+
First, we at CloudNativePG are making a landmark change to the operand images.
60+
We have definitively moved away from using the official `postgres` image from
61+
Docker Hub, which has accompanied the project since it was open-sourced.
62+
63+
Instead, we have transitioned to a **new software supply chain, built from the
64+
ground up with `docker bake`, that is entirely under the control of the
65+
CloudNativePG project**. While the images continue to be hosted at the standard
66+
registry, their origin and build process are now fundamentally more secure and
67+
robust.
68+
69+
This new, transparent, and secure supply chain provides several key guarantees:
70+
71+
- **Vulnerability Scanning:** Every image is continuously scanned for
72+
vulnerabilities with **Snyk**, allowing us to react faster to newly
73+
discovered CVEs.
74+
- **Image Signing:** All images are cryptographically signed using
75+
**sigstore/cosign**. This provides a guarantee that the images you use were
76+
built by our pipeline and have not been tampered with.
77+
- **Software Bill of Materials (SBOM):** We generate and distribute an SBOM for
78+
each image, providing a complete inventory of every software component and
79+
dependency for full transparency.
80+
- **Optimised Multi-Arch Builds:** Our new `docker bake` pipeline is designed
81+
from the start to efficiently produce multi-architecture images (**amd64**
82+
and **arm64**), ensuring first-class support for diverse Kubernetes
83+
environments.
84+
85+
## Image Catalogs, Perfected: A Reliable New Distribution Pipeline
86+
87+
[**Image Catalogs**](https://cloudnative-pg.io/documentation/current/image_catalog/)
88+
have been a powerful feature in CloudNativePG for over two years, allowing you
89+
to decouple your cluster configuration from specific image tags. However, the
90+
responsibility of creating and maintaining the catalog manifests often fell
91+
to you, the user.
92+
93+
Today, we are removing that friction completely. Our new, trusted distribution
94+
pipeline now provides a reliable, central source for these catalogs. Now,
95+
instead of managing these files yourself, you can install the complete,
96+
[officially maintained catalog](https://www.google.com/search?q=https://github.com/cloudnative-pg/artifacts/tree/main/image-catalogs)
97+
with a single command:
98+
99+
```sh
100+
# Deploy all supported PostgreSQL version catalogs to your cluster
101+
kubectl apply -k \
102+
https://github.com/cloudnative-pg/artifacts/image-catalogs?ref=main
103+
```
104+
105+
Once applied, you can verify that the catalogs have been successfully created
106+
in your cluster with the following command:
107+
108+
```sh
109+
kubectl get clusterimagecatalogs.postgresql.cnpg.io
110+
```
111+
112+
You should see an output similar to this, listing all the available catalogue
113+
options with format `postgresql-<type>-<debian_version>`:
114+
115+
```console
116+
NAME AGE
117+
postgresql-minimal-bookworm 19s
118+
postgresql-minimal-bullseye 19s
119+
postgresql-minimal-trixie 19s
120+
postgresql-standard-bookworm 19s
121+
postgresql-standard-bullseye 19s
122+
postgresql-standard-trixie 19s
123+
postgresql-system-bookworm 19s
124+
postgresql-system-bullseye 19s
125+
postgresql-system-trixie 19s
126+
```
127+
128+
To inspect a specific catalog and see the exact image versions it contains, you
129+
can use `kubectl describe`:
130+
131+
```sh
132+
kubectl describe clusterimagecatalogs.postgresql.cnpg.io \
133+
postgresql-minimal-trixie
134+
```
135+
136+
This reveals the mapping between each major PostgreSQL version and the precise,
137+
immutable container image digest that will be used:
138+
139+
```
140+
Name: postgresql-minimal-trixie
141+
...
142+
Spec:
143+
Images:
144+
Image: ghcr.io/cloudnative-pg/postgresql:16.10-202509290807-minimal-trixie@sha256:f69b49dc63c2988a358c58f8a1311ac98719846f91d8e97186eaf65c7085cf28
145+
Major: 16
146+
Image: ghcr.io/cloudnative-pg/postgresql:17.6-202509290807-minimal-trixie@sha256:f3e24407db6eb8c3c9a7cb433cfe81cbff006ba1f97ae9844a58c7d3cd8048d7
147+
Major: 17
148+
Image: ghcr.io/cloudnative-pg/postgresql:18.0-202509290807-minimal-trixie@sha256:dd7c678167cc6d06c2caf4e6ea7bc7a89e39754bc7e0111a81f5d75ac3068f70
149+
Major: 18
150+
...
151+
```
152+
153+
## Putting it to Work: Referencing the Catalog in a Cluster
154+
155+
Once the catalogs are installed, using them in your `Cluster` manifest is
156+
simple and powerful. Instead of a hardcoded `imageName`, you can use
157+
`imageCatalogRef` to select both a catalog and a specific major version from
158+
it.
159+
160+
```yaml
161+
{{< include "yaml/angus.yaml" >}}
162+
```
163+
164+
This elegant abstraction allows your manifest to declare its *intent*. In this
165+
case, you're requesting a cluster using the `postgresql-minimal-trixie`
166+
catalog, and pinning it specifically to **major version 18**.
167+
168+
After the cluster is up and running, you can `describe` it to see how the
169+
operator has resolved your request into a specific image digest in the `Status`
170+
section:
171+
172+
```sh
173+
kubectl describe cluster angus
174+
```
175+
176+
Notice how the `imageCatalogRef` from the `Spec` is translated into a concrete
177+
`Image` in the `Status`:
178+
179+
```
180+
...
181+
Spec:
182+
Image Catalog Ref:
183+
API Group: postgresql.cnpg.io
184+
Kind: ClusterImageCatalog
185+
Major: 18
186+
Name: postgresql-minimal-trixie
187+
...
188+
Status:
189+
...
190+
Image: ghcr.io/cloudnative-pg/postgresql:18.0-202509290807-minimal-trixie@sha256:dd7c678167cc6d06c2caf4e6ea7bc7a89e39754bc7e0111a81f5d75ac3068f70
191+
...
192+
```
193+
194+
## The Grand Finale: Safe, Automated Fleet Upgrades
195+
196+
This improved system truly shines when managing a database fleet at scale. When
197+
you update the Image Catalog in your cluster, all related clusters will be
198+
scheduled for a rolling update. To prevent a "thundering herd" that could
199+
overwhelm your system, you can control the rollout globally.
200+
201+
This feature, called **spread upgrades**, is configured in the operator's main
202+
`ConfigMap`. By setting the `CLUSTERS_ROLLOUT_DELAY` variable, you instruct the
203+
operator to wait a specific number of seconds before starting the update on the
204+
next cluster.
205+
206+
For example, to set a 2-minute delay between each cluster update:
207+
208+
```yaml
209+
{{< include "yaml/operator-config.yaml" >}}
210+
```
211+
212+
This is a powerful and simple way to ensure a safe, controlled, and completely
213+
automated rollout of updates across your entire database fleet.
214+
215+
## A More Declarative and Modular Future
216+
217+
These improvements—a fully controlled supply chain and a reliable distribution
218+
pipeline for catalogs—are more than just operational conveniences.
219+
They are foundational steps towards a more secure and modular architecture for
220+
running PostgreSQL on Kubernetes. Our ultimate goal is to ship "minimal"
221+
PostgreSQL images containing only the core database engine.
222+
223+
This vision is realised through another powerful feature called "extension
224+
image volumes". Instead of bundling every possible extension into a single,
225+
monolithic image, each extension is packaged in its own separate image.
226+
227+
A newborn project, [PostgreSQL Extension Containers](https://github.com/cloudnative-pg/postgres-extensions-containers),
228+
will contain these images.
229+
230+
When needed, CloudNativePG dynamically loads it into your PostgreSQL pod.
231+
232+
This combined approach is the future:
233+
234+
- **Enhanced Security:** Your core database has a **smaller surface attack**.
235+
- **Modularity and Flexibility:** Manage, version, and update extensions
236+
independently of the PostgreSQL engine.
237+
238+
The image catalogs are the control plane that makes this modular ecosystem
239+
possible, providing the robust, declarative mechanism to manage the entire
240+
suite of components that power your applications.
241+
242+
## Get Started Today
243+
244+
First, I want to thank the entire CloudNativePG team for completing this epic
245+
enhancement, which we started at the beginning of the year. I am really proud
246+
of the result we have achieved from every aspect: operations, security, and
247+
extensibility.
248+
249+
The fact that the [PostgreSQL 18 minimal image is now ~230MB]({{< relref "../20250926-postgresql-18/index.md" >}})
250+
—45% smaller than the equivalent for PostgreSQL 17—is a major step forward. The
251+
image catalogue artifacts are also an important achievement for
252+
standardisation, simplifying integration into any deployment.
253+
254+
I encourage you to adopt this new, simplified workflow for image catalogs
255+
today. You can get started by applying them from our
256+
[`artifacts` repository](https://github.com/cloudnative-pg/artifacts/tree/main/image-catalogs).
257+
258+
For a deeper dive, check out the official documentation on [image catalogs](https://cloudnative-pg.io/documentation/current/image_catalog/)
259+
and [spread upgrades](https://cloudnative-pg.io/documentation/current/installation_upgrade/#spread-upgrades).
260+
261+
To see where this is headed, I invite you to read my previous article on
262+
["The Immutable Future of PostgreSQL Extensions"]({{< relref "../20250303-volume-source-extension-control-path/index.md" >}})
263+
and the official docs on [extension image volumes](https://cloudnative-pg.io/documentation/current/imagevolume_extensions/).
264+
265+
---
266+
267+
Stay tuned for the upcoming recipes! For the latest updates, consider
268+
subscribing to my [LinkedIn](https://www.linkedin.com/in/gbartolini/) and
269+
[Twitter](https://twitter.com/_GBartolini_) channels.
270+
271+
If you found this article informative, feel free to share it within your
272+
network on social media using the provided links below. Your support is
273+
immensely appreciated!
46.3 KB
Loading
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: postgresql.cnpg.io/v1
2+
kind: Cluster
3+
metadata:
4+
name: angus
5+
spec:
6+
instances: 3
7+
imageCatalogRef:
8+
apiGroup: postgresql.cnpg.io
9+
kind: ClusterImageCatalog
10+
name: postgresql-minimal-trixie
11+
major: 18
12+
storage:
13+
size: 1Gi
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: cnpg-controller-manager-config
5+
namespace: cnpg-system
6+
data:
7+
CLUSTERS_ROLLOUT_DELAY: '120'

0 commit comments

Comments
 (0)