Zalando Postgres Operator

WARNING

This is not complete !

Logo

The Postgres Operator enables highly-available PostgreSQL clusters on Kubernetes (K8s) powered by Patroni. It is configured only through manifests to ease integration into automated CI/CD pipelines with no access to Kubernetes directly.

Operator features

  • Rolling updates on Postgres cluster changes
  • Volume resize without Pod restarts
  • Cloning Postgres clusters
  • Logical Backups to S3 Bucket
  • Standby cluster from S3 WAL archive
  • Configurable for non-cloud environments
  • UI to create and edit Postgres cluster manifests

PostgreSQL Operator features

The Postgres Operator has been developed at Zalando and is being used in production for over two years.

Installation

Clone the repository

mkdir tmp
git clone https://github.com/zalando/postgres-operator.git tmp/zalando-postgres-operator
git -C tmp/zalando-postgres-operator checkout v1.2.0

Install the PostgreSQL Operator:

helm install --name zalando --namespace zalando tmp/zalando-postgres-operator/charts/postgres-operator \
  --set configKubernetes.cluster_domain=${MY_DOMAIN} \
  --set configLoadBalancer.db_hosted_zone=db.${MY_DOMAIN}

Create a Postgres cluster:

cat << EOF | kubectl apply -f -
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
  name: myteam-mytest-cluster5
  namespace: default
spec:
  teamId: "myteam"
  volume:
    size: 1Gi
  numberOfInstances: 2
  users:
    myuser:           # database owner
    - superuser
    - createdb
    # mytestdb_user: []
  enableMasterLoadBalancer: false
  enableReplicaLoadBalancer: false
  databases:
    mytestdb: myuser  # dbname: owner
  postgresql:
    version: "10"
EOF

Check the deployed cluster:

kubectl describe postgresql

Check created database pods and services:

kubectl get pods,svc -l application=spilo -L spilo-role

Allow access to the database using Istio:

cat << EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: pgsql-myteam-mytest-cluster-gateway
  namespace: default
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 5432
      name: pgsql-myteam-mytest-cluster
      protocol: TCP
    hosts:
    - pgsql.${MY_DOMAIN}
  - port:
      number: 5433
      name: pgsql-repl-myteam-mytest-cluster
      protocol: TCP
    hosts:
    - pgsql.${MY_DOMAIN}
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: pgsql-myteam-mytest-virtual-service
  namespace: default
spec:
  hosts:
  - pgsql.${MY_DOMAIN}
  gateways:
  - pgsql-myteam-mytest-cluster-gateway
  tcp:
  - match:
    - port: 5432
    route:
    - destination:
        host: myteam-mytest-cluster.default.svc.cluster.local
        port:
          number: 5432
  - match:
    - port: 5433
    route:
    - destination:
        host: myteam-mytest-cluster-repl.default.svc.cluster.local
        port:
          number: 5432
EOF
export PGHOST=pgsql.${MY_DOMAIN}
export PGPORT=5432
export PGPASSWORD=$(kubectl get secret postgres.myteam-mytest-cluster.credentials -o 'jsonpath={.data.password}' | base64 -d)
psql -U postgres