CNPG-I
======
.. raw:: html
The **CloudNativePG Interface** ( `CNPG-I `_ ) is a standard way to
extend and customize CloudNativePG without modifying its core codebase.
Why CNPG-I?
-----------
CloudNativePG supports a wide range of use cases, but sometimes its
built-in functionality isn’t enough, or adding certain features directly
to the main project isn’t practical.
Before CNPG-I, users had two main options:
- Fork the project to add custom behavior, or
- Extend the upstream codebase by writing custom components on top of
it.
Both approaches created maintenance overhead, slowed upgrades, and
delayed delivery of critical features.
CNPG-I solves these problems by providing a stable, gRPC-based
integration point for extending CloudNativePG at key points in a
cluster’s lifecycle —such as backups, recovery, and sub-resource
reconciliation— without disrupting the core project.
CNPG-I can extend:
- The operator, and/or
- The instance manager running inside PostgreSQL pods.
Registering a plugin
--------------------
CNPG-I is inspired by the Kubernetes :ref:`Container Storage Interface (CSI) ` . The operator
communicates with registered plugins using **gRPC**, following the
`CNPG-I protocol `_ .
CloudNativePG discovers plugins **at startup**. You can register them in
one of two ways:
- Sidecar container – run the plugin inside the operator’s Deployment
- Standalone Deployment – run the plugin as a separate workload in the
same namespace
In both cases, the plugin must be packaged as a container image.
Sidecar Container
^^^^^^^^^^^^^^^^^
When running as a sidecar, the plugin must expose its gRPC server via a
**Unix domain socket**. This socket must be placed in a directory shared
with the operator container, mounted at the path set in
``PLUGIN_SOCKET_DIR`` (default: ``/plugin`` ).
Example:
.. code:: yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
spec:
template:
spec:
containers:
- image: cloudnative-pg:latest
[...]
name: manager
volumeMounts:
- mountPath: /plugins
name: cnpg-i-plugins
- image: cnpg-i-plugin-example:latest
name: cnpg-i-plugin-example
volumeMounts:
- mountPath: /plugins
name: cnpg-i-plugins
volumes:
- name: cnpg-i-plugins
emptyDir: {}
Standalone Deployment (recommended)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Running a plugin as its own Deployment decouples its lifecycle from the
operator’s and allows independent scaling. In this setup, the plugin
exposes a TCP gRPC endpoint behind a Service, with **mTLS** for secure
communication.
.. Warning::
CloudNativePG does **not** discover plugins dynamically. If you deploy a new plugin, you must **restart the operator** to detect it.
Example Deployment:
.. code:: yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: cnpg-i-plugin-example
spec:
template:
[...]
spec:
containers:
- name: cnpg-i-plugin-example
image: cnpg-i-plugin-example:latest
ports:
- containerPort: 9090
protocol: TCP
The related Service for the plugin must include:
- The label ``cnpg.io/plugin: `` — required for
CloudNativePG to discover the plugin
- The annotation ``cnpg.io/pluginPort: `` — specifies the port
where the plugin’s gRPC server is exposed
Example Service:
.. code:: yaml
apiVersion: v1
kind: Service
metadata:
annotations:
cnpg.io/pluginPort: "9090"
labels:
cnpg.io/pluginName: cnpg-i-plugin-example.my-org.io
name: cnpg-i-plugin-example
spec:
ports:
- port: 9090
protocol: TCP
targetPort: 9090
selector:
app: cnpg-i-plugin-example
Configuring TLS Certificates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When a plugin runs as a ``Deployment`` , communication with
CloudNativePG happens over the network. To secure it, **mTLS is
enforced**, requiring TLS certificates for both sides.
Certificates must be stored as `Kubernetes TLS Secrets `_
and referenced in the plugin’s Service annotations
(``cnpg.io/pluginClientSecret`` and ``cnpg.io/pluginServerSecret`` ):
.. code:: yaml
apiVersion: v1
kind: Service
metadata:
annotations:
cnpg.io/pluginClientSecret: cnpg-i-plugin-example-client-tls
cnpg.io/pluginServerSecret: cnpg-i-plugin-example-server-tls
cnpg.io/pluginPort: "9090"
name: barman-cloud
namespace: postgresql-operator-system
spec:
[...]
.. Note::
You can provide your own certificate bundles, but the recommended method is to use `Cert-manager `_ .
Using a plugin
--------------
To enable a plugin, configure the ``.spec.plugins`` section in your
``Cluster`` resource. Refer to the CloudNativePG API Reference for the
full `PluginConfiguration `_
specification.
Example:
.. code:: yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-with-plugins
spec:
instances: 1
storage:
size: 1Gi
plugins:
- name: cnpg-i-plugin-example.my-org.io
enabled: true
parameters:
key1: value1
key2: value2
Each plugin may have its own parameters—check the plugin’s documentation
for details. The ``name`` field in ``spec.plugins`` depends on how the
plugin is deployed:
- Sidecar container: use the Unix socket file name
- Deployment: use the value from the Service’s ``cnpg.io/pluginName``
label
Community plugins
-----------------
The CNPG-I protocol has quickly become a proven and reliable pattern for
extending CloudNativePG while keeping the core project maintainable.
Over time, the community has built and shared plugins that address
real-world needs and serve as examples for developers.
For a complete and up-to-date list of plugins built with CNPG-I, please
refer to the `CNPG-I GitHub page `_ .