How to Deploy Postgres to Kubernetes

Published:27 April 2022 - 11 min. read

Arvid Larson Image

Arvid Larson

Read more tutorials by Arvid Larson!

Azure Cloud Labs: these FREE, on‑demand Azure Cloud Labs will get you into a real‑world environment and account, walking you through step‑by‑step how to best protect, secure, and recover Azure data.

Deploying PostgreSQL with container technology can be challenging, especially in complicated environments, like Kubernetes. But no worries, this tutorial got you covered, so you can securely deploy PostgreSQL to Kubernetes.

In this tutorial, you will learn how to install and deploy PostgreS to Kubernetes environment in two different ways, using Helm charts and using manual YAML configurations.

Prerequisites

This tutorial will be a hands-on demonstration. To follow along, be sure you have the following:

  • Helm installed on your local machine.
  • kubectl tool installed on your local machine.
  • A Linux client machine.

Deploying PostgreSQL with Helm Chart

Helm is the package manager for Kubernetes that allows you to deploy applications to Kubernetes in no time. Helm simplifies the application deployment complexity on Kubernetes and comes with quick update features, sharing of charts, and rollbacks feature.

Learn how to deploy PostgreSQL to Kubernetes using the Helm repository as your template in the following sections.

Adding a Helm Chart Repository

Many available Helm repositories you can use to deploy PostgreSQL to Kubernetes. But this tutorial uses the Helm repository provided by Bitnami.

For the complete list of available Helm repositories, visit Artifacthub.io.

Open your terminal, and run the helm commands below to add the Bitnami helm repository to your system and refresh the index chart of the Helm repository.

# Add Helm repository by Bitnami
helm repo add bitnami <https://charts.bitnami.com/bitnami>

# Update Helm index charts
helm repo update
Updating and Refreshing Helm Index Charts
Updating and Refreshing Helm Index Charts

Now run the helm command below to verify the list of available Helm repositories on your system.

helm repo lists

You should get the Bitnami Helm repository available on your system, as shown below.

Verifying Repository
Verifying Repository

Creating a PersistentVolume (PV) and a PersistentVolumeClaim (PVC)

You’ve now added the Bitnami Helm repository to your system. But before deploying your PostgreSQL, you’ll need a place for storing PostgreSQL data permanently.

You’ll create the PersistentVolume (PV) and PersistentVolumeClaim (PVC) on Kubernetes:

  • PV – is a Kubernetes resource for storing data of your applications.

There are multiple types of PV supported by Kubernetes. These PV types include local directory and third-party cloud storage providers, such as Amazon EBS and AzureDisk.

  • PVC – is the way your application uses a given PV. PVC is used to mount a PV to your application’s pod.

To create persistent storage:

1. Create a new YAML configuration (local-pv.yaml) file with your preferred editor and populate the following configuration.

The configuration below creates a new PV named postgresql-data on Kubernetes with the PV’s type as local. Be sure to change the storage capacity with your need and the path with your local directory.

apiVersion: v1
kind: PersistentVolume # Create a PV
metadata:
  name: postgresql-data # Sets PV's name
  labels:
    type: local # Sets PV's type to local
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi # Sets PV Volume
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/data/volume" # Sets the volume's path

2. Next, run the kubectl apply command below to apply the configuration in the local-pv.yaml file to Kubernetes.

kubectl apply -f local-pv.yaml

3. Create another YAML configuration file (pv-claim.yaml) and populate the following configuration.

The below configuration creates a PVC named postgresql-data-claim with the size of 10GB.

apiVersion: v1
kind: PersistentVolumeClaim # Create PVC
metadata:
  name: postgresql-data-claim # Sets name of PV
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce # Sets read and write access
  resources:
    requests:
      storage: 10Gi # Sets volume size

4. Now, run the kubectl command below to apply the pv-claim.yaml configuration.

kubectl apply -f pv-claim.yaml

5. Lastly, run each command below to verify the PV and PVC on your Kubernetes.

# Checking PersistentVolume
kubectl get pv

# Checking PersistentVolumeClaim
kubectl get pvc

If your configurations are correct, you’ll see an output similar to below. The PV (postgresql-data) is bounded to the PVC (postgresql-data-claim) and vice-versa.

Verifying PersistentVolume (PV) and PersistentVolumeClaim (PVC)

Creating a Custom Configuration

You’ve now created the PV and PVC on your Kubernetes for permanently storing data. But how about your PostgreSQL secrets?

Typically, you wouldn’t want sensitive information lying around, so you’ll create a custom configuration. A custom configuration lets you store PostgreSQL secrets and add the postgresql-data-claim PVC to the PostgreSQL deployment for storing data permanently.

1. Create a new configuration file (values.yaml) using your preferred editor and populate the following configuration.

The below configuration deploys the PostgreSQL to Kubernetes, creating a new database called app_db and a new user named app1 with a password (StrongPassword).

# define default database user, name, and password for PostgreSQL deployment
auth:
  enablePostgresUser: true
  postgresPassword: "StrongPassword"
  username: "app1"
  password: "AppPassword"
  database: "app_db"

# The postgres helm chart deployment will be using PVC postgresql-data-claim
primary:
  persistence:
    enabled: true
    existingClaim: "postgresql-data-claim"

Deploying PostgreSQL to Kubernetes

You’ve completed setting up your resources, but they’re not doing much unless you deploy your PostgreSQL data to Kubernetes. You’ll start the PostgreSQL deployment to Kubernetes using the Bitnami Helm chart.

Run the helm install command below to deploy PostgreSQL to Kubernetes with the name postgresql-dev using the Bitnami Helm chart (bitnami/postgresql).

helm install postgresql-dev -f values.yaml bitnami/postgresql

After deployment, you’ll get an output like the screenshot below. As you can see, postgresql-dev is deployed to the Kubernetes with the default PostgreSQL version 14.1.0.

Notice that you also get messages on how to connect to the PostgreSQL pod.

Deploying PostgreSQL to Kubernetes using Helm

Now, run the kubectl commands below to check the PostgreSQL pod and pod’s logs. Be sure to change postgresql-dev-0 with your pod.

# Checking pods
kubectl get pods

# Checking logs of pods
kubectl logs postgresql-dev-0

As you can see below, the pod (postgresql-dev-0STATUS is running. And at the bottom of pod logs, you’ll see the message database system is ready to accept connections. This message indicates the PostgreSQL deployment is complete.

5-check-deployment
5-check-deployment

Connecting to PostgreSQL

At this point, you’ve completed the PostgreSQL deployment on Kubernetes. But how do you connect to the PostgreSQL database for managing the database itself?

You’ll connect to the PostgreSQL database on Kubernetes using a temporary pod. The temporary pod will automatically be deleted when the pod exits.

1. Run the below export command to create the POSTGRES_PASSWORD environment variable, which contains the password for the PostgreSQL database (app_db).

This command doesn’t have an output, but you’ll verify the PostgreSQL connection in the following steps.

export POSTGRES_PASSWORD=$(kubectl get secret --namespace default postgresql-dev -o jsonpath="{.data.password}" | base64 --decode)

2. Next, run the kubectl run command below to connect to the PostgreSQL database (app_db).

This command creates a new temporary pod called postgresql-dev-client that connects to the PostgreSQL database (app_db) with the user app1.

kubectl run postgresql-dev-client --rm --tty -i --restart='Never' --namespace default --image docker.io/bitnami/postgresql:14.1.0-debian-10-r80 --env="PGPASSWORD=$POSTGRES_PASSWORD" \
--command -- psql --host postgresql-dev -U app1 -d app_db -p 5432
Connecting to PostgreSQL Database
Connecting to PostgreSQL Database

3. Lastly, run the following PostgreSQL query to verify your connection to the PostgreSQL database.

# Checking PostgreSQL connection
\conninfo

# Logout from PostgreSQL shell
exit

Below, you can see that you’re connected to the PostgreSQL database (app_db) inside Kubernetes using the database user app1.

Notice that when you log out from the PostgreSQL shell, the pod postgresql-dev-client is deleted.

Connecting to PostgreSQL on Kubernetes and Verifying Connection
Connecting to PostgreSQL on Kubernetes and Verifying Connection

Deploying PostgreSQL to Kubernetes Manually

You’ve seen how to deploy PostgreSQL using a Helm chart as your template, so why choose manual deployment? The advantage of deploying PostgreSQL to Kubernetes manually is that it gives you a more in-depth understanding of application deployment on the Kubernetes environment.

You’ll create some Kubernetes resources required to manually deploy the PostgreSQL to Kubernetes.

Creating a ConfigMap to Store Database Details

Deploying PostgreSQL to Kubernetes manually requires some Kubernetes resources. One of those resources is a ConfigMap, an API object you’ll use to store key-value pairs.

You’ll create a Kubernetes ConfigMap to store database details such as user, database name, and password for the PostgreSQL deployment.

For the production environment, deploying secrets such as password authentication using the Kubernetes secret is highly recommended for security.

1. Create a new YAML configuration file (postgres-configmap.yaml) and populate the following configuration. The configuration below creates a ConfigMap named postgres-secret for the postgres application and a database called appdb.

You can set the database details with your preferred ones. But for this tutorial, the user is set as appuser and the password as strongpassword.

# Create ConfigMap postgres-secret for the postgres app
# Define default database name, user, and password
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-secret
  labels:
    app: postgres
data:
  POSTGRES_DB: appdb
  POSTGRES_USER: appuser
  POSTGRES_PASSWORD: strongpasswordapp

2. Now run the kubectl command below to apply the configuration in the postgres-configmap.yaml file.

kubectl apply -f postgres-configmap.yaml
Applying the postgres-configmap.yaml Configuration to Create a ConfigMap
Applying the postgres-configmap.yaml Configuration to Create a ConfigMap

3. Lastly, run the below command to get the list of ConfigMaps on your Kubernetes.

kubectl get configmap

You’ll see the postgres-secret ConfigMap on the list, as shown below.

Checking Kubernetes ConfigMap
Checking Kubernetes ConfigMap

Creating PersistentVolume (PV) and PersistentVolumeClaim (PVC)

Like deploying PostgreSQL with Helm chart, you’ll also create a PV and PVC for manual deployment to store PostgreSQL data on your Kubernetes host permanently.

1. Create a new YAML configuration file (postgres-volume.yaml) and populate the following configuration.

The configuration below creates a new PV called postgres-volume with a type as local on the Kubernetes host.

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: 10Gi # Sets PV's size
  accessModes:
    - ReadWriteMany
  hostPath:
    path: "/data/postgresql" # Sets PV's host path

2. Next, run the kubectl command below to apply the postgres-volume.yaml file’s configuration.

kubectl apply -f postgres-volume.yaml
Applying the postgres-volume.yaml Configuration to Create a PV
Applying the postgres-volume.yaml Configuration to Create a PV

3. Create another configuration file (postgres-pvc.yaml) and populate the following configuration.

This configuration creates the PVC called postgres-volume-claim for your PostgreSQL deployment.

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

4. Now run the following command to apply the postgres-pvc.yaml file’s configuration.

kubectl apply -f postgres-pvc.yaml
Applying the postgres-pvc.yaml Configuration to Create a PVC
Applying the postgres-pvc.yaml Configuration to Create a PVC

5. Lastly, run each command below to verify all available PV and PVC on your Kubernetes.

# Get list of PersistentVolume
kubectl get pv

# Get list of PersistentVolumeClaim
kubectl get pvc

You should see the postgres-volume PV  and the postgres-volume-pvc PVC with the status Bound to each other like the screenshot below.

Verifying PV and PVC on Kubernetes
Verifying PV and PVC on Kubernetes

Creating PostgreSQL Deployment

You’ve created a PersistentVolume and PersistentVolumeClaim for the PostgreSQL deployment. Now it’s time to create a PostgreSQL deployment and declare Pods configuration for the PostgreSQL in Kubernetes.

1. Create a new YAML file for the PostgreSQL deployment called postgres-deployment.yaml using your preferred editor and populate the following configuration.

apiVersion: apps/v1
kind: Deployment # Create a deployment
metadata:
  name: postgres # Set the name of the deployment
spec:
  replicas: 3 # Set 3 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

2. Next, run the kubectl command below to apply the postgres-deployment.yaml configuration to create the PostgreSQL deployment.

This command will download Docker images postgres:12.10 for your deployment and create three pods replicas.

kubectl apply -f postgres-deployment.yaml
Applying postgres-deployment.yaml Configuration to Create the PostgreSQL Deployment
Applying postgres-deployment.yaml Configuration to Create the PostgreSQL Deployment

3. Run the kubectl command below to verify the list of running pods and deployments on your Kubernetes.

# checking Kubernetes deployment
kubectl get deployments

# checking pods
kubectl get pods

Below is the screenshot of pods in creating status. The STATUS of all pods is still on the ContainerCreating process.

Viewing ContainerCreating for the PostgreSQL Deployment
Viewing ContainerCreating for the PostgreSQL Deployment

After the deployment process completes, you’ll see the STATUS of all pods is Running.

Viewing Completed PostgreSQL Deployment on Kubernetes
Viewing Completed PostgreSQL Deployment on Kubernetes

Creating a Service for PostgreSQL

At this point, you’ve completed the deployment of PostgreSQL on Kubernetes. But how do you let clients connect to the PostgreSQL pod? You’ll expose PostgreSQL outside of the Kubernetes environment by creating and running a Kubernetes service.

1. Create a new YAML configuration file (postgres-service.yaml) and populate the following configuration.

This configuration creates the Kubernetes service with the type as NodePort for the postgres application running on the default port 5432.

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
  selector:
    app: postgres

2. Next, run the kubectl command below to apply the postgres-service.yaml configuration to create a new Kubernetes service.

kubectl apply -f postgres-service.yaml
Applying postgres-service.yaml Configuration to Create New Kubernetes Service
Applying postgres-service.yaml Configuration to Create New Kubernetes Service

3. Lastly, run the kubectl get command below to verify the Kubernetes service.

kubectl get svc

Below, you can see that the postgres service with the type NodePort exposes the port 31398 on the Kubernetes host for the PostgreSQL client connections.

You may have a different port than 31398 because the NodePort is a randomly selected port for your service. The NodePort service will randomly select the port for your service between 30000-32767.

Notice the NodePort 31398 on the Kubernetes host is mapped to PostgreSQL pods on port 5432.

Checking Postgres Kubernetes Service
Checking Postgres Kubernetes Service

Connecting to PostgreSQL via kubectl Command

You’ve created the Kubernetes service resource for the PostgreSQL deployment, and now you’re ready to connect to the PostgreSQL pod. How? You’ll connect to the PostgreSQL shell using the kubectl exec command or the PostgreSQL client on your host.

You can jump to the “Connecting to PostgreSQL via PostgreSQL Client” section if you prefer to use the PostgreSQL client instead.

1. Run the kubectl exec command below to connect to the PostgreSQL pod. Be sure to change the pod name, database name, and the user.

kubectl exec -it postgres-xxxx -- psql -h localhost -U appuser --password -p 5432 appdb

2. Input the password for your database, and you’ll get the PostgreSQL shell like the screenshot below.

12-connect-topostgresql
12-connect-topostgresql

3. Lastly, run the query below to get information about your connection to the PostgreSQL shell and type exit to log out.

\conninfo
Connecting to PostgreSQL pod using kubectl
Connecting to PostgreSQL pod using kubectl

Connecting to PostgreSQL via PostgreSQL Client

If you prefer to connect to the PostgreSQL shell using the PostgreSQL client, run the psql command instead. Be sure the PostgreSQL client packages are installed on your local machine.

1. Run the psql command below to connect to the PostgreSQL pod through the NodePort (31389). Change the IP address 192.168.39.196 with your Kubernetes host IP address and port 31398 with the port of your NodePort resources.

psql -h 192.168.39.196 -U appuser --password -p 31398 appdb

2. Input the password for your database to connect to the PostgreSQL shell.

Connecting to PostgreSQL Pod using PostgreSQL Client
Connecting to PostgreSQL Pod using PostgreSQL Client

3. Finally, run the query below to get information about your connection.

\conninfo

The output below confirms you’ve connected successfully to your PostgreSQL database.

Connecting to PostgreSQL Pod
Connecting to PostgreSQL Pod

Conclusion

In this tutorial, you’ve learned how to deploy a PostgreSQL database to Kubernetes using the Helm chart. You’ve also deployed a PostgreSQL database manually using YAML configuration files. And at this point, you’ve acquired a basic understanding of how to deploy applications to Kubernetes securely.

Now how would you build on this newfound knowledge? Perhaps apply the PostgreSQL High Availability on your Kubernetes?

Hate ads? Want to support the writer? Get many of our tutorials packaged as an ATA Guidebook.

Explore ATA Guidebooks

Looks like you're offline!