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 `_ .