Percona Backup for MongoDB (PBM) supports snapshot-based physical backups. This is made possible by the backup cursor functionality present in Percona Server for MongoDB.
The flow of snapshot-based physical backup consists of these stages:
A more detailed description of what happens on each step can be found in the PBM documentation.
Let’s see a practical example of performing an actual backup. For this demo, I have created a 2-shard MongoDB cluster (each shard consisting of a 3-node replica set) deployed on Google Cloud Platform instances. Each instance has an extra persistent disk attached to it for the MongoDB data. PBM agent is installed on each instance as per the documentation.
First, we start an external backup. This can be done from any host running the PBM client.
|
1 |
# pbm backup -t external<br>Starting backup '2024-09-26T15:21:53Z'..........Ready to copy data from:<br> - my-test-env-mongodb-shard00svr1:27018<br> - my-test-env-mongodb-shard01svr1:27018<br> - my-test-env-mongodb-cfg01:27019<br>After the copy is done, run: pbm backup-finish 2024-09-26T15:21:53Z<br> |
As we can see, PBM selects one node of each shard and one config server to be backed up.
At this point, we need to create snapshots of the hosts listed above. We could use the Google Cloud web console or run gcloud commands, as below.
Let’s list the attached disks of the first instance:
|
1 |
# gcloud compute instances describe "my-test-env-mongodb-shard00svr1" --zone northamerica-northeast1-b --format="get(disks[].source)"<br><br>https://www.googleapis.com/compute/v1/projects/my-gcp-project/zones/northamerica-northeast1-b/disks/my-test-env-mongodb-shard00svr1;https://www.googleapis.com/compute/v1/projects/my-gcp-project/zones/northamerica-northeast1-b/disks/my-test-env-mongodb-shard00svr1-data<br> |
Once we know the attached disks, we can snapshot them. For example:
|
1 |
gcloud compute disks snapshot "my-test-env-mongodb-shard00svr1-data" --zone="northamerica-northeast1-b" --snapshot-names="my-test-env-mongodb-shard00svr1-data-snap"<br> |
After repeating the above commands for all the instances listed, we need to complete the backup:
|
1 |
# pbm backup-finish 2024-09-26T15:21:53Z<br>Command sent. Check `pbm describe-backup 2024-09-26T15:21:53Z` for the result.<br> |
Finally, let’s check the backup status:
|
1 |
# pbm describe-backup 2024-09-26T15:21:53Z<br>name: "2024-09-26T15:21:53Z"<br>opid: 66f57c110c75d10bcd29893f<br>type: external<br>last_write_time: "2024-09-26T15:21:56Z"<br>last_transition_time: "2024-09-26T15:23:48Z"<br>mongodb_version: 7.0.12-7<br>fcv: "7.0"<br>pbm_version: 2.6.0<br>status: done<br>size_h: 0 B<br>replsets:<br>- name: shard0<br> status: done<br> node: my-test-env-mongodb-shard00svr1:27018<br> last_write_time: "2024-09-26T15:21:47Z"<br> last_transition_time: "2024-09-26T15:23:47Z"<br> security: {}<br>- name: shard1<br> status: done<br> node: my-test-env-mongodb-shard01svr1:27018<br> last_write_time: "2024-09-26T15:21:53Z"<br> last_transition_time: "2024-09-26T15:23:47Z"<br> security: {}<br>- name: mongo-cfg<br> status: done<br> node: my-test-env-mongodb-cfg01:27019<br> last_write_time: "2024-09-26T15:21:56Z"<br> last_transition_time: "2024-09-26T15:23:47Z"<br> configsvr: true<br> security: {}<br> |
Now, the manual approach is ok but let’s see how we can automate the above.
I haven’t mentioned authentication yet. We are going to use a service account with the required permissions to take snapshots. Another possibility could be using an IAM user with an associated HMAC key pair. Here are the steps to create the service account:
1. Set your project ID
|
1 |
gcloud config set project my-gcp-project |
2. Create the service account
|
1 |
gcloud iam service-accounts create snapshot-creator-sa <br> --description="Service account to create snapshots" <br> --display-name="Snapshot Creator Service Account" |
3. Assign Compute Admin and Compute Storage Admin roles
|
1 |
gcloud projects add-iam-policy-binding my-gcp-project <br> --member="serviceAccount:[email protected]" <br> --role="roles/compute.admin" |
|
1 |
gcloud projects add-iam-policy-binding my-gcp-project <br> --member="serviceAccount:[email protected]" <br> --role="roles/compute.storageAdmin" |
4. Generate and download the service account key file
|
1 |
gcloud iam service-accounts keys create snapshot-creator-key.json <br> --iam-account=snapshot-creator-sa@my-gcp-project.iam.gserviceaccount.com |
The service account file should look like this:
|
1 |
{<br> "type": "service_account",<br> "project_id": "my-gcp-project",<br> "private_key_id": "*********************",<br> "private_key": "-----BEGIN PRIVATE KEY-----n************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************n-----END PRIVATE KEY-----n",<br> "client_email": "[email protected]",<br> "client_id": "1069678999695160482161",<br> "auth_uri": "https://accounts.google.com/o/oauth2/auth",<br> "token_uri": "https://oauth2.googleapis.com/token",<br> "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",<br> "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/snapshot-creator-sa%40my-gcp-project.iam.gserviceaccount.com",<br> "universe_domain": "googleapis.com"<br>} |
With the service account ready, we can now start working on our automation.
To automate the process, we loop through the list of hosts selected by PBM, get all the attached volumes, and create snapshots of them with descriptive names.
The following script requires gcloud CLI to be installed. Keep in mind this is just a proof of concept, so don’t use it for production environments, as there is only basic error checking.
|
1 |
#!/bin/bash<br><br># Set the path to the service account JSON key file <br>SERVICE_ACCOUNT_KEY="service-account-key.json"<br><br># Authenticate using the service account key<br>export GOOGLE_APPLICATION_CREDENTIALS="$SERVICE_ACCOUNT_KEY"<br><br># Set the GCP project <br>PROJECT_ID="my-gcp-project"<br><br>gcloud auth activate-service-account --key-file="$SERVICE_ACCOUNT_KEY"<br><br>gcloud config set project "$PROJECT_ID"<br><br># Run the pbm backup command once and capture its output<br>pbm_output=$(pbm backup -t external | tee /dev/tty)<br><br># Extract the backup timestamp from pbm_output<br>backup_timestamp=$(echo "$pbm_output" | grep -oP "'K[0-9T:-]+" | head -1) # Get the first timestamp<br><br># Format the timestamp for snapshot names (replace ':' with '-' and 'T' with 't')<br>formatted_timestamp=$(echo "$backup_timestamp" | sed 's/:/-/g; s/T/t/g')<br><br># Extract hostnames to be snapshotted from the output<br>hostnames=$(echo "$pbm_output" | grep -oP '(?<=- ).*?(?=:)')<br><br># Extract the pbm backup-finish command from the output<br>finish_command=$(echo "$pbm_output" | grep -oP 'pbm backup-finish S+')<br><br># Function to create snapshots of disks for a given instance<br>create_snapshots() {<br> local instance_name=$1<br> local zone=$2<br><br> # Get attached disks for the instance<br> disks=$(gcloud compute instances describe "$instance_name" --zone="$zone" <br> --format="get(disks[].source)")<br><br> # Loop through each disk and create a snapshot<br> for disk in $disks; do<br> disk_name=$(basename "$disk")<br> snapshot_name="${disk_name}-${formatted_timestamp}" <br> echo "Creating snapshot for disk: $disk_name"<br> gcloud compute disks snapshot "$disk_name" --zone="$zone" --snapshot-names="$snapshot_name" | tee /dev/tty<br><br> if [ $? -eq 0 ]; then<br> echo "Snapshot $snapshot_name created for disk $disk_name"<br> snapshot_names+=("$snapshot_name") # Add to snapshot_names array<br> else<br> echo "Failed to create snapshot for disk $disk_name"<br> fi<br> done<br>}<br><br>snapshot_names=()<br><br># Loop through each hostname and find the corresponding GCE instance<br>for hostname in $hostnames; do<br> instance_info=$(gcloud compute instances list --filter="name:$hostname" <br> --format="get(name,zone)" | tee /dev/tty)<br><br> instance_name=$(echo "$instance_info" | awk '{print $1}')<br> zone=$(echo "$instance_info" | awk '{print $2}')<br><br> create_snapshots "$instance_name" "$zone"<br>done<br><br>echo "Snapshot creation completed."<br><br># Run the pbm backup-finish command<br>echo "Running: $finish_command"<br>finish_output=$(eval "$finish_command" | tee /dev/tty)<br><br># Extract the backup timestamp from the pbm backup-finish output<br>backup_finish_timestamp=$(echo "$finish_output" | grep -oP '(?<=pbm describe-backup )S+' | tr -d '`')<br><br># Run the pbm describe-backup command to get the final backup status<br>describe_command="pbm describe-backup $backup_finish_timestamp"<br>echo "Running: $describe_command"<br>eval "$describe_command" <br><br> |
Percona Backup for MongoDB provides the interface for making snapshot-based physical backups and restores. Database owners benefit from faster and more cost-efficient backups while ensuring that their data remains consistent.
This is the first stage of snapshot-based backups, and automated snapshot-based backups are planned for the future. If you have any suggestions for feature requests or bug reports, make sure to let us know by creating a ticket in our public issue tracker. Pull requests are also more than welcome!
Continue on to part two of this series.
MongoDB Performance Tuning is a collection of insights, strategies, and best practices from Percona’s MongoDB experts. Use it to diagnose — and correct — the issues that may be affecting your database’s performance.
Resources
RELATED POSTS