Skip to content

Databases

PostgreSQL, MariaDB and Redis run on the platform under Kubernetes operators. An operator is a controller that watches for objects of its own custom resource types and reconciles the running database to match them, continuously. Creating a database therefore means creating an object rather than calling a provisioning API, and the operator keeps the result in the state the object describes.

Each engine runs as a StatefulSet on persistent volumes, so it is scheduled, restarted, monitored and backed up by the same machinery as any other workload. You are responsible for your schema and your data; provisioning, replication, failover, patching and backups are handled by the operator.

Each engine is reached the same way in the console: WebHosting > Databases, then the engine you want. Every row on those pages is one logical database in your project.

PostgreSQL

Powered by CloudNativePG.

PostgreSQL databases can only reference a Postgres cluster in the same project, so each project that wants PostgreSQL needs its own cluster provisioned once before the Create PostgreSQL button will work. That first step is not yet self-service - ask your platform administrator, or apply the Cluster yourself if you have oc access with sufficient permissions:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgres
  namespace: <your-project>
spec:
  bootstrap:
    initdb:
      database: app
      owner: app
  enablePDB: false
  enableSuperuserAccess: true
  imageName: ghcr.io/cloudnative-pg/postgresql:17.2
  instances: 1
  storage:
    storageClass: berry-storage-block
    accessModes:
    - ReadWriteOnce
    size: 5Gi

Set instances above 1 for high availability, and enablePDB: true once you do. Encrypted offsite backups are wired up automatically for every cluster - you do not configure spec.backup yourself. See Observability & backup.

Once the cluster exists, each additional database is lightweight:

apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
  name: myapp
  namespace: <your-project>
spec:
  cluster:
    name: postgres
  name: myapp
  owner: app

Connecting. CloudNativePG creates the Services and a credentials Secret for you:

What Where
Read-write host <cluster-name>-rw.<your-project>.svc
Read-only host <cluster-name>-ro.<your-project>.svc
Credentials Secret <cluster-name>-app, keys username and password

Deleting. Removing a Database drops that one database. Removing the Cluster removes the whole instance and every database in it - back up anything you need first.

MariaDB

Powered by the MariaDB Operator.

Like PostgreSQL, MariaDB runs per project: a MariaDB server in your namespace, on your storage, with the databases inside it. Two Templates in the openshift namespace create the objects, so the console and oc process produce the same result:

oc process -n openshift mariadb-instance -p NAME=mariadb -p NAMESPACE=<your-project> | oc apply -f -
oc process -n openshift mariadb-database -p NAME=myapp -p NAMESPACE=<your-project> \
  -p INSTANCE_NAME=mariadb -p DB_USER=myapp-user | oc apply -f -

The first creates the server and a Secret mariadb-root with root's generated password. The second creates the database, the user your application connects as, a grant giving that user all privileges on that one database, and the credentials Secret:

apiVersion: k8s.mariadb.com/v1alpha1
kind: Database
metadata:
  name: myapp
  namespace: <your-project>
spec:
  mariaDbRef:
    name: mariadb
    waitForIt: true
  name: myapp
  characterSet: utf8mb4
  collate: utf8mb4_unicode_ci
  cleanupPolicy: Skip

Connecting. Everything a workload needs is in one Secret:

What Where
Host <server>.<your-project>.svc, port 3306
Credentials Secret <database>-db-user, keys username, password, host, port and database

Deleting. Removing a Database keeps the data on the server (cleanupPolicy: Skip); set it to Delete first to drop the database. Removing the MariaDB removes the whole server and every database in it - back up anything you need first. See the MariaDB guide.

Redis

Powered by the Redis Operator. Each instance is dedicated to your project - caching, sessions, queues and other low-latency workloads.

The password comes from a Secret you create first:

apiVersion: v1
kind: Secret
metadata:
  name: redis-cache
  namespace: <your-project>
type: Opaque
stringData:
  password: <choose-a-strong-password>
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: Redis
metadata:
  name: cache
  namespace: <your-project>
spec:
  kubernetesConfig:
    image: quay.io/opstree/redis:v7.0.12
    imagePullPolicy: IfNotPresent
    redisSecret:
      name: redis-cache
      key: password
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 250m
        memory: 256Mi
    service:
      serviceType: ClusterIP
  redisConfig: {}
  storage:
    volumeClaimTemplate:
      spec:
        storageClassName: berry-storage-block
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi

Omit redisSecret for an instance with no authentication.

Connecting. Host <name>.<your-project>.svc, port 6379, authenticating with the password from the Secret.

Deleting. Remove the Redis object. Depending on your storage class's reclaim policy, its persistent volume goes with it.

Simple and advanced views

The PostgreSQL and MariaDB pages carry a Simple / Advanced toggle. Simple is the guided view described above. Advanced hands off to the operator's own panel, which exposes every resource type the operator provides and full YAML editing - useful for replicas, poolers and scheduled backups that the guided forms do not cover.

How to

Step-by-step guides for each of these, in the console and as YAML: