Automate PostgreSQL Database Backups in Kubernetes with CronJobs and Azure File Share

Tired of manually backing up your PostgreSQL database? Automate the process using Kubernetes CronJobs, ConfigMaps, Persistent Volumes, and a lightweight PostgreSQL client Docker image.

In this step-by-step guide, you’ll learn how to:

✅ Create a Docker image with postgresql-client to perform backups.

✅ Use Kubernetes ConfigMaps to manage your backup script.

✅ Set up Persistent Volumes (PV & PVC) for storage.

✅ Automate backups using CronJobs with retention policies.


🛠 Prerequisites

Before getting started, ensure you have:

✔ A Kubernetes cluster on Azure Kubernetes Service (AKS) or another Kubernetes environment.

✔ kubectl installed and configured.

✔ A running PostgreSQL database in Kubernetes.

✔ Azure CLI installed for managing Azure resources.

✔ Docker installed to build and push images.

✔ A DockerHub or private container registry to store the backup image.

✔ Azure File Share created for storing backups persistently.

💡 Azure File Share will be used as persistent storage for backups.

Let’s get started! 🚀


💡 Why Automate PostgreSQL Backups?

Manual backups are risky — you might forget, or worse, data loss could occur before you act. With this Kubernetes-native solution, backups run automatically on a schedule, ensuring:

Reliability — No missed backups!

Security — Stored in Persistent Volumes (PVC).

Efficiency — Old backups are deleted after 7 days.


🔧 Step 1: Build & Push the PostgreSQL Backup Docker Image

We’ll create a lightweight Docker image that only installs postgresql-client. This avoids unnecessary overhead from a full PostgreSQL installation.

📌 Dockerfile

# Use the official Ubuntu base image
FROM ubuntu:latest  
# Install PostgreSQL client
RUN apt-get update && \
    apt-get install -y postgresql-client && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*  
# Set default command  
CMD ["psql", "--version"]

🛠 Build & Push the Image

docker build -t your-dockerhub-username/postgres-backup:latest .
docker push your-dockerhub-username/postgres-backup:latest

🔹 Replace your-dockerhub-username with your actual DockerHub username.

Step 2: Create Persistent Storage for Backups (PV & PVC)

We’ll store backups in an Azure File Share-backed Persistent Volume (PV & PVC).

📌 PersistentVolume (PV)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgresql-backup-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  azureFile:
    secretName: ""  # Add your secret here
    secretNamespace: "" 
    shareName: ""  # Add your Azure File Share name here
    readOnly: false

📌 PersistentVolumeClaim (PVC)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgresql-backup-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  volumeName: postgresql-backup-pv

🔹 Modify shareName and secretName based on your Azure setup.

Apply these:

kubectl apply -f pv.yaml
kubectl apply -f pvc.yaml

📜 Step 3: Create ConfigMap for Backup Script

We need to mount the backup.sh script inside the CronJob container. Instead of hardcoding it, let’s use a ConfigMap.

📌 backup.sh (Backup Script)

#!/bin/bash
NAMESPACE=${NAMESPACE:-"default"}
POSTGRES_SVC=${POSTGRES_SVC}
POSTGRES_USER=${POSTGRES_USER}
POSTGRES_DB=${POSTGRES_DB}
BACKUP_DIR="/backup"
DATE=$(date +"%Y-%m-%d")
BACKUP_FILE="${BACKUP_DIR}/${POSTGRES_DB}_${DATE}.sql"
TAR_FILE="${BACKUP_DIR}/${POSTGRES_DB}_${DATE}.tar.gz"
POSTGRES_PASS=${POSTGRES_PASS}
# Perform the backup
PGPASSWORD="$POSTGRES_PASS" pg_dump -h "$POSTGRES_SVC" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -F c -f "$BACKUP_FILE"
# Compress the backup
if [ $? -eq 0 ]; then
  tar -czf "$TAR_FILE" -C "$BACKUP_DIR" "$(basename "$BACKUP_FILE")"
  rm -f "$BACKUP_FILE"
  echo "Backup completed: $TAR_FILE"
else
  echo "Backup failed!"
  exit 1
fi
# Delete backups older than 7 days
find "$BACKUP_DIR" -type f -name "${POSTGRES_DB}_*.tar.gz" -mtime +7 -exec rm -f {} \;

📌 Create ConfigMap

kubectl create configmap backup-script --from-file=backup.sh
🔹 This mounts backup.sh in the CronJob without modifying the container.

⏳ Step 4: Automate Backups with a Kubernetes CronJob

The CronJob runs the backup script every night at 12:30 AM(UTC).

📌 CronJob YAML

apiVersion: batch/v1
kind: CronJob
metadata:
  name: postgresql-backup
spec:
  schedule: "30 0 * * *"  # Runs daily at 12:30 AM UTC
  successfulJobsHistoryLimit: 1
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: postgresql-backup
              image: your-dockerhub-username/postgres-backup:latest   #update the values
              imagePullPolicy: IfNotPresent
              command: ["/bin/sh", "-c"]
              args:
                - |
                  cp /scripts/backup.sh /tmp/backup.sh
                  chmod +x /tmp/backup.sh
                  until pg_isready -h "$POSTGRES_SVC" -U "$POSTGRES_USER"; do
                    echo "Waiting for PostgreSQL to be ready..."
                    sleep 5
                  done
                  echo "Running backup script..."
                  /tmp/backup.sh
              env:
                - name: POSTGRES_SVC
                  value: "your-postgres-service"   #update the values
                - name: POSTGRES_USER
                  valueFrom:
                    secretKeyRef:
                      name: your-secret        #update the values
                      key: POSTGRES_USER
                - name: POSTGRES_PASS
                  valueFrom:
                    secretKeyRef:
                      name: your-secret        #update the values
                      key: POSTGRES_PASSWORD
                - name: POSTGRES_DB
                  value: "your-database"       #update the values
              volumeMounts:
                - name: backup
                  mountPath: /backup
                - name: script-volume
                  mountPath: /scripts
          restartPolicy: OnFailure
          volumes:
            - name: backup
              persistentVolumeClaim:
                claimName: postgresql-backup-pvc
            - name: script-volume
              configMap:
                name: backup-script

🔹 Replace your-dockerhub-username and your-postgres-service with actual values.

🛠 Apply CronJob

kubectl apply -f cronjob.yaml

🚀 Wrapping Up

Congratulations! 🎉 You have successfully automated PostgreSQL backups on Kubernetes using:

✔ Dockerized PostgreSQL client for backup execution.

✔ ConfigMaps to manage scripts.

✔ Persistent Storage (PV & PVC) to retain backups.

✔ CronJobs to schedule automated backups.

💬 What’s Next?

Want to take your PostgreSQL backup automation to the next level?

Hire me on Fiverr for customized solutions tailored to your needs!

Have any questions or improvements? Drop a comment below!
🔥 Have you automated PostgreSQL backups yet? Let me know in the comments! 🚀