Database

RAIL provide Postgres clusters that you can set up to provide database services for your application. These are provided by the CloudNativePG operator.

Postgres clusters are by default created with a database called app and a corresponding user called app as well, but in order to connect to it we also need to provide a password for the user. The password is set up with a secret like this one:

apiVersion: v1
kind: Secret
metadata:
  name: db-app-user
type: kubernetes.io/basic-auth
stringData:
  username: app
  password: pass1

and then you can set up the cluster with a reference to this secret with:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: db
spec:
  instances: 2
  monitoring:
    enablePodMonitor: true
  bootstrap:
    initdb:
      database: app
      owner: app
      secret:
        name: db-app-user
  storage:
    size: 500Mi

This sets up a service with a name derived from the cluster name, suffixed by -rw (in this case db-rw), that you can connect to. In another Pod in the same namespace where the psql command is available you can connect to the database like this:

$ psql --host=db-rw --username=app
Password for user app:
psql (16.9 (Ubuntu 16.9-0ubuntu0.24.04.1), server 17.0 (Debian 17.0-1.pgdg110+1))
WARNING: psql major version 16, server major version 17.
        Some psql features might not work.
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

app=>

Backup

You can set up backups with plugin-barman-cloud, which uses barman under the hood, a popular solution for managing postgresql backups, additional configuration available at https://cloudnative-pg.io/plugin-barman-cloud/docs/usage/

Object Store

Firstly you need an object store, which is how you configure the Barman plugin. In this example we have a secret called nrec-s3 containing the credentials, and using object storage from nrec-bgo. The instanceSidecarConfiguration is required due to plugin-barman-cloud#393

apiVersion: v1
kind: Secret
metadata:
  name: nrec-s3
type: Opaque
data:
  ACCESS_KEY_ID: verylongstring
  ACCESS_SECRET_KEY: verylongsecret
apiVersion: barmancloud.cnpg.io/v1
kind: ObjectStore
metadata:
  name: nrec-store
spec:
  # This will ensure that barman retains at least one backup older than 30 days
  retentionPolicy: "30d"
  configuration:
    destinationPath: s3://postgres-backups/
    endpointURL: https://object.api.bgo.nrec.no
    s3Credentials:
      accessKeyId:
        name: nrec-s3
        key: ACCESS_KEY_ID
      secretAccessKey:
        name: nrec-s3
        key: ACCESS_SECRET_KEY
    wal:
      compression: zstd
    data:
      compression: bzip2
  instanceSidecarConfiguration:
    env:
      - name: AWS_REQUEST_CHECKSUM_CALCULATION
        value: when_required
      - name: AWS_RESPONSE_CHECKSUM_VALIDATION
        value: when_required

Barman Cloud Plugin

Then, in your Cluster spec, you can enable the barman plugin and set it as the designated WAL archiver

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-example
spec:
  # Other cluster settings...
  plugins:
    - name: barman-cloud.cloudnative-pg.io
      isWALArchiver: true
      parameters:
        barmanObjectName: nrec-store

Base Backup

The plugin will now start shipping write-ahead logs to s3, you also need a base backup to apply these logs to, this can be achieved with the cnpg Backup resource, or more likely with the ScheduledBackup resource. This can also be achieved using a VolumeSnapshot rather than the barman plugin, but we’ll use Barman in this example.

How often you take base backups will impact your usage of s3, and how long it takes you to perform a full recovery, similar for the compression options

apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
  name: cluster-example-backup
spec:
  immediate: true # Also trigger a backup when creating this resource
  cluster:
    name: cluster-example
  schedule: '0 0 18 */6 * *' # Every 6th day at 18:00
  backupOwnerReference: self
  method: plugin
  pluginConfiguration:
    name: barman-cloud.cloudnative-pg.io

Restore

Once you have a base backup and working WAL shipping, it’s possible to restore the cluster, if you want to do this it’s probably a good idea to read the recovery documentation. The manifest below creates a new cluster and initializes it using the latest base backup, and then applies each write-ahead log to it

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-restore
spec:
  instances: 2
  imagePullPolicy: IfNotPresent
  bootstrap:
    recovery:
      source: source
      #recoveryTarget:
      #  # Time base target for the recovery
      #  targetTime: "2023-08-11 11:14:21.00000+02"
  externalClusters:
  - name: source
    plugin:
      name: barman-cloud.cloudnative-pg.io
      parameters:
        barmanObjectName: nrec-store
        serverName: cluster-example
  storage:
    size: 1Gi