|
| 1 | +--- |
| 2 | +title: "From proposal to PR: how to contribute to the new CloudNativePG extensions project" |
| 3 | +date: 2026-03-07T17:36:35+11:00 |
| 4 | +description: "A step-by-step guide on contributing PostgreSQL extensions to the CloudNativePG ecosystem using modern build tools and the new Image Volume feature." |
| 5 | +tags: ["postgresql", "postgres", "kubernetes", "k8s", "cloudnativepg", "cnpg", "postgresql", "postgres", "dok", "data on kubernetes", "extensions", "pg_crash", "chaos engineering"] |
| 6 | +cover: cover.jpg |
| 7 | +thumb: thumb.jpg |
| 8 | +draft: false |
| 9 | +--- |
| 10 | + |
| 11 | +_In this article I walk you through the journey of adding the `pg_crash` |
| 12 | +extension to the new CloudNativePG extensions project. It explores the |
| 13 | +transition from legacy standalone repositories to a unified, Dagger-powered |
| 14 | +build system designed for PostgreSQL 18 and beyond. By focusing on the *Image |
| 15 | +Volume* feature and minimal operand images, the post provides a step-by-step |
| 16 | +guide for community members to contribute and maintain their own extensions |
| 17 | +within the CloudNativePG ecosystem._ |
| 18 | + |
| 19 | + |
| 20 | +<!--more--> |
| 21 | + |
| 22 | +--- |
| 23 | + |
| 24 | +At CloudNativePG, we recently reached a milestone in how we manage PostgreSQL |
| 25 | +extensions. With the Kubernetes **Image Volume** feature and the new |
| 26 | +`extension_control_path` parameter in PostgreSQL 18, we finally have a scalable |
| 27 | +way to provide the community with trusted, immutable extension images. |
| 28 | +This critical advancement is the result of amazing work by my colleagues at |
| 29 | +EDB, both for CloudNativePG and PostgreSQL. This led to the creation of the |
| 30 | +[`postgres-extensions-containers`](https://github.com/cloudnative-pg/postgres-extensions-containers) |
| 31 | +project. |
| 32 | + |
| 33 | +But a repository is only as good as its contribution workflow, and only time |
| 34 | +will tell. |
| 35 | + |
| 36 | +## The birth of a unified ecosystem |
| 37 | + |
| 38 | +Making this project a reality was a significant undertaking. If you are |
| 39 | +interested in the technical roadmap, you can explore the [GitHub Epic (Issue #15)](https://github.com/cloudnative-pg/postgres-extensions-containers/issues/15), |
| 40 | +which tracks the features and tasks we implemented to make community |
| 41 | +contributions possible. |
| 42 | + |
| 43 | +As maintainers, our first priority was ensuring a seamless upgrade path for our |
| 44 | +existing users. Before opening the doors to community contributions, we |
| 45 | +migrated and stabilised the key extensions that we already maintain: |
| 46 | + |
| 47 | +- `pgAudit` and `pgvector`: currently part of the `standard` and `system` |
| 48 | + images in the [`postgres-containers`](https://github.com/cloudnative-pg/postgres-containers) |
| 49 | + project. |
| 50 | +- `PostGIS`: currently maintained in the dedicated |
| 51 | + [`postgis-containers`](https://github.com/cloudnative-pg/postgis-containers) |
| 52 | + project. |
| 53 | + |
| 54 | +It is worth noting that we have omitted `pg_failover_slots` from this new |
| 55 | +project. This is because PostgreSQL 18 and CloudNativePG 1.27+ now provide |
| 56 | +native support for failover slots, making the external extension redundant for |
| 57 | +the future. |
| 58 | + |
| 59 | +We are also shifting our strategy regarding operand containers: the `system` |
| 60 | +and `PostGIS` operand images will eventually disappear once PostgreSQL 17 is |
| 61 | +phased out in November 2029. For PostgreSQL 18 and beyond, this new unified |
| 62 | +repository is the official home. |
| 63 | +While the `standard` image will remain to serve users requiring locale support |
| 64 | +and specific libraries, the ecosystem is converging towards **minimal images**. |
| 65 | + |
| 66 | +By centralising these extensions, we have decoupled their lifecycle from the |
| 67 | +main PostgreSQL engine images. This allows us to update an extension or patch a |
| 68 | +vulnerability without forcing a rebuild of the entire PostgreSQL operand |
| 69 | +image. It is a massive win for operational stability and security. |
| 70 | + |
| 71 | +## The case study: pg_crash |
| 72 | + |
| 73 | +To "dogfood" our new contribution process, I chose to migrate `pg_crash`. This |
| 74 | +extension is a disruptive tool designed for Chaos Engineering; it |
| 75 | +randomly or periodically terminates PostgreSQL processes to verify that |
| 76 | +CloudNativePG properly detects failures and performs failovers. |
| 77 | + |
| 78 | +I strongly discourage using it in production, unless you are deliberately chaos |
| 79 | +engineering your infrastructure (which, in fact, is the proper way to perform |
| 80 | +chaos engineering). However, for most users, it serves as the ultimate "fire |
| 81 | +drill" for testing resilience in staging environments. |
| 82 | + |
| 83 | +By distributing the `pg_crash` extension image, we can successfully dismiss the |
| 84 | +old, standalone [`pgcrash-containers`](https://github.com/cloudnative-pg/pgcrash-containers) |
| 85 | +project and, at the same time, provide an example for future contributors to follow. |
| 86 | + |
| 87 | +## The journey: following the guide |
| 88 | + |
| 89 | +I used our new |
| 90 | +[`CONTRIBUTING_NEW_EXTENSION.md`](https://github.com/cloudnative-pg/postgres-extensions-containers/blob/main/CONTRIBUTING_NEW_EXTENSION.md) |
| 91 | +guide as my map. Here is how the journey looked. |
| 92 | + |
| 93 | +### Package discovery |
| 94 | + |
| 95 | +Before writing code, I had to ensure the package was available in the PGDG |
| 96 | +(PostgreSQL Global Development Group) repositories. I ran a "disposable" |
| 97 | +container to search for it: |
| 98 | + |
| 99 | +```sh |
| 100 | +docker run -u root -ti --rm ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie |
| 101 | +# apt update && apt search pg-crash |
| 102 | +``` |
| 103 | + |
| 104 | +### Scaffolding the extension |
| 105 | + |
| 106 | +We use [Dagger](https://dagger.io) to automate the mundane tasks of |
| 107 | +building and testing. One command created the entire directory structure for |
| 108 | +me: |
| 109 | + |
| 110 | +```bash |
| 111 | +task create-extension NAME=pg-crash |
| 112 | +``` |
| 113 | + |
| 114 | +This generated the `metadata.hcl`, `Dockerfile`, and a template `README.md`. My |
| 115 | +job was to fill in the "TODOs" to ensure the extension correctly copied the |
| 116 | +`.so`, `.sql`, and `.control` files into the scratch image. |
| 117 | + |
| 118 | +### The local feedback loop |
| 119 | + |
| 120 | +One of the most satisfying parts of the workflow is the local testing |
| 121 | +environment. I could bake the image and see it running in a real Kubernetes |
| 122 | +cluster on my laptop: |
| 123 | + |
| 124 | +```bash |
| 125 | +task e2e:test:full TARGET="pg-crash" |
| 126 | +``` |
| 127 | + |
| 128 | +The framework provides basic smoke tests to verify that the extension image can |
| 129 | +be deployed in a CNPG cluster and installed both in the system and, if |
| 130 | +applicable, in a database via `CREATE EXTENSION`. |
| 131 | +If an extension requires more rigorous validation, you can submit additional |
| 132 | +specific tests using the Chainsaw framework. |
| 133 | + |
| 134 | +### Manual verification |
| 135 | + |
| 136 | +Once the automated tests passed, I performed a manual "sanity check". I |
| 137 | +exported the Kubeconfig, identified the image tag using tools like `skopeo`, |
| 138 | +and deployed a 3-instance cluster to watch `pg_crash` trigger a real failover. |
| 139 | +Seeing the orchestrator respond exactly as expected is the ultimate validation. |
| 140 | + |
| 141 | +## Navigating licensing |
| 142 | + |
| 143 | +During the PR process |
| 144 | +([#126](https://github.com/cloudnative-pg/postgres-extensions-containers/pull/126)), |
| 145 | +we refined our licensing policy. Since we redistribute unmodified PGDG |
| 146 | +packages, we confirmed that the PostgreSQL License is CNCF-compliant. |
| 147 | +For other open-source licenses, such as FSF-approved (GPL), we established a |
| 148 | +case-by-case review process to ensure the legal integrity of the project. |
| 149 | + |
| 150 | +## Conclusion: join the movement |
| 151 | + |
| 152 | +With thew conversion of `pg_crash` to an image volume extension, we have turned |
| 153 | +a standalone maintenance burden into a community-ready template. |
| 154 | + |
| 155 | +The [`postgres-extensions-containers`](https://github.com/cloudnative-pg/postgres-extensions-containers) |
| 156 | +project represents a unique opportunity for everyone to contribute to |
| 157 | +CloudNativePG and maintain one or more extensions for the years to come. |
| 158 | +By maintaining these images, you are helping build the most robust and flexible |
| 159 | +PostgreSQL ecosystem in the cloud-native world. |
| 160 | + |
| 161 | +If you want to dive deeper into the technical mechanics of how these extensions |
| 162 | +are used, I encourage you to read my previous blog post: |
| 163 | +[CNPG Recipe 23: Managing extensions with ImageVolume in CloudNativePG]({{< relref "../20251201-extensions/index.md" >}}). |
| 164 | + |
| 165 | +Furthermore, the future of extension management is becoming even more |
| 166 | +streamlined; CloudNativePG 1.29 introduces [support for extensions in image catalogs](https://github.com/cloudnative-pg/cloudnative-pg/pull/9781), |
| 167 | +a feature that makes the distribution,discovery and usage of these |
| 168 | +community-maintained images much easier. |
| 169 | + |
| 170 | +Finally, I want to thank EDB and EDB's customers for supporting us in this |
| 171 | +endeavour. This project has been nearly two years in the making, and your |
| 172 | +support is what allows us to keep making Postgres better for the years to come |
| 173 | +in Kubernetes. |
| 174 | + |
| 175 | +_Are you ready to contribute? Check out the |
| 176 | +[Contribution Guide](https://github.com/cloudnative-pg/postgres-extensions-containers/blob/main/CONTRIBUTING_NEW_EXTENSION.md) |
| 177 | +and let's build the future of cloud-native PostgreSQL together!_ |
| 178 | + |
| 179 | +--- |
| 180 | + |
| 181 | +Stay tuned for the upcoming recipes! For the latest updates, consider |
| 182 | +subscribing to my [LinkedIn](https://www.linkedin.com/in/gbartolini/) and |
| 183 | +[Twitter](https://twitter.com/_GBartolini_) channels. |
| 184 | + |
| 185 | +If you found this article informative, feel free to share it within your |
| 186 | +network on social media using the provided links below. Your support is |
| 187 | +immensely appreciated! |
| 188 | + |
| 189 | +<!-- |
| 190 | +_Cover Picture: [“TITLE“](URL)._ |
| 191 | +--> |
| 192 | + |
0 commit comments