28 Apr 2019

Running PostgreSQL in a Cloud on Oracle Containers Engine for Kubernetes

In this post I am going to show a few steps to deploy and run PostgreSQL database in a K8S cluster on OKE.

The deployment is going to be based on postgres:11.1 Docker image which requires a few environment variables to be configured: POSTGRES_DB (database name), POSTGRES_USER and POSTGRES_PASSWORD. I am going to store values of these variables in K8S ConfigMap and Secret:
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgre-db-config
data:
  db-name: flexdeploy

apiVersion: v1
kind: Secret
metadata:
  name: postgre-db-secret
stringData:
  username: creator
  password: c67

These configuration K8S resources are referenced by the StatefulSet which actually takes care of the lifespan of a pod with postgres-db container:
apiVersion: apps/v1beta2
kind: StatefulSet
metadata:
  name: postgre-db
  labels:
    run: postgre-db
spec:
  selector:
      matchLabels:
        run: postgre-db
  serviceName: "postgre-db-svc"
  replicas: 1
  template:
    metadata:
      labels:
        run: postgre-db
    spec:
      containers:
      - image: postgres:11.1
        volumeMounts:
           - mountPath: /var/lib/postgresql/data
             name: db     
        env:
          - name: POSTGRES_DB
            valueFrom:
              configMapKeyRef:
                   name: postgre-db-config
                   key: db-name                  
          - name: POSTGRES_USER
            valueFrom:
              secretKeyRef:
                   name: postgre-db-secret
                   key: username                  
          - name: POSTGRES_PASSWORD
            valueFrom:
              secretKeyRef:
                   name: postgre-db-secret
                   key: password                  
          - name: PGDATA
            value: /var/lib/postgresql/data/pgdata           
        name: postgre-db
        ports:
        - containerPort: 5432
  volumeClaimTemplates:
   - metadata:
       name: db
     spec:
       accessModes: [ "ReadWriteOnce" ]
       resources:
         requests:
           storage: 3Gi  


StatefulSet K8S resource has been specially designed for stateful applications like database that save their data to a persistent storage. In order to define a persistent storage for our database we use another K8s resource Persistent Volume and here in the manifest file we are defining a claim to create a 3Gi Persistent Volume with name db. The volume is called persistent because its lifespan is not maintained by a container and not even by a pod, it’s maintained by a K8s cluster. So it can outlive any containers and pods and save the data. Meaning that if we kill or recreate a container or a pod or even the entire StatefulSet, the data will be still there. We are referring to this persistence volume in the container definition mounting a volume on path /var/lib/postgresql/data. This is where PostgreSQL container stores its data.

In order to access the database we are going to create a service:
apiVersion: v1
kind: Service
metadata:
  name: postgre-db-svc 
spec:
  selector:
    run: postgre-db
  ports:
    - port: 5432
      targetPort: 5432 
  type: LoadBalancer   

This is a LoadBalancer service which is accessible from outside of the K8S cluster:
$ kubectl get svc postgre-db-svc
NAME             TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)          AGE
postgre-db-svc   LoadBalancer   10.96.177.34   129.146.211.77   5432:32498/TCP   39m

Assuming that we have created a K8s cluster on OKE and our kubectl is configured to communicate with it we can apply the manifest files to the cluster:
kubectl apply -f postgre-db-config.yaml
kubectl apply -f postgre-db-secret.yaml
kubectl apply -f postgre-db-pv.yaml
kubectl apply -f postgre-db-service.yaml

Having done that, we can connect to the database from our favorite IDE on our laptop

The manifest files for this post are available on GitHub.

That's it!

No comments:

Post a Comment

Post Comment