Application-Consistent MongoDB BackupΒΆ

To obtain an application-consistent MongoDB backup where MongoDB is first quiesced and then a snapshot of the underlying volume belong to only the primary replica is performed, start by installing the MongoDB chart from the stable Helm repository:

Note

Due to certain quirks in the MongoDB chart, you must use mongodb, the name of the chart, in the Helm release name below. Otherwise, the below test blueprint will be unable to find the right MongoDB secret required for authentication.

$ helm install --namespace mongodb-app-consistent --name mongodb-app-consistent \
    stable/mongodb --set replicaSet.enabled=true
$ kubectl create namespace mongodb-app-consistent
$ helm install mongodb-app-consistent stable/mongodb --namespace=mongodb-app-consistent \
    --set replicaSet.enabled=true

Next, create a file mongodb_hooks.yaml with the following contents:

apiVersion: cr.kanister.io/v1alpha1
kind: Blueprint
metadata:
  name: mongo-hooks
actions:
  backupPrehook:
    type: StatefulSet
    phases:
    - func: KubeExec
      name: lockMongo
      objects:
        mongoDbSecret:
          kind: Secret
          name: '{{ .Object.metadata.labels.release }}'
          namespace: '{{ .StatefulSet.Namespace }}'
      args:
        namespace: "{{ .StatefulSet.Namespace }}"
        pod: "{{ index .StatefulSet.Pods 0 }}"
        container: mongodb-primary
        command:
        - bash
        - -o
        - errexit
        - -o
        - pipefail
        - -c
        - |
          export MONGODB_ROOT_PASSWORD='{{ index .Phases.lockMongo.Secrets.mongoDbSecret.Data "mongodb-root-password" | toString }}'
          mongo --authenticationDatabase admin -u root -p "${MONGODB_ROOT_PASSWORD}" --eval="db.fsyncLock()"
  backupPosthook:
    type: StatefulSet
    phases:
    - func: KubeExec
      name: unlockMongo
      objects:
        mongoDbSecret:
          kind: Secret
          name: '{{ .Object.metadata.labels.release }}'
          namespace: '{{ .StatefulSet.Namespace }}'
      args:
        namespace: "{{ .StatefulSet.Namespace }}"
        pod: "{{ index .StatefulSet.Pods 0 }}"
        container: mongodb-primary
        command:
        - bash
        - -o
        - errexit
        - -o
        - pipefail
        - -c
        - |
          export MONGODB_ROOT_PASSWORD='{{ index .Phases.unlockMongo.Secrets.mongoDbSecret.Data "mongodb-root-password" | toString }}'
          mongo --authenticationDatabase admin -u root -p "${MONGODB_ROOT_PASSWORD}" --eval="db.fsyncUnlock()"
---
apiVersion: cr.kanister.io/v1alpha1
kind: Blueprint
metadata:
  name: mongo-noop
actions:
  backup:
    type: StatefulSet
    phases:
    - func: KubeExec
      name: lockMongo
      args:
        namespace: "{{ .StatefulSet.Namespace }}"
        pod: "{{ index .StatefulSet.Pods 0 }}"
        container: mongodb-secondary
        command:
        - echo
        - NOOP

And then apply the file using:

$ kubectl --namespace=kasten-io create -f mongodb_hooks.yaml

Finally add the following annotation to the MongoDB StatefulSets to instruct K10 to use the above hooks when performing operations on this MongoDB instance.

$ kubectl annotate statefulset mongodb-app-consistent-primary kanister.kasten.io/blueprint='mongo-hooks' \
     --namespace=mongodb-app-consistent
$ kubectl annotate statefulset mongodb-app-consistent-secondary kanister.kasten.io/blueprint='mongo-noop' \
    --namespace=mongodb-app-consistent

Finally, use K10 to backup and restore the application.