Service Management

A PostgreSQL cluster should only be accessed via standard Kubernetes network services directly managed by CloudNativePG. For more details, refer to the "Service" page of the Kubernetes Documentation.

CloudNativePG defines three types of services for each Cluster resource:

  • rw: Points to the primary instance of the cluster (read/write).
  • ro: Points to the replicas, where available (read-only).
  • r: Points to any PostgreSQL instance in the cluster (read).

By default, CloudNativePG creates all the above services for a Cluster resource, with the following conventions:

  • The name of the service follows this format: <CLUSTER_NAME>-<SERVICE_NAME>.
  • All services are of type ClusterIP.

Important

Default service names are reserved for CloudNativePG usage.

While this setup covers most use cases for accessing PostgreSQL within the same Kubernetes cluster, CloudNativePG offers flexibility to:

  • Disable the creation of the ro and/or r default services.
  • Define your own services using the standard Service API provided by Kubernetes.

You can mix these two options.

A common scenario arises when using CloudNativePG in database-as-a-service (DBaaS) contexts, where access to the database from outside the Kubernetes cluster is required. In such cases, you can create your own service of type LoadBalancer, if available in your Kubernetes environment.

Disabling Default Services

You can disable any or all of the ro and r default services through the managed.services.disabledDefaultServices option.

Important

The rw service is essential and cannot be disabled because CloudNativePG relies on it to ensure PostgreSQL replication.

For example, if you want to remove both the ro (read-only) and r (read) services, you can use this configuration:

# <snip>
managed:
  services:
    disabledDefaultServices: ["ro", "r"]

Adding Your Own Services

Important

When defining your own services, you cannot use any of the default reserved service names that follow the convention <CLUSTER_NAME>-<SERVICE_NAME>. It is your responsibility to pick a unique name for the service in the Kubernetes namespace.

You can define a list of additional services through the managed.services.additional stanza by specifying the service type (e.g., rw) in the selectorType field and optionally the updateStrategy.

The serviceTemplate field gives you access to the standard Kubernetes API for the network Service resource, allowing you to define both the metadata and the spec sections as you like.

You must provide a name to the service and avoid defining the selector field, as it is managed by the operator.

Warning

Service templates give you unlimited possibilities in terms of configuring network access to your PostgreSQL database. This translates into greater responsibility on your end to ensure that services work as expected. CloudNativePG has no control over the service configuration, except honoring the selector.

The updateStrategy field allows you to control how the operator updates a service definition. By default, the operator uses the patch strategy, applying changes directly to the service. Alternatively, the recreate strategy deletes the existing service and recreates it from the template.

Warning

The recreate strategy will cause a service disruption with every change. However, it may be necessary for modifying certain parameters that can only be set during service creation.

For example, if you want to have a single LoadBalancer service for your PostgreSQL database primary, you can use the following excerpt:

# <snip>
managed:
  services:
    additional:
      - selectorType: rw
        serviceTemplate:
          metadata:
            name: "mydb-lb"
            labels:
              test-label: "true"
            annotations:
              test-annotation: "true"
          spec:
            type: LoadBalancer

The above example also shows how to set metadata such as annotations and labels for the created service.

About Exposing Postgres Services

There are primarily three use cases for exposing your PostgreSQL service outside your Kubernetes cluster:

  • Temporarily, for testing.
  • Permanently, for DBaaS purposes.
  • Prolonged period/permanently, for legacy applications that cannot be easily or sustainably containerized and need to reside in a virtual machine or physical machine outside Kubernetes. This use case is very similar to DBaaS.

Be aware that allowing access to a database from the public network could expose your database to potential attacks from malicious users.

Warning

Ensure you secure your database before granting external access, or make sure your Kubernetes cluster is only reachable from a private network.