Building a CloudNativePG Provider with OpenEverest v2

Building a CloudNativePG Provider with OpenEverest v2

By Aditya Pimpalkar Aditya Pimpalkar

What is CloudNativePG?

CloudNativePG (CNPG) is an open-source operator designed to manage PostgreSQL workloads on any supported Kubernetes cluster. It fosters cloud-neutrality through seamless deployment in private, public, hybrid, and multi-cloud environments via its distributed topology feature.

Built around DevOps principles, CloudNativePG embraces declarative configuration and immutable infrastructure, ensuring reliability and automation in database management.

At its core, CloudNativePG introduces a custom Kubernetes resource called Cluster, representing a PostgreSQL cluster with:

  • A single primary instance for write operations.
  • Optional replicas for High Availability and read scaling.

In short: CloudNativePG is the operator layer that turns “I want Postgres on this cluster” into a reconciled, observable Kubernetes workload.

Why choose CloudNativePG?

OpenEverest v1 baked database-specific logic into the core. Adding a new engine meant touching the server, operator, CLI, and UI. v2 flips that model. A Provider is a self-contained plugin with it owns the component catalog, topologies, UI schema, and reconciliation against a real Kubernetes operator. CloudnativePG is a CNCF Sandbox project and it has been gaining some reputable traction over the years, becoming a de facto standard for running PostgreSQL on Kubernetes. Since OpenEverest comes with support for Percona PostgresSQL in v1, a community driven CloudnativePG would make a great alternative alongside Percona’s PostgresSQL.

Implementation journey

Day-one operations came quickly

The first slice of the provider was surprisingly smooth.

Core provisioning: scaffolding with the Provider SDK, wiring Sync to create a CloudNativePG Cluster from the Instance engine component, and getting basic status reconciliation working. Once the mental model clicked, day-one create/reconcile felt natural.

UI and resource settings: expanding the replicaSet UI schema, PostgreSQL parameters, managed roles, and separate CPU/memory requests and limits. The definition-driven UI meant most of this was schema work plus small Go type changes, not a custom frontend.

That early progress was motivating. The harder work started when we moved past from simply spin up a cluster into real CloudNativePG depth.

Going deeper: bootstrap, platform features, and backup

Bootstrap (initdb) needed careful reading of CloudNativePG’s bootstrap docs - database name, owner, and credential secrets and making sure the provider passed them through correctly without fighting CNPG defaults.

Certificates, monitoring, and local/CI tooling pushed further into operator behavior and cluster lifecycle. Getting cert support, monitoring hooks, Tilt for local loops, and kuttl integration tests in place meant more time in CloudNativePG docs and more careful RBAC/watch wiring than the day-one path.

Backup was the steepest climb. On-demand backups and Barman cloud plugin integration required a lot of digging into CloudNativePG’s documentation and its Go SDK/APIs ObjectStore, plugin configuration, backup/restore status shapes, and how those map cleanly onto OpenEverest’s backup interfaces. That exploration consumed the most time, but its also where the provider started to feel like a real operational surface, not just a thin translator.

Dogfooding the platform: bugs and UX gaps

Building against a real operator is the fastest way to find platform rough edges.

While implementing Status(), I returned human-readable progress messages:

return controller.Provisioning("waiting for CloudNativePG cluster to initialize"), nil

The phase showed up. The message did not on the Instance CR, not in logs developers care about, not in the UI. Operators only saw Provisioning phase with no hint of if or what the provider was waiting on.

Root cause: ToV2Alpha1() silently dropped Status.Message. I filed #2359 and fixed it upstream in PR #2366 by plumbing message through the API/CRD and conversion path.

That fix matters for every provider, not just this one. Status helpers like Provisioning(...) and Initializing(...) only help if the message survives into the Instance status users actually look at.

Along the way I also filed smaller UX improvements against OpenEverest itself - for example #2452, asking the preview form to show resource units (Gi, mi, etc.) next to CPU, memory, and disk values. Building a provider surfaces both hard bugs and polish opportunities filing them back is part of the job.

Additionally, after giving a coummunity call feedback about wanting a hot-reload developer setup using tilt which allows you to get up and running as a developer without running a bunch of commands first was also taken into consideration and later added to the Provider SDK. Building a real provider is how I was able to find platform gaps and address them personally or relay the feedback to the maintainers.

What’s next?

This provider can create and reconcile CloudNativePG clusters from OpenEverest Instance CRs for local development and testing. Core provisioning: replicas, storage, resources, versions, bootstrap, PostgreSQL tuning, managed roles is in place, with kuttl coverage for basic flows. Backup support exists but still needs more hardening; restore, pooling, and production-grade CI/ops polish are still outstanding.

Keep building with OpenEverest provider model and keep improving it to make the platform better with each feedback and fixes.

If you try it:

Join the Community

Join Slack Star the Repo

See Also