Severalnines Blog
The automation and management blog for open source databases

Using Kubernetes to Deploy PostgreSQL

Introduction

Kubernetes is an open source container orchestration system for automating deployment, scaling and management of containerized applications. Running a PostgreSQL database on Kubernetes is a topic of discussion nowadays as Kubernetes provides ways to provision stateful container using persistent volumes, statefulsets, etc.

This blog intended to provide steps to run PostgreSQL database on Kubernetes cluster. It doesn’t cover the installation or configuration of Kubernetes cluster, although we previously wrote about it in this blog on MySQL Galera Cluster on Kubernetes.

Prerequisites

  • Working Kubernetes Cluster
  • Basic understanding of Docker

You can provision the Kubernetes cluster on any public cloud provider like AWS, Azure or Google cloud, etc. Refer Kubernetes cluster installation and configuration steps for CentOS here. You can also check the earlier blog post for basics about Deploying PostgreSQL on Docker container.

To Deploy PostgreSQL on Kubernetes we need to follow below steps:

  • Postgres Docker Image
  • Config Maps for storing Postgres configurations
  • Persistent Storage Volume
  • PostgreSQL Deployment
  • PostgreSQL Service

PostgreSQL Docker Image

We are using PostgreSQL 10.4 Docker image from the public registry. This image will provide the functionality of providing custom configurations/environment variables of PostgreSQL like username, password, database name and path, etc.

Config Maps for PostgreSQL Configurations

We will be using config maps for storing PostgreSQL related information. Here, we are using the database, user and password in the config map which will be used by the PostgreSQL pod in the deployment template.

File: postgres-configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-config
  labels:
    app: postgres
data:
  POSTGRES_DB: postgresdb
  POSTGRES_USER: postgresadmin
  POSTGRES_PASSWORD: admin123

Create Postgres config maps resource

$ kubectl create -f postgres-configmap.yaml 
configmap "postgres-config" created

Persistent Storage Volume

As you all know that Docker containers are ephemeral in nature. All the data which is generated by or in the container will be lost after termination of the container instance.

To save the data, we will be using Persistent volumes and persistent volume claim resource within Kubernetes to store the data on persistent storages.

Here, we are using local directory/path as Persistent storage resource (/mnt/data)

File: postgres-storage.yaml

kind: PersistentVolume
apiVersion: v1
metadata:
  name: postgres-pv-volume
  labels:
    type: local
    app: postgres
spec:
  storageClassName: manual
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteMany
  hostPath:
    path: "/mnt/data"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: postgres-pv-claim
  labels:
    app: postgres
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

Create storage related deployments

$ kubectl create -f postgres-storage.yaml 
persistentvolume "postgres-pv-volume" created
persistentvolumeclaim "postgres-pv-claim" created

PostgreSQL Deployment

PostgreSQL manifest for deployment of PostgreSQL container uses PostgreSQL 10.4 image. It is using PostgreSQL configuration like username, password, database name from the configmap that we created earlier. It also mounts the volume created from the persistent volumes and claims to make PostgreSQL container’s data persists.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: postgres
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:10.4
          imagePullPolicy: "IfNotPresent"
          ports:
            - containerPort: 5432
          envFrom:
            - configMapRef:
                name: postgres-config
          volumeMounts:
            - mountPath: /var/lib/postgresql/data
              name: postgredb
      volumes:
        - name: postgredb
          persistentVolumeClaim:
            claimName: postgres-pv-claim

Create Postgres deployment

$ kubectl create -f postgres-deployment.yaml 
deployment "postgres" created
Download the Whitepaper Today
 
PostgreSQL Management & Automation with ClusterControl
Learn about what you need to know to deploy, monitor, manage and scale PostgreSQL

PostgreSQL Service

To access the deployment or container, we need to expose PostgreSQL service. Kubernetes provides different type of services like ClusterIP, NodePort and LoadBalancer.

With ClusterIP we can access PostgreSQL service within Kubernetes. NodePort gives the ability to expose service endpoint on the Kubernetes nodes. For accessing PostgreSQL externally, we need to use a Load Balancer service type which exposes the service externally.

File: postgres-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: postgres
  labels:
    app: postgres
spec:
  type: NodePort
  ports:
   - port: 5432
  selector:
   app: postgres

Create Postgres Service

$ kubectl create -f postgres-service.yaml 
service "postgres" created

Connect to PostgreSQL

For connecting PostgreSQL, we need to get the Node port from the service deployment.

$ kubectl get svc postgres
NAME       TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
postgres   NodePort   10.107.71.253   <none>        5432:31070/TCP   5m

We need to use port 31070 to connect to PostgreSQL from machine/node present in kubernetes cluster with credentials given in the configmap earlier.

$ psql -h localhost -U postgresadmin1 --password -p 31070 postgresdb
Password for user postgresadmin1: 
psql (10.4)
Type "help" for help.
 
postgresdb=#

Delete PostgreSQL Deployments

For deletion of PostgreSQL resources, we need to use below commands.

# kubectl delete service postgres 
# kubectl delete deployment postgres
# kubectl delete configmap postgres-config
# kubectl delete persistentvolumeclaim postgres-pv-claim
# kubectl delete persistentvolume postgres-pv-volume

Hopefully, by using the above steps you are able to provision a standalone PostgreSQL instance on a Kubernetes Cluster.

Conclusion

Running PostgreSQL on Kubernetes help to utilize resources in a better way than when just using virtual machines. Kubernetes also provides isolation of other applications using PostgreSQL within the same virtual machine or Kubernetes cluster.

This article provides an overview about how we can use PostgreSQL on Kubernetes for development/POC environment. You may explore/setup PostgreSQL cluster using statefulsets of Kubernetes.

StatefulSets required?

In Kubernetes, StatefulSets are required to scale stateful applications. PostgreSQL can be easily scaled using StatefulSets with a single command.

References