Install Zalando Postgres Operator on K8s Cluster

Posted on Aug 11, 2022

Overview

Postgres Operator

The Postgres Operator delivers an easy to run highly-available PostgreSQL clusters on Kubernetes (K8s) powered by Patroni. It is configured only through Postgres manifests (CRDs) to ease integration into automated CI/CD pipelines with no access to Kubernetes API directly, promoting infrastructure as code vs manual operations.

Patroni

Patroni is a template for you to create your own customized, high-availability solution using Python and - for maximum accessibility - a distributed configuration store like ZooKeeper, etcd, Consul or Kubernetes. Database engineers, DBAs, DevOps engineers, and SREs who are looking to quickly deploy HA PostgreSQL in the datacenter-or anywhere else-will hopefully find it useful.

Spilo

Spilo is a Docker image that provides PostgreSQL and Patroni bundled together. Multiple Spilos can create a resilient High Available PostgreSQL cluster. For this, you’ll need to start all participating Spilos with identical etcd addresses and cluster names.

Install Postgres Operator

Clone repo:

git clone https://github.com/zalando/postgres-operator.git
cd postgres-operator
git checkout v1.8.2

We will use postgres-operator namespace to deploy operator and cluster in it. Create postgres-operator namespase:

kubectl create ns postgres-operator

Let’s switch to it:

kubens postgres-operator

Install the Postgres Operator:

helm install postgres-operator ./charts/postgres-operator

Check that Pod is running:

kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
postgres-operator-6f6fcf84b4-bss7k   1/1     Running   0          4s

To check Spilo image use the command below:

kubectl get operatorconfiguration
NAME                IMAGE                                               CLUSTER-LABEL   SERVICE-ACCOUNT   MIN-INSTANCES   AGE
postgres-operator   registry.opensource.zalan.do/acid/spilo-14:2.1-p6   cluster-name    postgres-pod      -1              30s

Create Postgres cluster

Configure Postgres cluster CR manifests/minimal-postgres-manifest.yaml:

apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
  name: postgres-minimal-cluster
  namespace: postgres-operator
spec:
  teamId: "postgres"
  volume:
    size: 1Gi
  numberOfInstances: 3
  users:
    alise:  # database owner
    - superuser
    - createdb
    bob:
    - nologin
    carl:
    - login
  databases:
    alisedb: alise  # dbname: owner
    carldb: carl
  postgresql:
    version: "14"

In this CR we want to create a couple of users and assigned to them flags (credentials). By the way if you want to add some additional users in existing database you need to edit an existing CR. The Zalando Postgres Operator will update/add the users without restart the Pods. Use following command for that and update the relevant fields:

kubectl edit  postgresqls.acid.zalan.do postgres-minimal-cluster

Create Postgres cluster:

kubectl create -f manifests/minimal-postgres-manifest.yaml

Check the Pods:

kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
postgres-minimal-cluster-0           1/1     Running   0          3m49s
postgres-minimal-cluster-1           1/1     Running   0          3m24s
postgres-minimal-cluster-2           1/1     Running   0          2m20s
postgres-operator-6f6fcf84b4-ngbxc   1/1     Running   0          4m22s

You can also check who is the master among the Pods:

kubectl get pods -l spilo-role=master
NAME                         READY   STATUS    RESTARTS   AGE
postgres-minimal-cluster-0   1/1     Running   0          9m26s

Check the status of the cluster:

kubectl get postgresql
NAME                       TEAM       VERSION   PODS   VOLUME   CPU-REQUEST   MEMORY-REQUEST   AGE     STATUS
postgres-minimal-cluster   postgres   14        3      1Gi                                     3m34s   Running

Check the logs:

kubectl logs postgres-minimal-cluster-0 -f

Connect to PostgreSQL

Use psql client to connect to the database.

Connect to a Pod of the Postgres cluster:

kubectl exec -it postgres-minimal-cluster-0 -- bash

As we already here let’s quickly check the status of the cluster but at this time we will use patronictl command for that:

patronictl list
+ Cluster: postgres-minimal-cluster (7130504521272213573) ------+----+-----------+
| Member                     | Host         | Role    | State   | TL | Lag in MB |
+----------------------------+--------------+---------+---------+----+-----------+
| postgres-minimal-cluster-0 | 100.64.1.237 | Leader  | running |  1 |           |
| postgres-minimal-cluster-1 | 100.64.0.51  | Replica | running |  1 |         0 |
| postgres-minimal-cluster-2 | 100.64.1.202 | Replica | running |  1 |         0 |
+----------------------------+--------------+---------+---------+----+-----------+

Switch as a postgres user to connect to the Postgres database without password:

su - postgres

Then run psql command to connect to the Postgres:

psql
psql (14.4 (Ubuntu 14.4-1.pgdg18.04+1))
Type "help" for help.

postgres=# \du
                                             List of roles
 Role name  |                         Attributes                         |          Member of
------------+------------------------------------------------------------+-----------------------------
 admin      | Create DB, Cannot login                                    | {cron_admin,carl,alise,bob}
 alise      | Superuser, Create DB                                       | {}
 bob        | Cannot login                                               | {}
 carl       |                                                            | {}
 cron_admin | Cannot login                                               | {}
 postgres   | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 robot_zmon | Cannot login                                               | {}
 standby    | Replication                                                | {}
 zalandos   | Create DB, Cannot login                                    | {}

postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 alisedb   | alise    | UTF8     | en_US.utf-8 | en_US.utf-8 |
 carldb    | carl     | UTF8     | en_US.utf-8 | en_US.utf-8 |
 postgres  | postgres | UTF8     | en_US.utf-8 | en_US.utf-8 |
 template0 | postgres | UTF8     | en_US.utf-8 | en_US.utf-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf-8 | en_US.utf-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(5 rows)

As you can see our users and databases have successfully created.

Delete Postgres cluster

To delete Postgres cluster execute the following commands:

kubectl delete -f manifests/minimal-postgres-manifest.yaml && \
kubectl delete statefulset postgres-minimal-cluster --ignore-not-found=true && \
kubectl delete crds postgresqls.acid.zalan.do --ignore-not-found=true  && \
kubectl delete crds postgresteams.acid.zalan.do --ignore-not-found=true  && \
kubectl delete endpoints postgres-minimal-cluster --ignore-not-found=true  && \
kubectl delete endpoints postgres-minimal-cluster-config --ignore-not-found=true  && \
kubectl delete endpoints postgres-minimal-cluster-repl --ignore-not-found=true  && \
kubectl delete service postgres-minimal-cluster --ignore-not-found=true  && \
kubectl delete service postgres-minimal-cluster-repl --ignore-not-found=true  && \
kubectl delete poddisruptionbudgets postgres-postgres-minimal-cluster-pdb --ignore-not-found=true

Uninstall postgres-operator:

helm uninstall postgres-operator

Delete the operatorconfigurations CRD:

kubectl delete crds operatorconfigurations.acid.zalan.do

That’s all for today.