MongoDB
Deploy MongoDB on Kubernetes using the official mongo Docker image.
Supports standalone single-instance, replica set for high availability, and sharded cluster for
horizontal scalability.
Replica set members authenticate each other using a shared keyFile (auth.replicaSetKey). When the chart generates
it, the Secret is retained and reused across upgrades and persistent-release removal. Rotating or regenerating this
key after initialization will cause all replica set members to reject each other. Back up the generated Secret with
the PVCs, or use auth.existingKeySecret when credentials are externally managed.
auth.rootPassword and user passwords defined in auth.users are written during the first container initialization
(/docker-entrypoint-initdb.d/). Changing these values in a subsequent helm upgrade has no effect on the
running container. To rotate credentials, connect to MongoDB directly using the mongo shell (db.updateUser() /
db.changeUserPassword()).
Key Features
- Three architectures — standalone, replica set, sharded cluster
- Replica set HA —
rs0with configurable member count and optional arbiter - Sharded cluster — mongos routers, config servers, and data shards
- Internal keyFile auth — replica set member authentication via shared secret
- Upgrade-safe generated credentials — root credentials and keyFiles are retained with persistent data
- Init scripts —
.jsand.shfiles via/docker-entrypoint-initdb.d/ - WiredTiger tuning — custom
mongod.confviaconfigblock - Prometheus exporter —
percona/mongodb_exportersidecar with ServiceMonitor mongodumpbackup — scheduled S3 backup CronJob- Pinned upstream image — official MongoDB
9.0.4patch release
Installation
HTTPS repository:
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install my-mongo helmforge/mongodb -f values.yaml
OCI registry:
helm install my-mongo oci://ghcr.io/helmforgedev/helm/mongodb -f values.yaml
Deployment Examples
# values.yaml — MongoDB standalone (single instance)
architecture: standalone
auth:
enabled: true
rootUser: root
existingSecret: mongodb-root-credentials # keys: mongodb-root-username, mongodb-root-password
users:
- username: appuser
password: 'app-password'
database: myapp
roles:
- { role: readWrite, db: myapp }
persistence:
enabled: true
size: 20Gi
config:
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 1 # set to ~50% of available memory minus OS overhead
metrics:
enabled: true
serviceMonitor:
enabled: true# values.yaml — MongoDB replica set (3 members, HA)
architecture: replicaset
auth:
enabled: true
existingSecret: mongodb-root-credentials
existingKeySecret: mongodb-replica-key # key: mongodb-replica-set-key (must not change)
replicaSet:
name: rs0
members: 3
persistence:
enabled: true
size: 50Gi
config:
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 2
metrics:
enabled: true
serviceMonitor:
enabled: true# Connection string for replica set:
# mongodb://appuser:[email protected]:27017/myapp?replicaSet=rs0# values.yaml — Replica set with arbiter (2 data members + 1 arbiter)
# Use when you want odd-number election votes without a 3rd data-bearing member
architecture: replicaset
auth:
enabled: true
existingSecret: mongodb-root-credentials
existingKeySecret: mongodb-replica-key
replicaSet:
name: rs0
members: 2 # 2 data-bearing members; arbiter provides the 3rd vote
arbiter:
enabled: true # lightweight pod: votes in elections but stores no data
persistence:
enabled: true
size: 50GiAn arbiter participates in elections but holds no data. Use it when you have an even number of data-bearing members to ensure a majority for elections. MongoDB recommends three data-bearing members when capacity permits because an arbiter does not add data redundancy and can affect majority write availability. The chart supports one arbiter with 2, 4, or 6 data-bearing members. See the official arbiter considerations.
# values.yaml — MongoDB sharded cluster (2 shards, 3 members each)
architecture: sharded
auth:
enabled: false
sharded:
mongos:
replicaCount: 2 # query routing layer
port: 27017
configServer:
replicaCount: 3 # cluster metadata (must be odd)
persistence:
size: 10Gi
shards:
count: 2 # number of shards
membersPerShard: 3 # members per shard replica set
persistence:
size: 100Gi
config:
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 4Always connect to the mongos service, not to individual shard replica set members. Shards should only be accessed
directly for administrative operations.
The chart validates sharded mode as an unauthenticated lab topology. The official MongoDB container initializes
MONGO_INITDB_ROOT_* as a standalone process, which conflicts with --configsvr and --shardsvr. Production sharded
authentication requires an operator-managed bootstrap flow outside the chart’s automatic root-user path.
Configuration Reference
Image
| Parameter | Type | Default | Description |
|---|---|---|---|
image.repository |
string | docker.io/library/mongo |
MongoDB image. |
image.tag |
string | "9.0.4" |
Image tag. |
Authentication
| Parameter | Type | Default | Description |
|---|---|---|---|
auth.enabled |
boolean | true |
Enable MongoDB --auth flag. |
auth.rootUser |
string | root |
Root username (MONGO_INITDB_ROOT_USERNAME). |
auth.rootPassword |
string | "" |
Root password. Auto-generated and retained if empty. Set only on first deployment. |
auth.existingSecret |
string | "" |
Existing secret. Keys: mongodb-root-username, mongodb-root-password. |
auth.replicaSetKey |
string | "" |
KeyFile for internal replica set auth. Auto-generated and retained if empty. |
auth.existingKeySecret |
string | "" |
Existing secret with keyFile. Key: mongodb-replica-set-key. |
auth.users |
array | [] |
Additional users to create on first startup. |
Architecture
| Parameter | Type | Default | Description |
|---|---|---|---|
architecture |
string | standalone |
standalone, replicaset, or sharded. |
replicaSet.name |
string | rs0 |
Replica set name. |
replicaSet.members |
integer | 3 |
Number of data-bearing replica set members. |
arbiter.enabled |
boolean | false |
Add one non-data-bearing voting member in replica set mode. |
arbiter.resources |
object | {} |
CPU and memory requests/limits for the arbiter mongod container. |
Sharded Cluster
| Parameter | Type | Default | Description |
|---|---|---|---|
sharded.mongos.replicaCount |
integer | 2 |
Number of mongos router pods. |
sharded.configServer.replicaCount |
integer | 3 |
Config server members (must be odd). |
sharded.configServer.persistence.size |
string | 8Gi |
Config server PVC size. |
sharded.shards.count |
integer | 2 |
Number of shards. |
sharded.shards.membersPerShard |
integer | 3 |
Replica set members per shard. |
sharded.shards.persistence.size |
string | 16Gi |
Data PVC size per shard member. |
Persistence and Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
persistence.enabled |
boolean | true |
Enable PVC for data (StatefulSet volumeClaimTemplate). |
persistence.size |
string | 8Gi |
PVC size per member. |
config |
object | {} |
Custom mongod.conf content (WiredTiger cache, profiling). |
port |
integer | 27017 |
MongoDB listen port. |
initdbScripts |
object | {} |
.js/.sh init scripts via /docker-entrypoint-initdb.d/. |
MongoDB’s WiredTiger engine defaults to 50% of available RAM for its cache. Always set resources.limits.memory and
tune config.storage.wiredTiger.engineConfig.cacheSizeGB explicitly to avoid OOM kills. For example, a pod with 4 GiB
memory limit should use cacheSizeGB: 1.5 (leaving headroom for OS and index overhead).
Service
| Parameter | Type | Default | Description |
|---|---|---|---|
service.type |
string | ClusterIP |
Client Service type. |
service.port |
integer | 27017 |
Client Service port. |
service.ipFamilyPolicy |
string | "" |
Service IP family policy: SingleStack, PreferDualStack, or RequireDualStack. |
service.ipFamilies |
array | [] |
Optional Service IP family override. |
External Secrets
Use External Secrets when root credentials are owned by an external secret
manager. Set auth.existingSecret to the same target Secret name so the
StatefulSet consumes the synchronized Secret instead of rendering a competing
chart-managed Secret.
| Parameter | Type | Default | Description |
|---|---|---|---|
externalSecrets.enabled |
boolean | false |
Render an ExternalSecret for MongoDB credentials. |
externalSecrets.refreshInterval |
string | 1h |
ExternalSecret refresh interval. |
externalSecrets.secretStoreRef.name |
string | "" |
SecretStore or ClusterSecretStore name. |
externalSecrets.secretStoreRef.kind |
string | SecretStore |
Secret store kind. |
externalSecrets.data |
array | [] |
Data mappings for root credentials and backup secrets. |
Metrics
| Parameter | Type | Default | Description |
|---|---|---|---|
metrics.enabled |
boolean | false |
Deploy percona/mongodb_exporter sidecar. |
metrics.port |
integer | 9216 |
Exporter metrics port. |
metrics.serviceMonitor.enabled |
boolean | false |
Create Prometheus ServiceMonitor resource. |
When auth.enabled: false, the exporter now connects without root credentials using
mongodb://localhost:27017/admin. With authentication enabled, it keeps using the root
credentials from the chart-managed or existing secret.
Pod Security
| Parameter | Type | Default | Description |
|---|---|---|---|
automountServiceAccountToken |
boolean | false |
Mount a Kubernetes API token in pods and jobs. |
podSecurityContext.fsGroup |
integer | 999 |
Filesystem group used for MongoDB data volumes. |
podSecurityContext.seccompProfile.type |
string | RuntimeDefault |
Seccomp profile applied to MongoDB pods and jobs. |
Backup
Backup uses mongodump (not pg_dump). All databases are dumped and archived.
| Parameter | Type | Default | Description |
|---|---|---|---|
backup.enabled |
boolean | false |
Enable scheduled mongodump S3 backup. |
backup.schedule |
string | "0 3 * * *" |
Cron schedule. |
backup.s3.endpoint |
string | "" |
S3-compatible endpoint URL. |
backup.s3.bucket |
string | "" |
Target bucket name. |
backup.s3.existingSecret |
string | "" |
Existing secret with S3 credentials. |
backup.database.mongoDumpArgs |
string | "" |
Extra mongodump arguments. |
extraManifests |
array | [] |
Extra Kubernetes manifests. |
Upgrade Notes
MongoDB 9.0.4 is a patch in the 9.0 rapid-release line. Before upgrading
from 8.3, take a tested backup and confirm every member reports
featureCompatibilityVersion: "8.3". Follow the topology-specific upstream
procedure, then raise FCV to 9.0 only after all members are healthy and
rollback is no longer required. Review the
MongoDB 9.0 release notes.
The chart reuses generated root credentials and replica set keyFiles across
helm upgrade --reset-values and helm upgrade --reuse-values, and retains
them when a persistent release is removed. Back up the Secrets together with
the PVCs. Rotate credentials with MongoDB administrative commands and a
coordinated Secret update instead of changing initialization values.
StatefulSet claim-template sizes are immutable. The chart preserves each
installed template size during upgrades, including --reset-values, so a
custom-size installation does not fail when defaults are reapplied. Resize the
bound PVC through the storage class workflow; changing persistence.size alone
does not resize an existing claim or change the size used for PVCs created by
future scale-up. Before adding members after expanding existing PVCs, confirm
that the retained claim-template size can hold a new member’s initial
synchronization.
MongoDB cannot automatically convert a standalone instance to a replica set with data. You must:
- Dump the data with
mongodump. - Deploy the chart in
replicasetmode. - Restore data with
mongorestore.
Enabling or disabling arbiter.enabled reconciles the arbiter through the post-upgrade hook. Increasing
replicaSet.members adds missing members. Reducing it does not remove data-bearing members from MongoDB; follow MongoDB’s
member-removal procedure before scaling down the StatefulSet.
When arbiter reconciliation would change MongoDB’s implicit default write concern, the hook preserves the currently
effective value (w: 1 or majority) by promoting it to a global default. Existing operator-managed global defaults are
left unchanged. MongoDB 5.0 and newer do not allow a global default write concern to be unset after it is established. See
the official setDefaultRWConcern documentation.