Setting up multiple databases with CNPG v1.25+

I love a bit of Kubernetes but I also hate it as I navigate the Kubernetes landscape and learning from doing. I have come across multiple gotyas. This is one of them, I run a CloudnativePG Cluster, Originally I only used this to play around with Postgres.

However, the more applications I deployed to my cluster the more applications depended on storing things in Postgres. This made me spin up a Postgres instance via Docker on a VM, this way I could keep the instance up, in case I needed to tear down my cluster.

This worked fine, but I wanted to migrate everything to within Kubernetes. Now with CNPG v1.25+ I and ArgoCDs sync-wave I can do just that.

Deploying a database

Getting a basic cluster setup via CNPG is pretty simple, deploy an operator and then a cluster manifest. Now you have yourself a working High-Availability Postgres cluster. But bare bones it doesn't spin up with any databases unless you use bootstrap.initdb to configure a single database from the start.

But what about multiple databases, Each of my applications requires its own. With v1.25+ this is as simple as deploying a Database manifest. Additional databases can be created or managed via declarative database management using the Database CRD, Below is an example of a database deployed for the application Authentik:

apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
  name: authentik-db
spec:
  name: authentik-db # db name
  owner: authentik # db owner
  cluster:
    name: cnpg-cluster # name of your cluster

Before deploying you will have to give the owner a role within the cluster, if you're not using the postgres superuser. A role within the cluster manifest looks like this:

spec:
  managed:
  roles:
 - name: authentik
      ensure: present
      comment: 'Simple application user for Authentik'
      login: true
      superuser: true
      passwordSecret:
        name: cnpg-authentik-user

For my use case, I gave the user superuser access, as I had trouble giving the role the correct permissions so I gave up and gave superuser access. You also have to give the user a password, which is as simple as creating a secret and deploying that.

That's pretty much it, this is how I deploy multiple databases within my cluster when it's created. And of course, you can deploy as many Database manifests as needed.

Sync-wave...ArgoCD

Not sure about you, but I was wondering how I could deploy the applications and databases without things crashing because the database wasn't ready.

Enter sync-wave with ArgoCD. Adding a sync-wave annotation to ArgoCD Application manifest tells ArgoCD to deploy your applications in waves. The below manifest shows that I am deploying my Postgres cluster in sync-wave: 0. This will deploy in the first round, ArgoCD won't deploy any other waves till all applications in wave 0 are healthy.

metadata:
  name: &app cnpg-cluster
  namespace: argocd
  annotations:
    argocd.argoproj.io/sync-wave: '0'

Therefore it would be practical to deploy all other applications that relied on the PostgreSQL cluster to deploy in wave 1 or wave 2. This way once the cluster is healthy and all of its databases are deployed. The other applications can be deployed and write to the databases. Something like this:

sync-wave argocd

This is how I have set up my CloudNativePG cluster and it works pretty well. I am sure this is very basic but for me it works, you can find more about sync-wave or deploying Databases on the links below: