Skip to content

Databases

Databases are created as custom resources in your namespace. The operators already run in the cluster, there is nothing to install.

PostgreSQL (CloudNativePG)

Group and version: postgresql.cnpg.io/v1, kind Cluster.

yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: app-db
spec:
  instances: 3
  storage:
    size: 10Gi
    storageClass: hcloud-volumes

A single instance with no backup is not production

A Cluster with instances: 1 and no backup configuration is a starting point for trying things out. For production use instances: 3 and configure a backup target. Without both, losing the node means losing the data.

You cannot get a shell in a PostgreSQL pod

kubectl exec into a CloudNativePG pod is refused:

text
Error from server: admission webhook denied the request:
Exec/attach is only allowed into gVisor-sandboxed pods.

Your own workloads run sandboxed and accept exec normally. PostgreSQL pods are the exception, so this affects PostgreSQL only. MariaDB and Dragonfly pods take a shell like anything else.

kubectl port-forward is not affected, so the usual way to run SQL against your own database is to forward its port and connect with a local client, using the credentials the operator generated. A short-lived psql pod inside the namespace works too.

MariaDB (mariadb-operator)

Group: k8s.mariadb.com, kind MariaDB.

yaml
apiVersion: k8s.mariadb.com/v1alpha1
kind: MariaDB
metadata:
  name: app-db
spec:
  rootPasswordSecretKeyRef:
    name: app-db-root
    key: password
  storage:
    size: 10Gi
    storageClassName: hcloud-volumes

Dragonfly

Group and version: dragonflydb.io/v1alpha1, kind Dragonfly.

yaml
apiVersion: dragonflydb.io/v1alpha1
kind: Dragonfly
metadata:
  name: cache
spec:
  replicas: 2

The instance is reachable at redis://<name>:6379, so redis://cache:6379 for the example above.

Dragonfly speaks the Redis wire protocol, so most clients work unchanged. There are, however, documented behavioural differences on individual commands. Test your application before migrating an existing Redis instance.

Backups

Both PostgreSQL and MariaDB can back themselves up on a schedule, to a bucket you own. There is no bucket provided for you, so this is a thing you set up rather than a thing you inherit.

Where backups go

Anywhere S3-compatible. ITSH object storage works and is the easiest option: create a bucket and an access key, then put the key in a secret in your namespace.

bash
kubectl create secret generic backup-creds \
  --from-literal=ACCESS_KEY_ID='<access-key>' \
  --from-literal=ACCESS_SECRET_KEY='<secret-key>'

PostgreSQL

Add a backup target to the cluster, then schedule it:

yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: app-db
spec:
  instances: 3
  storage:
    size: 10Gi
    storageClass: hcloud-volumes
  backup:
    barmanObjectStore:
      destinationPath: "s3://my-backups/app-db"
      endpointURL: "https://storage.itsh.dev"
      s3Credentials:
        accessKeyId:
          name: backup-creds
          key: ACCESS_KEY_ID
        secretAccessKey:
          name: backup-creds
          key: ACCESS_SECRET_KEY
    retentionPolicy: "30d"
---
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
  name: app-db-daily
spec:
  schedule: "0 0 3 * * *"
  cluster:
    name: app-db

The schedule is a six-field cron expression, seconds first, so the example runs at 03:00 daily.

barmanObjectStore prints a deprecation warning

Applying the above tells you the field is deprecated and will be removed in a future version of the operator. That is expected: it is currently the only way to configure backups here, and the plugin that replaces it is not available yet. Use it, and expect to migrate when it is.

MariaDB

Backup and Restore resources work the same way, taking either an S3 target or a PVC. See the mariadb-operator documentation for the field layout.

Two limits worth knowing

Object versioning, lifecycle rules and object-lock are not available on ITSH object storage buckets, so backups here cannot be made immutable: anything with write access to the bucket can also delete them.

Give backups their own bucket and an access key scoped to it, and keep that key out of workloads that do not need it. If immutable backups are a hard requirement for you, talk to support before you rely on this setup.

There is no volume snapshot and no point-in-time volume restore. Backups are database-level, taken by the operator. A PVC that is not a managed database has no equivalent, so anything you care about in a plain volume needs its own copy somewhere.

Test the restore

A backup nobody has restored is a guess. Restore into a scratch cluster once, before you need it, and check the data is actually there.

What's next