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.
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
Prerequisites
Two secrets and a GVC with your locations must exist before you install. Secrets are org-level, so no GVC flag is involved.Create the database credentials secret
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.mongodb.credentialsSecretName to this name.Create the replica set keyfile secret
plain holding the key that members authenticate to each other with. Generate it — never invent a passphrase: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.Check that the GVC has every location you will list
locations must be present. The locations are under spec.staticPlacement.locationLinks:Read either secret back later
cpln secret reveal prints only a summary table; pass -o yaml for the values:Installation
Create the prerequisite secrets, then install with their names and the location your GVC has. The defaultlocations 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
CLI
Terraform
Pulumi
Configuration
Each block below is the shipped default for that part ofvalues.yaml.
Locations
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:
mongod that reports ready while never being in the replica set.
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.
Image and Resources
Credentials
cpln://secret/... references, so the values appear in neither the Helm release nor the stored workload spec.
Storage
Access
firewall can take several minutes to take effect; re-test rather than trusting the first response.
HAProxy
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
admin database, so connection strings must carry authSource=admin:
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:
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
Whenbackup.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.
AWS S3
- Create an S3 bucket. Set
backup.aws.bucketto its name andbackup.aws.regionto its region. - If you do not have a Control Plane Cloud Account for AWS, follow the Create a Cloud Account guide. Set
backup.aws.cloudAccountNameto its name. - Create an IAM policy with the following JSON, replacing
YOUR_BUCKET_NAME, and setbackup.aws.policyNameto 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:
- Set
backup.locationto one of yourlocations,backup.aws.prefixto the folder path for the archives, thenbackup.enabled: trueandbackup.provider: aws.
GCS
- Create a GCS bucket. Set
backup.gcp.bucketto its name. - If you do not have a Control Plane Cloud Account for GCP, follow the Create a Cloud Account guide. Set
backup.gcp.cloudAccountNameto its name. - Add the Storage Admin role to the GCP service account associated with the Cloud Account. The template additionally binds the identity to
roles/storage.objectAdminon exactly the bucket inbackup.gcp.bucket. - Set
backup.locationto one of yourlocations,backup.gcp.prefixto the folder path for the archives, thenbackup.enabled: trueandbackup.provider: gcp.
[INFO] Backup completed: mongo-....archive.gz:
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 amongodump --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.
Download the archive
aws s3 ls s3://BUCKET_NAME/PREFIX/ (for GCS, gcloud storage ls gs://BUCKET_NAME/PREFIX/), then download the one you want:Open a tunnel to the proxy
RELEASE_NAME-mongo instead.Restore through the tunnel
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:Verify
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:Change it inside MongoDB
Update the secret
password entry, keeping username and database unchanged:Redeploy the members
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.xgvc key, so the usual path fails safely:
Pick an existing GVC and create the prerequisite secrets
Install 2.0.0 as a new release
Move the data across
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.Point your applications at the new release, then uninstall the old one
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.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. Acpln 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):
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
The workload never becomes ready and cpln logs is empty
The workload never becomes ready and cpln logs is empty
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: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.FATAL: the keyfile in secret ... contains characters outside the base64 alphabet
FATAL: the keyfile in secret ... contains characters outside the base64 alphabet
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.FATAL: refusing to bootstrap a replica set smaller than it was configured to be
FATAL: refusing to bootstrap a replica set smaller than it was configured to be
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.This workload location is deactivated because maxScale is set to 0
This workload location is deactivated because maxScale is set to 0
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.Install rejected with exceed the autoscaling.maxScale of 6 (quota: replicas-per-replica-direct-workload)
Install rejected with exceed the autoscaling.maxScale of 6 (quota: replicas-per-replica-direct-workload)
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.Render fails with the gvc values key was REMOVED or backup.mode physical was REMOVED
Render fails with the gvc values key was REMOVED or backup.mode physical was REMOVED
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[].messagefromcpln 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 upgradea 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
locationsafter 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.removebefore 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.