Skip to main content

Overview

MongoDB is a document-oriented NoSQL database. This template deploys a MongoDB replica set built on Percona Server for MongoDB 8.0 (percona/percona-server-mongodb:8.0): a configurable number of members per location, keyfile authentication between members, automatic replica set formation at boot, and automatic primary election when a member is lost. An HAProxy workload (on by default) gives clients one stable address that always routes to the current primary, and an optional cron job writes mongodump archives to AWS S3 or GCS. Neither the database credentials nor the replica set keyfile are template values. Both come from secrets you create before installing, so no credential passes through Helm or lands in the release.
This template does not create a GVC. It deploys into an existing GVC that you already have, and every location you list in locations must already be on that GVC. Locations on the GVC that you do not list start nothing: no members, no proxy replicas and no volumes are created there.

What Gets Created

The template creates no credential secret of its own. The password and the keyfile live only in the secrets you create.

Prerequisites

Two secrets and a GVC with your locations must exist before you install. Secrets are org-level, so no GVC flag is involved.
1

Create the database credentials secret

A dictionary secret holding exactly three keys — username, password and database. The cluster is bootstrapped with this user (created in the admin database with the root role), and it is the credential your applications put in their connection strings. The database entry is for your own connection strings; MongoDB creates the database on first write.
Set mongodb.credentialsSecretName to this name.
2

Create the replica set keyfile secret

An opaque secret with encoding plain holding the key that members authenticate to each other with. Generate it — never invent a passphrase:
Set mongodb.keyfileSecretName to this name. The two secrets stay separate so that an application granted reveal on the credentials cannot also read the key that lets a member join your replica set.
3

Check that the GVC has every location you will list

The GVC may have more locations than you list — nothing runs in those — but every entry in locations must be present. The locations are under spec.staticPlacement.locationLinks:
4

Read either secret back later

A bare cpln secret reveal prints only a summary table; pass -o yaml for the values:
The keyfile must be valid base64, or the cluster will not start. MongoDB accepts 6–1024 characters from the base64 alphabet only (A-Z, a-z, 0-9, +, /, =). A hand-written passphrase with hyphens or punctuation will not boot. The container checks the key before starting MongoDB and fails with a message naming your secret, visible in cpln logs:
The keyfile cannot be changed after the cluster is initialized.
Create both secrets before installing, or the deployment wedges silently. The template refuses to render when either name is blank, but a name that points at a secret which does not exist installs successfully and then never starts. No container runs, so cpln logs returns zero lines. The one place the reason appears is status.versions[].message:
Use get-deployments — plain cpln workload get has no versions key. Once the secret exists the deployment recovers on its own after several minutes, or run cpln workload force-redeployment RELEASE_NAME-mongo --gvc GVC_NAME to skip the wait.
Backups need a bucket and a Control Plane Cloud Account before they can be enabled — see Backing Up. Nothing else is required.

Installation

Create the prerequisite secrets, then install with their names and the location your GVC has. The default locations entry is aws-us-east-1 with three members; a --set on a list entry replaces the whole entry, so pass both fields. For more than one location, use a values file instead.

UI

Browse, install, and manage templates visually

CLI

Manage templates from your terminal

Terraform

Declare templates in your Terraform configurations

Pulumi

Declare templates in your Pulumi programs

Configuration

Each block below is the shipped default for that part of values.yaml.

Locations

The default is one location with three members — the smallest shape that installs on any single-location GVC and survives losing a member. Set it to your GVC’s locations before installing. Listing the same location twice, or giving one replicas: 0, is refused at render; to stop running somewhere, remove the entry. Every member this template creates is a voting member, so the total across all locations decides what the replica set survives: A total above 7 is refused at render: MongoDB rejects the 8th voting member, and every member past it would run a mongod that reports ready while never being in the replica set.
At most 6 members in one location on a default org quota. A 7-member roster in a single location passes render and is then rejected at install with One or more containers exceed the autoscaling.maxScale of 6 (quota: replicas-per-replica-direct-workload). Reach 7 by splitting across locations (4 + 3 is proven), or request a quota increase.
Spreading members across locations buys survival of a whole location, at the cost of cross-region replication traffic, which is billed. Size it against the same table: 3 locations × 1 member survives losing one location; 2 locations × 2 members survives losing neither, because 2 of 4 is not a majority.
Never reorder locations after installing — only append. The first entry is the bootstrap location: replica-0 there is the member that initializes the replica set. Moving a different location into first position points that logic at a member with an empty data directory.

Image and Resources

Credentials

Both secrets must exist before you install — see Prerequisites. The workloads read them through cpln://secret/... references, so the values appear in neither the Helm release nor the stored workload spec.

Storage

There is no snapshot schedule: a final snapshot is taken when the volume set is deleted and kept for 7 days. Use backups for point-in-time copies.

Access

The list also governs replication between the members, HAProxy’s health checks and the backup job, so the template always adds its own workloads to it — list only your clients. A change to firewall can take several minutes to take effect; re-test rather than trusting the first response.

HAProxy

The proxy health-checks every member and forwards to the one that is currently primary, so applications keep one connection string across failovers. Backups do not use it: the backup job connects to replica-0 in backup.location directly, so proxy.enabled: false does not affect them.

Backups

backup.location is validated against locations at render time, and backup.mode: physical fails at render even while backup.enabled is false. The bucket and Cloud Account must exist first — see Backing Up for the per-provider steps and the IAM policy.

Connecting

The user lives in the admin database, so connection strings must carry authSource=admin:
To offload reads, connect to the members directly and add readPreference=secondaryPreferred; secondary reads can lag the primary slightly. Verify the replica set from inside a member. The credentials are already in its environment, so nothing is typed on the command line:
Every member should be listed, one PRIMARY and the rest SECONDARY. To use mongosh from your own machine, forward the proxy port and connect to 127.0.0.1; db.hello().primary shows which member the proxy is routing to:

Operations

Backing Up

When backup.enabled is true, the RELEASE_NAME-mongo-backup cron workload runs mongodump on backup.schedule in backup.location only, authenticating with the username and password from your credentials secret. Each run writes one gzip-compressed archive of every database in the cluster to PREFIX/mongo-YYYY-MM-DDTHH-MM-SSZ.archive.gz in your bucket. Backups do not delete older archives; manage retention with a bucket lifecycle rule.
1

AWS S3

  1. Create an S3 bucket. Set backup.aws.bucket to its name and backup.aws.region to its region.
  2. If you do not have a Control Plane Cloud Account for AWS, follow the Create a Cloud Account guide. Set backup.aws.cloudAccountName to its name.
  3. Create an IAM policy with the following JSON, replacing YOUR_BUCKET_NAME, and set backup.aws.policyName to its name. The template attaches this policy to the identity and nothing else, so the bucket in it is the only storage the job can reach:
  1. Set backup.location to one of your locations, backup.aws.prefix to the folder path for the archives, then backup.enabled: true and backup.provider: aws.
2

GCS

  1. Create a GCS bucket. Set backup.gcp.bucket to its name.
  2. If you do not have a Control Plane Cloud Account for GCP, follow the Create a Cloud Account guide. Set backup.gcp.cloudAccountName to its name.
  3. Add the Storage Admin role to the GCP service account associated with the Cloud Account. The template additionally binds the identity to roles/storage.objectAdmin on exactly the bucket in backup.gcp.bucket.
  4. Set backup.location to one of your locations, backup.gcp.prefix to the folder path for the archives, then backup.enabled: true and backup.provider: gcp.
Check a run with the container logs of the cron workload; a successful run ends with [INFO] Backup completed: mongo-....archive.gz:
If you enable backups while firewall.internalAllowType: workload-list is in force, the first scheduled run can fail with server selection error: context deadline exceeded because the firewall change has not taken effect yet; the next run succeeds.

Restoring a Backup

The archive is a mongodump --archive --gzip file, so it is restored with mongorestore --gzip --archive. The cluster has no public endpoint, so the restore runs through a cpln port-forward tunnel from a machine that has the MongoDB Database Tools and your cloud CLI installed. This procedure was verified end to end during the template’s 2.0.0 test cycle: archive downloaded, data dropped, restored, and the restored documents read back from a secondary.
1

Download the archive

List what is in the bucket with aws s3 ls s3://BUCKET_NAME/PREFIX/ (for GCS, gcloud storage ls gs://BUCKET_NAME/PREFIX/), then download the one you want:
2

Open a tunnel to the proxy

The proxy routes the tunnel to whichever member is primary right now, which is where a restore must write. Leave this running. If you disabled the proxy, forward to RELEASE_NAME-mongo instead.
3

Restore through the tunnel

By default mongorestore adds the archive’s documents to the existing collections and keeps any document whose _id already exists. Add --drop to replace each collection with the backup’s contents, or --nsInclude to restore a single database or collection; see the mongorestore reference for both. In another terminal:
Restored data replicates to the secondaries like any other write.
4

Verify

Through the same tunnel, list the databases and spot-check a collection count:

Rotating the Password

The password in the secret creates the root user on first boot; afterwards the members and the backup job present it when they authenticate. Rotate inside MongoDB first, then bring the secret and the running replicas in line:
1

Change it inside MongoDB

Through a port-forward tunnel to the proxy, which reaches the primary:
2

Update the secret

Re-apply your dictionary secret with the new password entry, keeping username and database unchanged:
3

Redeploy the members

A running replica keeps the environment it started with; updating the secret does not restart it, and the old value keeps working with no error until it does. Force a redeployment so every member — and the startup checks that use these credentials — picks up the new password. The template sets no limit on how many members restart at once, so this can restart every member in every location together (each steps a primary down in its pre-stop hook first); plan it as a short write outage with client retries:

Migrating from 1.x

Template versions through 1.1.1 created their own GVC. Version 2.0.0 does not — and Helm deletes what a chart stops declaring, so an in-place upgrade of a 1.x release onto 2.0.0 deletes the GVC the 1.x release created, with every workload, volume set and identity in it, including your data. The chart refuses to render when your values still carry the 1.x gvc key, so the usual path fails safely:
Do not run cpln helm upgrade on a 1.x release with the 2.0.0 chart under any circumstances, including with no values at all — the guard can only see values you pass. Migrate to a new release instead.
1

Pick an existing GVC and create the prerequisite secrets

Choose a GVC that already has the locations you will list, and create both prerequisite secrets with new values. The new cluster is bootstrapped from them on a fresh data directory, so this is the moment to choose a new password and generate a new keyfile.
2

Install 2.0.0 as a new release

Use a different release name — secret and policy names are org-wide. Re-check your roster against the sizing table: 1.x defaulted to nine members, and only seven of them were ever in the replica set.
3

Move the data across

Dump from the old cluster and restore into the new one, tunnelling to each with cpln port-forward — the procedure is Restoring a Backup, with mongodump --uri="mongodb://USERNAME:PASSWORD@127.0.0.1:27017/?authSource=admin" --gzip --archive=./backup.gz against the old proxy in place of downloading an archive.
4

Point your applications at the new release, then uninstall the old one

Run cpln helm uninstall against the GVC you installed the 1.x release into — that is where Helm tracks it. Uninstalling the 1.x release deletes the GVC it created and everything still in it.
Values that moved or were removed in 2.0.0. Each is named at render time rather than ignored: Coming from 1.0.0 specifically. That version took the credentials as plain values with a working default password, and shipped a working replica set keyfile as the mongodb.replicaSetKey default. Both were published in the public template repository, so treat an unchanged 1.0.0 password and keyfile as compromised, not merely outdated — do not carry either across. Version 1.1.0 replaced them with the two prerequisite secrets. While the old cluster is still running and you need its credentials to dump from it, read them from the secret 1.0.0 created (keys username, password, database), or from the values file you installed with:

Scaling and Availability

What the cluster survives. Only the primary accepts writes; when it is lost, the remaining members elect a new primary and the proxy re-routes to it, so clients using the proxy address keep the same connection string. With three members in one location the set survives losing one member; spread across three locations with one member each it survives losing a whole location. A member that comes back rejoins as a secondary on its own volume. Members are voting members, so size against the table under Locations. A cpln helm upgrade that changes the MongoDB tier, or a forced redeployment, restarts the whole tier. The template sets no limit on how many members restart at once, so every member in every location can restart together; each runs rs.stepDown in its pre-stop hook before it stops, but there is no primary while the members are down. Plan it as a short write outage with client retries, and do not perform other maintenance or lose a member while the tier is restarting — a set that has not yet re-formed a majority cannot elect a primary. Scaling up. Increase replicas for a location, or append a location the GVC already has, and upgrade the release. New members find the primary through the other members and register themselves into the replica set; no manual step is needed. Stay within 7 members in total and 6 per location. Scaling down. Remove departing members from the replica set configuration before reducing replicas; otherwise the configuration keeps referencing hosts that no longer exist, which distorts elections and quorum. Through a tunnel to the proxy, for each departing member (highest index first):
Then upgrade the release with the lower count. To stop running in a location entirely, remove its entry from locations. Storage. Each member’s data lives on its own volume, survives restarts and upgrades, and grows automatically when volumeset.autoscaling.enabled is true. cpln helm uninstall deletes the volume set; a final snapshot is retained for 7 days.

Troubleshooting

Symptom: cpln helm install reported success, RELEASE_NAME-mongo never reaches ready, and cpln logs returns no lines. cpln workload get-deployments RELEASE_NAME-mongo --gvc GVC_NAME -o yaml shows under status.versions[].message:
Cause: mongodb.credentialsSecretName or mongodb.keyfileSecretName names a secret that does not exist in this org.Fix: Create the secret as shown in Prerequisites, then run cpln workload force-redeployment RELEASE_NAME-mongo --gvc GVC_NAME or wait several minutes for the deployment to recover on its own.
Symptom: The member container exits with code 1 before MongoDB starts, and cpln logs '{gvc="GVC_NAME", workload="RELEASE_NAME-mongo"}' --limit 50 --since 10m shows FATAL: the keyfile in secret '...' contains characters outside the base64 alphabet or ... is N characters; mongod requires 6-1024.Cause: The keyfile secret holds a hand-written passphrase or a truncated value. MongoDB accepts only 6–1024 characters from A-Z a-z 0-9 + / =.Fix: On a cluster that has never started, recreate the secret with openssl rand -base64 756 | cpln secret create-opaque --name KEYFILE_SECRET_NAME --encoding plain -f - (delete the old one first) and force a redeployment. The keyfile cannot be changed once the cluster is initialized.
Symptom: Member logs show locations declared in values are not in GVC 'GVC_NAME': ... followed by either FATAL: refusing to bootstrap a replica set smaller than it was configured to be (fresh members, which exit) or This member holds data and keeps running rather than taking a live cluster down (members that already hold data, which keep serving).Cause: locations names a location the GVC does not have. The platform accepts the placement without error, so the members there never start and the replica set would be smaller than the quorum you sized.Fix: Add the missing location to the GVC, or remove it from locations and upgrade the release. Check the GVC’s locations with cpln gvc get GVC_NAME -o yaml under spec.staticPlacement.locationLinks.
Symptom: cpln workload get-deployments RELEASE_NAME-mongo --gvc GVC_NAME -o yaml shows a location with This workload location is deactivated because maxScale is set to 0. and no replicas.Cause: The GVC has a location that is not in locations. This is intended: nothing runs there and no volume is provisioned.Fix: None needed. To run members there, add the location to locations and upgrade the release.
Symptom: cpln helm install creates the proxy and then fails on RELEASE_NAME-mongo with One or more containers exceed the autoscaling.maxScale of 6 (quota: replicas-per-replica-direct-workload). Request quota increase.Cause: A single location lists 7 members. The chart allows 7 in total, but a default org quota caps this workload at 6 replicas per location.Fix: Split the roster across locations (for example 4 + 3), or request a quota increase. Uninstall the failed release before reinstalling.
Symptom: cpln helm install or cpln helm upgrade exits with a mongodb-cluster 2.0.0: render error naming the gvc key or backup.mode 'physical', and nothing is changed.Cause: Your values file is from a 1.x release. The gvc block and physical backups were removed in 2.0.0, and an in-place upgrade from 1.x is refused deliberately.Fix: Follow Migrating from 1.x. For a 2.0.0 values file, remove the gvc block and set backup.mode: logical.

Important Notes

  • Create both prerequisite secrets before installing. A missing secret wedges the deployment with no log output; the only diagnostic is status.versions[].message from cpln workload get-deployments.
  • Generate the keyfile with openssl rand -base64 756, never a passphrase, and never change it after the cluster is initialized.
  • Never helm upgrade a 1.x release onto 2.0.0. It deletes the GVC the 1.x chart created and everything in it. Migrate to a new release.
  • The GVC must already have every location you list, and may have more; unlisted locations run nothing. Never reorder locations after install — only append.
  • At most 7 members in total and 6 in one location. A 2-member set is refused; 3 is the usual minimum.
  • Connection strings need authSource=admin, and clients should use the proxy address so failover needs no client change.
  • Rotating a secret does not restart anything. The old value keeps working with no error until you run cpln workload force-redeployment.
  • Remove members with rs.remove before scaling down. An upgrade or forced redeployment restarts the whole MongoDB tier at once — plan a short write outage and let it finish before any other maintenance.
  • Backups are full-cluster dumps with no retention policy of their own; use a bucket lifecycle rule. Restore runs through cpln port-forward.
  • Uninstalling deletes the volume set. A final snapshot is retained for 7 days.

External References

Percona Server for MongoDB

Official documentation for the database image this template runs

MongoDB Replication

Replica set concepts, elections and failover

Replica Set Members

Member roles and the 7-voting-member limit

mongorestore Reference

Options for restoring archives, including —drop and —nsInclude

MongoDB Connection String

Connection string URI format and options

MongoDB Cluster Template

View the source files, default values, and chart definition