Databases 5 min read

Automate MySQL Backups with Kubernetes CronJob: A Step‑by‑Step Guide

This article explains how to centralize MySQL backup management on Kubernetes by creating a dedicated namespace, PVC, and CronJob, then shows commands to monitor jobs and restore databases from compressed backup files, providing a complete, repeatable solution for DBAs.

DevOps Operations Practice
DevOps Operations Practice
DevOps Operations Practice
Automate MySQL Backups with Kubernetes CronJob: A Step‑by‑Step Guide

Backup Procedure

Create a dedicated namespace for backup resources: kubectl create namespace mysql-backup Define a PersistentVolumeClaim (PVC) to store backup files. Adjust storageClassName to match the cluster configuration.

# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-backup-pvc
  namespace: mysql-backup
  labels:
    app: mysql-backup
spec:
  storageClassName: "nfs-client"
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Gi

Create the PVC: kubectl create -f pvc.yaml Deploy a CronJob that runs daily, dumps all MySQL databases, compresses the dump, and retains backups for seven days.

# cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: mysql-backup-01
  namespace: mysql-backup
spec:
  schedule: "0 2 * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 7
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      backoffLimit: 3
      template:
        spec:
          restartPolicy: Never
          containers:
          - name: mysql-backup
            image: mysql:8.0.43
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - |
              BACKUP_DIR="/backup/mysql-backup"
              BACKUP_FILE="${BACKUP_DIR}/mysql-backup-01-$(date +%Y%m%d%H%M%S).sql.gz"
              RETENTION_DAYS=7
              mkdir -p ${BACKUP_DIR}
              mysqldump -h mysql.mysql-backup -u root -p123456 \
                --all-databases --single-transaction --quick --lock-tables=false \
                | gzip > ${BACKUP_FILE}
              if [ -f ${BACKUP_FILE} ]; then
                echo "Backup succeeded: ${BACKUP_FILE}"
                find ${BACKUP_DIR} -name "mysql-backup-01-*.sql.gz" -mtime +${RETENTION_DAYS} -delete
                echo "Deleted backups older than ${RETENTION_DAYS} days"
              else
                echo "Backup failed: file not created"
                exit 1
              fi
            volumeMounts:
            - name: backup-storage
              mountPath: /backup
          volumes:
          - name: backup-storage
            persistentVolumeClaim:
              claimName: mysql-backup-pvc

Create the CronJob: kubectl create -f cronjob.yaml Monitor the resources:

kubectl get cronjob -n mysql-backup
kubectl get jobs -n mysql-backup

Restore Procedure

Decompress a backup file: gzip -d mysql-backup-01-20260303092641.sql.gz Copy the resulting .sql file into the target MySQL pod and run the restore command. Replace the placeholders with the actual host, user, password, and database name.

mysql -h <host> -u <user> -p<password> --one-database <database> < mysql-backup-01-20260303092641.sql

This approach centralizes MySQL backup scheduling, retention, and recovery using native Kubernetes resources.

KubernetesMySQLBackupCronJobDatabase AdministrationPVC
DevOps Operations Practice
Written by

DevOps Operations Practice

We share professional insights on cloud-native, DevOps & operations, Kubernetes, observability & monitoring, and Linux systems.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.