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 bitnami 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.

The example workflow has been validated with the latest version of the MongoDB helm chart. For other versions, modify the mongodb_hooks.yaml blueprint below as required.

If it hasn't been done already, the bitnami Helm repository needs to be added to your local configuration:

# Add bitnami helm repo
$ helm repo add bitnami https://charts.bitnami.com/bitnami
$ kubectl create namespace mongodb-app-consistent
$ helm install mongodb-app-consistent bitnami/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:
    phases:
    - func: KubeExec
      name: lockMongo
      objects:
        mongoDbSecret:
          kind: Secret
          name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}'
          namespace: '{{ .Deployment.Namespace }}'
      args:
        namespace: "{{ .Deployment.Namespace }}"
        pod: "{{ index .Deployment.Pods 0 }}"
        container: mongodb
        command:
        - bash
        - -o
        - errexit
        - -o
        - pipefail
        - -c
        - |
          export MONGODB_ROOT_PASSWORD='{{ index .Phases.lockMongo.Secrets.mongoDbSecret.Data "mongodb-root-password" | toString }}'
          mongosh --authenticationDatabase admin -u root -p "${MONGODB_ROOT_PASSWORD}" --eval="db.fsyncLock()"
  backupPosthook:
    phases:
    - func: KubeExec
      name: unlockMongo
      objects:
        mongoDbSecret:
          kind: Secret
          name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}'
          namespace: '{{ .Deployment.Namespace }}'
      args:
        namespace: "{{ .Deployment.Namespace }}"
        pod: "{{ index .Deployment.Pods 0 }}"
        container: mongodb
        command:
        - bash
        - -o
        - errexit
        - -o
        - pipefail
        - -c
        - |
          export MONGODB_ROOT_PASSWORD='{{ index .Phases.unlockMongo.Secrets.mongoDbSecret.Data "mongodb-root-password" | toString }}'
          mongosh --authenticationDatabase admin -u root -p "${MONGODB_ROOT_PASSWORD}" --eval="db.fsyncUnlock()"

And then apply the file using:

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

Note

If MongoDB chart is installed specifying existing secret by setting parameter --set auth.existingSecret=<mongo-secret-name>, secret name in the blueprint mongodb_hooks.yaml needs to be modified at following places:

actions.backupPrehook.phases[0].objects.mongoDbSecret.name: <mongo-secret-name> actions.backupPosthook.phases[0].objects.mongoDbSecret.name: <mongo-secret-name>

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

$ kubectl annotate deployment mongodb-app-consistent kanister.kasten.io/blueprint='mongo-hooks' \
     --namespace=mongodb-app-consistent

Finally, use K10 to backup and restore the application.