Important
This code works, but I never ran it in production for long. The issue it tries to solve (specificall for SQLite Databases) can also be solved with Lightstream or Cron script I'm keeping the repository as an exhibit, you should probably not actually use this.
Easy, simple backup solution for Persistent Volume Claims in your Kubernetes Cluster.
- No components to install into your cluster
- Fully customizable
- Extensive, readable logs for every run
- Fast, secure, efficient backups via restic
- All in one small Docker image:
ghcr.io/lukasknuth/ezbackup
- Helpers to statically generate Job/CronJob
Taking backups of persistent application state while the application is still running is risky because data might not be fully flushed to disk yet. At best the backup is incomplete, at worst it's corrupted.
This is especially true for applications like Databases which are very picky about when they do disk IO to optimize throughput.
A simple solution to this problem is to stop the application before taking the backup. This is where EzBackup can help.
- The EzBackup CLI finds the Pods mounting a given Persistent Volume Claim with write access
- For each Pod it walks the ownership chain to find the owning controller (for example a Deployment)
- All found controllers are scaled down and EzBackup waits for Pod termination
- restic is used to do the actual backup
- All controllers are scaled back up to their original replica count
Since EzBackup uses the Kubernetes API from inside the cluster, the service account used by it's Pod must be allowed to perform certain actions.
A ClusterRole with all required permissions is available in install/001-cluster-role.yaml
. The ClusterRole resource is not namespaced, so it only needs to be created once in the cluster.
Now bind the ClusterRole to a ServiceAccount using a RoleBinding. It's advised to create a new ServiceAccount specific to EzBackup rather than changing the namespaces default ServiceAccount. install/002-account-and-role.yaml
creates both. Note that since these resources are namespaced, you need to customize the file to create the resources in the namespace you intend to use.
Lastly, specify the ServiceAccount to use in the Pod template under spec.serviceAccountName
The actual backup is done by restic. It supports repositories with different storage backends.
NOTE: The Docker image does NOT contain rclone, so repository types supported through it are not available!
The executable is started by EzBackup, no parameters are passed on. However, any environment variables set on the container are passed onto restic.
Usually, you'll want to set at least RESTIC_REPOSITORY
and RESTIC_PASSWORD
. Depending on the repository type, additional variables are required. See the restic documentation for all available options.
Simply start the EzBackup container in a Job:
apiVersion: batch/v1
kind: Job
metadata:
name: backup
namespace: &namespace testing # 1
annotations:
ezbackup.codeisland.org/pvc-name: &pvc-name test-claim # 2
spec:
backoffLimit: 4
template:
spec:
serviceAccountName: ezbackup-automation # 3
restartPolicy: Never
containers:
- name: run-backup
image: ghcr.io/lukasknuth/ezbackup:latest
imagePullPolicy: Always
args: ["backup", *pvc-name, "-n", *namespace]
env:
- name: RESTIC_REPOSITORY
value: "your_repository_here" # 4
- name: RESTIC_PASSWORD
value: "YourVerySavePasswordGoesHere"
volumeMounts:
- name: target
mountPath: /mnt/target # 5
readOnly: true
volumes:
- name: target
persistentVolumeClaim:
claimName: *pvc-name
- The namespace of the Job must match the namespace of the PVC to backup.
- Since we the PVC name multiple times, we use a YAML anchor here to refer to it.
- References the Service Account setup in the "Setup" section.
- Configure the restic repository as described in the "Configuring restic" section. Note: Since this probably contains sensitive credentials, in production you should use a Secret resource instead.
- By default, EzBackup expects the PVC to be mounted to
/mnt/target
. Customize withBACKUP_TARGET_DIR
Simply adapt the Job from the previous section into a CronJob and use the cron notation to specify the schedule.
todo: add once "restore" command is implemented...
Meanwhile, since the backups are created by restic, you can simply restore them with any container with a restic binary and the repository information.