Deploy PostgreSQL on Kubernetes cluster

Install kubernetes cluster, follow below article if you don’t have one

Create and deploy configmap for PostgreSQL

Create postgres configmap file
# postgres-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-secret
  labels:
    app: postgres
data:
  POSTGRES_DB: yourdb
  POSTGRES_USER: yourusername
  POSTGRES_PASSWORD: yourpassword
Deploy postgres configmap file
# create-configmap.sh
kubectl apply -f postgres-configmap.yaml

# Verify your change
kubectl get configmap

# Sample output
NAME               DATA   AGE
kube-root-ca.crt   1      3d1h
postgres-secret    3      7s

Create PersistentVolume (PV) and PersistentVolumeClaim (PVC)

Create persistent volume for postgresql
# postgres-volume.yaml
apiVersion: v1
kind: PersistentVolume # Create PV 
metadata:
  name: postgres-volume # Sets PV name
  labels:
    type: local # Sets PV's type
    app: postgres
spec:
  storageClassName: manual
  capacity:
    storage: 100Gi # Sets PV's size
  accessModes:
    - ReadWriteMany
  hostPath:
    path: "/home/username/data/postgresql" # Sets PV's host path
Deploy and verify your change
# create-postgres-volume.sh
kubectl apply -f postgres-volume.yaml

# Verify PV
kubectl get pv
# Sample output
NAME              CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
postgres-volume   100Gi      RWX            Retain           Available           manual                  5s
Create persistent volume claim for postgres
# postgres-volume-claim.yaml
apiVersion: v1
kind: PersistentVolumeClaim # Create PVC
metadata:
  name: postgres-volume-claim # Sets PVC's name
  labels:
    app: postgres # Defines app to create PVC for
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi # Sets PVC's size
Deploy your change
# create-postgres-volume-claim.sh
kubectl apply -f postgres-volume-claim.yaml

# Verify
kubectl get pvc
# Sample output
NAME                    STATUS   VOLUME            CAPACITY   ACCESS MODES   STORAGECLASS   AGE
postgres-volume-claim   Bound    postgres-volume   100Gi      RWX            manual         6s

Create PostgreSQL Deployment and Service

Create and deploy postgres deployment
# postgres-deployment.yaml
apiVersion: apps/v1
kind: Deployment # Create a deployment
metadata:
  name: postgres # Set the name of the deployment
spec:
  replicas: 1 # Set 1 deployment replicas
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:12.10 # Docker image
          imagePullPolicy: "IfNotPresent"
          ports:
            - containerPort: 5432 # Exposing the container port 5432 for PostgreSQL client connections.
          envFrom:
            - configMapRef:
                name: postgres-secret # Using the ConfigMap postgres-secret
          volumeMounts:
            - mountPath: /var/lib/postgresql/data
              name: postgresdata
      volumes:
        - name: postgresdata
          persistentVolumeClaim:
            claimName: postgres-volume-claim
Deploy postgres deployment
# create postgres-deployment.sh
kubectl apply -f postgres-deployment.yaml

# Verify your change
kubectl get pods
# Sample output
NAME                                       READY   STATUS    RESTARTS   AGE
postgres-9db8ff595-tffgz                   1/1     Running   0          39s
Create and deploy postgres service
# postgres-service.yaml
apiVersion: v1
kind: Service # Create service
metadata:
  name: postgres # Sets the service name
  labels:
    app: postgres # Defines app to create service for
spec:
  type: NodePort # Sets the service type
  ports:
    - port: 5432 # Sets the port to run the postgres application
      nodePort: 30432 # Node port for external access by clients
  selector:
    app: postgres
Deploy service
# create-postgres-service.sh
kubectl apply -f postgres-service.yaml

# Verify your change
kubectl get services
# Sample output
NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes                ClusterIP   10.96.0.1        <none>        443/TCP          3d1h
postgres                  NodePort    10.96.228.238    <none>        5432:30432/TCP   7s

Verify and test PostgreSQL via kubectl Command

# user kubectl exec to access your pod and postgres database
kubectl exec -it postgres-xxxx -- psql -h localhost -U yourusername --password -p 5432 yourdb

# Type your password and sample output
Password: 
psql (12.10 (Debian 12.10-1.pgdg110+1))
Type "help" for help.

yourdb=# 

Reference: https://adamtheautomator.com/postgres-to-kubernetes/