RClone for Backups
There are many backup solutions out there for Kubernetes, but the one I ended up going with for my needs is Rclone. It supports MANY different back ends and is incredibly flexible. It's been called the "swiss army knife" of backup solutions.
For my needs, I've configured Rclone as a cronjob in a namespace called backup to run every night to send files from various locations to private Backblaze buckets for off-site storage. Below is an example of how I deployed Rclone in Kubernetes.
To keep things tidy I create a dedicated backup namespace.
00-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: backup
labels:
name: backup
Now we need to define the volumes and claims we're going to backup so they can be mounted to the Rclone container. Below is an example of an NFS share on my network that I want backed up. You can define as many volumes and claims as you need.
01-storage.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: backups
spec:
capacity:
storage: 1Ti
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /path/to/share
server: server.name.or.ip
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: backup
name: backups
spec:
accessModes:
- ReadWriteMany
volumeName: backups
storageClassName: nfs
resources:
requests:
storage: 1Ti
Be sure to change the details like you server name, path. and storage size. While I'm using NFS shares here, you could certainly use any storage available to you (like Longhorn for example).
Now that we've created the foundations, we need to define some configurations for Rclone. Rclone will look for a rclone.conf file for it's configuration and we will want to provide this as a Kubernetes Secret so we can easily maintain it. Since I'm using Backblaze I've configured Rclone for B2. You can either use the documentation as a guide or even install Rclone on your workstation and run:
rclone config
This will interactively create your config file locally and you can use that to create your Secret.
Additionally, I have created a bash script as a Kubernetes ConfigMap that will do the work of backing up my drives. I've combined the Secret and ConfigMap into a single "configs" YAML file here.
02-configs.yaml
apiVersion: v1
kind: Secret
metadata:
name: rclone-config
namespace: backup
stringData:
rclone.conf: |
[My-Backup]
type = b2
account = <your-application-api-keyID>
key = <your-applications-api-secret>
hard_delete = true
---
apiVersion: v1
kind: ConfigMap
metadata:
name: rclone-scripts
namespace: backup
data:
rclone-sync.sh: |
#!/bin/sh
echo "---------------------------------------------------"
echo "Begining backup of path 1"
echo "---------------------------------------------------"
rclone sync /mnt/backup/path1 <Your Instance Name>:<Your Bucket Name> --config /config/rclone/rclone.conf -v
echo "---------------------------------------------------"
echo "Begining backup of path 2"
echo "---------------------------------------------------"
rclone sync /mnt/backup/path2 <Your Instance Name>:<Your Bucket Other Name> --config /config/rclone/rclone.conf -v
You can define multiple volumes and PVCs to backup if you need to, or have a single PVC with different directories. Rclone will recursively backup all items is a defined path.
We need to put this all together as a CronJob in Kubernetes to execute automatically.
03-cronob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
labels:
app: rclone
name: rclone-sync
namespace: backup
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: rclone
image: rclone/rclone:latest
imagePullPolicy: Always
env:
- name: TZ
value: "America/NewYork"
volumeMounts:
- name: scripts
mountPath: /scripts
- name: backups
mountPath: /mnt/backup
- name: rclone-config
mountPath: /config/rclone/rclone.conf
subPath: rclone.conf
resources:
limits:
cpu: '4'
memory: 16Gi
requests:
cpu: 100m
memory: 100Mi
command:
- "/bin/sh"
- "/scripts/rclone-sync.sh"
restartPolicy: OnFailure
volumes:
- name: backups
persistentVolumeClaim:
claimName: backups
- name: scripts
configMap:
name: rclone-scripts
- name: rclone-config
secret:
secretName: rclone-config
As you can see, this will create a CronJob that runs daily at 2 AM and will mount the Secret and ConfigMap we created earlier as files on the file system. The container then runs the script we defined in the ConfigMap to do the backups.
Now we need to deploy to the Kubernetes Cluster. I like to save these in a script to easily redeploy again if I make any changes. Simply run the below script to deploy to Kubernetes.
build-rclone.sh
#!/bin/bash
kubectl apply -f 00-namespace.yaml \
-f 01-storage.yaml \
-f 02-configs.yaml \
-f 03-cronjob.yaml
While there are several ways to do backups, I hope this simple example will give you some ideas on how to implement a backup strategy that works for you.