k8up-io / k8up

Kubernetes and OpenShift Backup Operator
https://k8up.io/
Apache License 2.0
617 stars 63 forks source link

Annotation k8up.io/restorecommand #637

Open ThomasSteinbach opened 2 years ago

ThomasSteinbach commented 2 years ago

Summary

As "DevOp / Admin"\ I want "to restore application-aware backups as easy as pvc backups"\ So that "I does not bother with boilerplate code to restore my databases."

Context

K8up can restore PVC backups defined by restore objects. However it should also be possible to restore application-aware backups - exactly the other way around as those backups were made. See my implementation idea below

Implementation Ideas

For making an application-aware backup you have to annotate your pods with (for instance):

k8up.syn.tools/backupcommand: /bin/bash -c 'mysqldump -uroot -p"${MARIADB_ROOT_PASSWORD}" --all-databases'

K8up will then gather the stdout and process it with restic. However the other way around should also be possible:

k8up.syn.tools/restorecommand: /bin/bash -c 'mysql -uroot --password="${MARIADB_ROOT_PASSWORD}"'

K8up only needs to push the restic output to the restorecommand. K8up only needs to create a restore job, which executes the restic restore command and pushes the output with kubectl to the target pod. I tried this approach sucessfully with the official tutorial setup. The restore job should look like following:

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kubectl
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: kubectl
rules:
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - list
  - apiGroups:
      - ""
    resources:
      - pods/exec
    verbs:
      - create
  - apiGroups:
      - apps
    resources:
      - deployments
    verbs:
      - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: kubectl
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubectl
subjects:
  - kind: ServiceAccount
    name: kubectl
---
apiVersion: batch/v1
kind: Job
metadata:
  name: restore-wordpress-mariadb
spec:
  backoffLimit: 1
  template:
    spec:
      restartPolicy: Never
      serviceAccountName: kubectl
      containers:
        - name: mariadb-restore
          image: thomass/restic-kubectl
          command:
            - /bin/sh
            - -c
            - restic dump "${DB_SNAPSHOT_ID}" /default-mariadb | kubectl exec -i deployment/mariadb -- /bin/bash -c 'mysql -uroot --password="${MARIADB_ROOT_PASSWORD}"'
          env:
            - name: RESTIC_REPOSITORY
              value: s3:http://minio-api:9000/backups/
            - name: RESTIC_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: backup-repo
                  key: password
            - name: AWS_ACCESS_KEY_ID
              valueFrom:
                secretKeyRef:
                  name: minio-credentials
                  key: username
            - name: AWS_SECRET_ACCESS_KEY
              valueFrom:
                secretKeyRef:
                  name: minio-credentials
                  key: password

It would be nice when K8up could wrap this functionality into its existing CRD "k8up.io/restore".

Kidswiss commented 2 years ago

Hi @ThomasSteinbach

That's a pretty neat idea!

We're currently overthinking the whole pre-backup handling for K8up v3, as it's a bit finicky. See #585. So it's possible that we integrate Kanister into K8up in the future, as it provides pretty flexible handling of such scripts. This would allow to define various hook scripts for the various backup and restore stages.

ThomasSteinbach commented 2 years ago

Cool. Looking forward to v3 :)