Restic Database Example¶
Attention
Scribe has been renamed to VolSync!
The Scribe project has been renamed to VolSync, and it has a new home. Come join us at our new location:
Documentation: https://volsync.readthedocs.io
Artifact Hub: https://artifacthub.io/packages/helm/backube-helm-charts/volsync
Restic backup¶
Restic is a fast and secure backup program. The following example will use Restic to create a backup of a source volume.
A MySQL database will be used as the example application.
Creating source PVC to be backed up¶
Create a namespace called source
, and deploy the source MySQL database.
$ kubectl create ns source
$ kubectl -n source create -f examples/source-database/
Verify the database is running:
$ kubectl -n source get pods,pvc,volumesnapshots
NAME READY STATUS RESTARTS AGE
pod/mysql-87f849f8c-n9j7j 1/1 Running 1 58m
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/mysql-pv-claim Bound pvc-adbf57f1-6399-4738-87c9-4c660d982a0f 2Gi RWO csi-hostpath-sc 60m
Add a new database:
$ kubectl exec --stdin --tty -n source `kubectl get pods -n source | grep mysql | awk '{print $1}'` -- /bin/bash
$ mysql -u root -p$MYSQL_ROOT_PASSWORD
> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
> create database synced;
> exit
$ exit
Restic Repository Setup¶
For the purpose of this tutorial we are using minio as the object storage target for the backup.
Start minio
:
$ hack/run-minio.sh
The restic-config
Secret configures the Restic repository parameters:
---
apiVersion: v1
kind: Secret
metadata:
name: restic-config
type: Opaque
stringData:
# The repository url
RESTIC_REPOSITORY: s3:http://minio.minio.svc.cluster.local:9000/restic-repo
# The repository encryption key
RESTIC_PASSWORD: my-secure-restic-password
# ENV vars specific to the back end
# https://restic.readthedocs.io/en/stable/030_preparing_a_new_repo.html
AWS_ACCESS_KEY_ID: access
AWS_SECRET_ACCESS_KEY: password
ReplicationSource¶
Start by configuring the source; a minimal example is shown below
---
apiVersion: scribe.backube/v1alpha1
kind: ReplicationSource
metadata:
name: database-source
namespace: source
spec:
sourcePVC: mysql-pv-claim
trigger:
schedule: "*/30 * * * *"
restic:
pruneIntervalDays: 15
repository: restic-config
retain:
hourly: 1
daily: 1
weekly: 1
monthly: 1
yearly: 1
copyMethod: Clone
In the above ReplicationSource
object,
The PiT copy of the source data
mysql-pv-claim
will be created by cloning the source volume.The synchronization schedule,
.spec.trigger.schedule
, is defined by a cronspec, making the schedule very flexible. In this case, it will take a backup every 30 minutes.The restic repository configuration is provided via the
restic-config
Secret.pruneIntervalDays
defines the interval between Restic prune operations.The
retain
settings determine how many backups should be saved in the repository. Read more about restic forget.
Now, deploy the restic-config
followed by ReplicationSource
configuration.
$ kubectl create -f examples/restic/source-restic/source-restic.yaml -n source
$ kubectl create -f examples/restic/scribe_v1alpha1_replicationsource.yaml -n source
To verify the replication has completed, view the the ReplicationSource
.status
field.
$ kubectl -n source get ReplicationSource/database-source -oyaml
apiVersion: scribe.backube/v1alpha1
kind: ReplicationSource
metadata:
name: database-source
namespace: source
spec:
# ... lines omitted ...
status:
conditions:
- lastTransitionTime: "2021-05-17T18:16:35Z"
message: Reconcile complete
reason: ReconcileComplete
status: "True"
type: Reconciled
lastSyncDuration: 3m10.261673933s
lastSyncTime: "2021-05-17T18:19:45Z"
nextSyncTime: "2021-05-17T18:30:00Z"
restic: {}
In the above output, the lastSyncTime
shows the time when the last backup
completed.
The backup created by Scribe can be seen by directly accessing the Restic repository:
# In one window, create a port forward to access the minio server
$ kubectl port-forward --namespace minio svc/minio 9000:9000
# An another, access the repository w/ restic via the above forward
$ AWS_ACCESS_KEY_ID=access AWS_SECRET_ACCESS_KEY=password restic -r s3:http://127.0.0.1:9000/restic-repo snapshots
enter password for repository:
repository 03fd0c91 opened successfully, password is correct
created new cache in /home/jstrunk/.cache/restic
ID Time Host Tags Paths
------------------------------------------------------------
caebaa8e 2021-05-17 14:19:42 scribe /data
------------------------------------------------------------
1 snapshots
There is a snapshot in the restic repository created by the restic data mover.
Restoring the backup¶
To restore from the backup, create a destination, deploy restic-config
and
ReplicationDestination
on the destination.
$ kubectl create ns dest
$ kubectl -n dest create -f examples/restic/source-restic/
To start the restore, create a empty PVC for the data:
$ kubectl -n dest create -f examples/source-database/mysql-pvc.yaml
persistentvolumeclaim/mysql-pv-claim created
Create the ReplicationDestination in the dest
namespace to restore the data:
---
apiVersion: scribe.backube/v1alpha1
kind: ReplicationDestination
metadata:
name: database-destination
spec:
trigger:
manual: restore
restic:
destinationPVC: mysql-pv-claim
repository: restic-config
copyMethod: None
$ kubectl -n dest create -f examples/restic/scribe_v1alpha1_replicationdestination.yaml
Once the restore is complete, the .status.lastManualSync
field will match
.spec.trigger.manual
.
To verify restore, deploy the MySQL database to the dest
namespace which will use the data that has
been restored from sourcePVC backup.
$ kubectl create -n dest -f examples/destination-database/
Validate that the mysql pod is running within the environment.
$ kubectl get pods -n dest
NAME READY STATUS RESTARTS AGE
mysql-8b9c5c8d8-v6tg6 1/1 Running 0 38m
Connect to the mysql pod and list the databases to verify the synced database exists.
$ kubectl exec --stdin --tty -n dest `kubectl get pods -n dest | grep mysql | awk '{print $1}'` -- /bin/bash
$ mysql -u root -p$MYSQL_ROOT_PASSWORD
> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| synced |
| sys |
+--------------------+
5 rows in set (0.00 sec)
> exit
$ exit