Generic Backup and Restore

Applications can often be deployed using non-shared storage (e.g., local SSDs) or on systems where K10 does not currently support the underlying storage provider. To protect data in these scenarios, K10 with Kanister gives you the ability, with extremely minor application modifications to add functionality to backup, restore, and migrate this application data in an efficient and transparent manner.

Extending Applications

While a complete example is provided below, the only change needed is the addition of a sidecar to your application deployment that can mount the application data volume. An example, where /data is used as an sample mount path, can be seen in the below specification. Note that the sidecar must be named kanister-sidecar and you should pin the version of the image to the latest Kanister release.

- name: kanister-sidecar
  image: kanisterio/kanister-tools:0.22.0
  command: ["bash", "-c"]
  args:
  - "tail -f /dev/null"
  volumeMounts:
  - name: data
    mountPath: /data

Once the above change is made, K10 will be able to automatically extract data and, via tools such as Restic, able to efficiently deduplicate data and transfer it into an object store.

If you have multiple volumes used by your pod, you simply need to mount them all within this sidecar container. There is no naming requirement on the mount path as long as they are unique.

End-to-End Example

The below section provides a complete end-to-end example of how to extend your application to support file-system level backup and restore. We use a dummy application as an example but it should be straightforward to extend this example.

Deploy the application

The following specification contains a complete example of how to exercise generic backup and restore functionality. It consists of a an application Deployment that use a Persistent Volume Claim (mounted internally at /data) for storing data. Two containers are used in this example: the regular application container and a sidecar. The sidecar container includes Kanister-provided tools and, as specified above, also has access to the same volume for data extraction and insertion.

We recommend saving the below specification as a file, deployment.yaml, for reuse later.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: demo-pvc
  labels:
    app: demo
    pvc: demo
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: demo-app
  labels:
    app: demo
spec:
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: demo-container
        image: alpine:3.7
        resources:
            requests:
              memory: 256Mi
              cpu: 100m
        command: ["tail"]
        args: ["-f", "/dev/null"]
        volumeMounts:
        - name: data
          mountPath: /data
      - name: kanister-sidecar
        image: kanisterio/kanister-tools:0.22.0
        command: ["tail"]
        args: ["-f", "/dev/null"]
        volumeMounts:
        - name: data
          mountPath: /data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: demo-pvc

Deploy the above application as follows:

# Deploying in a specific namespace
$ kubectl create namespace <namespace>
$ kubectl apply --namespace=<namespace> -f deployment.yaml

Create a Kanister Profile

If you haven't done so already, create a Kanister profile with the appropriate Location and Credentials information from the K10 settings page.

Insert Data

The easiest way to insert data into the demo application is to simply copy it in:

# Get pods for the demo application from its namespace
$ kubectl get pods --namespace=<namespace> | grep demo-app

# Copy required data manually into the pod
$ kubectl cp <file-name> <namespace>/<pod>:/data/

# Verify if the data was copied successfully
$ kubectl exec --namespace=<namespace> <pod> -- ls -l /data

Backup Data

Backup the application data either by creating a Policy or running a Manual Backup from K10. This assumes that the application is running on a system where we do not support the provisioned disks (e.g., local storage).

Destroy Data

To destroy the data manually, run the following command:

# Using kubectl
$ kubectl exec --namespace=<namespace> <pod> -- rm -rf /data/*

Alternatively, the application and the PVC can be deleted and recreated.

Restore Data

Restore the data using K10 by selecting the appropriate restore point.

Verify Data

After restore, you should verify that the data is intact. One way to verify this is to use MD5 checksum tool.

# MD5 on the original file copied
$ md5 <file-name>

# Copy the restored data back to local env
$ kubectl get pods --namespace=<namespace> | grep demo-app
$ kubectl cp <namespace>/<pod>:/data/<filename> <new-filename>

# MD5 on the new file
$ md5 <new-filename>

The MD5 checksums should match.