Title
Create new category
Edit page index title
Edit category
Edit link
Deploy Pulse databases with Helm
Use the helm-databases umbrella chart to deploy Pulse database dependencies on Kubernetes by using supported operators and charts.
Supported databases
| Database | Operator or chart | Version |
|---|---|---|
| MongoDB | MongoDB Controllers for Kubernetes (MCK) | 1.7.0 |
| PostgreSQL | CloudNativePG | 0.27.1 |
| Elasticsearch | ECK Operator | 3.3.0 |
| VictoriaMetrics | VictoriaMetrics Operator | 0.58.1 |
| Redis | OpsTree Redis Operator | 0.23.0 |
| NATS | NATS Helm Chart | 1.3.16 |
Before You Begin
Make sure you have:
- Kubernetes 1.21 or later
- Helm 3.x
kubectlconfigured for your cluster- Cluster admin permissions to install CRDs and ClusterRoles
Add Helm repositories
Before installing, you must register the Helm repositories that this chart references. Run all six commands, or only the ones for the databases you plan to install:
xxxxxxxxxxhelm repo add mongodb https://mongodb.github.io/helm-chartshelm repo add cnpg https://cloudnative-pg.github.io/chartshelm repo add elastic https://helm.elastic.cohelm repo add victoriametrics https://victoriametrics.github.io/helm-charts/helm repo add ot-container-kit https://ot-container-kit.github.io/helm-chartshelm repo add nats https://nats-io.github.io/k8s/helm/charts/helm repo updateThen pull the dependency charts:
xxxxxxxxxxhelm dependency update ./helm-databasesInstallation Modes
This chart supports two install modes using the same chart.
Fresh Install: Two-Step Process
On a fresh cluster where operator CRDs do not exist yet, Helm cannot create custom resources (database instances) in the same transaction that installs the CRDs. The chart handles this automatically.
Step 1 -- Install operators + CRDs (database instances are auto-deferred)
xxxxxxxxxxhelm install pulse-db ./helm-databases \ --namespace pulse-databases \ --create-namespaceStep 2 -- Create database instances (CRDs now exist in the API)
xxxxxxxxxxhelm upgrade pulse-db ./helm-databases \ --namespace pulse-databases \ --reuse-valuesThe post-install notes will tell you when step 2 is needed. On subsequent upgrades, everything works in a single command.
Mode 1: All databases in a single namespace
Deploy every enabled database into one shared namespace. Follow the two-step process above on a fresh cluster.
xxxxxxxxxxhelm install pulse-db ./helm-databases \ --namespace pulse-databases \ --create-namespaceDisable specific databases at install time:
xxxxxxxxxxhelm install pulse-db ./helm-databases \ --namespace pulse-databases \ --create-namespace \ --set nats.enabled=false \ --set victoriametrics.enabled=falseMode 2: Each database in its own namespace
Use the convenience value files in values/ to install one database per release. The same two-step process applies per release.
MongoDB
xxxxxxxxxxhelm install pulse-mongo ./helm-databases \ -n pulse-mongo --create-namespace \ -f helm-databases/values/mongo-only.yamlPostgreSQL
xxxxxxxxxxhelm install pulse-pg ./helm-databases \ -n pulse-postgres --create-namespace \ -f helm-databases/values/postgres-only.yamlElasticsearch
xxxxxxxxxxhelm install pulse-es ./helm-databases \ -n pulse-elastic --create-namespace \ -f helm-databases/values/elastic-only.yamlVictoriaMetrics
xxxxxxxxxxhelm install pulse-vm ./helm-databases \ -n pulse-victoriametrics --create-namespace \ -f helm-databases/values/victoriametrics-only.yamlRedis
xxxxxxxxxxhelm install pulse-redis ./helm-databases \ -n pulse-redis --create-namespace \ -f helm-databases/values/redis-only.yamlNATS
xxxxxxxxxxhelm install pulse-nats ./helm-databases \ -n pulse-nats --create-namespace \ -f helm-databases/values/nats-only.yamlMongoDB Sharded Cluster
The chart supports deploying a sharded MongoDB cluster by using the Community Operator. No Ops Manager is required. Set mongodb.cr.type=shardedCluster to enable it.
The MongoDBCommunity operator does not officially support sharding. It works by deploying separate MongoDBCommunity CRs for config servers, shard servers, and mongos routers, wired together through a shared keyfile and a mongos command override. Test thoroughly before production use.
What Gets Created
When type: shardedCluster is set, the chart creates:
| Resource | Name | Description |
|---|---|---|
| Secret | {name}-shared-keyfile | Master keyfile (auto-generated or user-provided) |
| Secret (×N) | {name}-configsvr-keyfile, {name}-shard-N-keyfile, {name}-mongos-keyfile | Per-component copies of the keyfile |
| Secret | admin password secret | Shared admin credentials |
| MongoDBCommunity | {name}-configsvr | Config server replica set (clusterRole: configsvr) |
| MongoDBCommunity (×shardCount) | {name}-shard-0, {name}-shard-1, ... | Shard replica sets (clusterRole: shardsvr) |
| MongoDBCommunity | {name}-mongos | mongos query routers (command override) |
| Job (Helm hook) | {name}-add-shards | Post-install job that runs sh.addShard() for each shard |
Deploy
Step 1 -- Install the operator (same two-step process as a fresh install)
xxxxxxxxxxhelm install pulse-db ./helm-databases \ --namespace pulse-databases \ --create-namespace \ --set mongodb.cr.type=shardedClusterStep 2 -- Create the sharded cluster CRs
xxxxxxxxxxhelm upgrade pulse-db ./helm-databases \ --namespace pulse-databases \ --reuse-valuesDeploy with Custom Settings
Override shard count, router count, or provide your own keyfile:
xxxxxxxxxxhelm install pulse-db ./helm-databases \ --namespace pulse-databases \ --create-namespace \ --set mongodb.cr.type=shardedCluster \ --set mongodb.cr.shardedCluster.shardCount=3 \ --set mongodb.cr.shardedCluster.membersPerShard=3 \ --set mongodb.cr.shardedCluster.mongosCount=3 \ --set mongodb.cr.shardedCluster.configServerCount=3 \ --set mongodb.cr.auth.adminPassword=mySecurePasswordTo supply your own keyfile (must be at least 6 characters):
xxxxxxxxxxhelm install pulse-db ./helm-databases \ --namespace pulse-databases \ --create-namespace \ --set mongodb.cr.type=shardedCluster \ --set mongodb.cr.shardedCluster.keyfile.value="$(openssl rand -base64 756)"If keyfile.value is left empty, which is the default, a random keyfile is auto-generated on first install and preserved across upgrades.
Verify the Cluster
After the install and upgrade cycle, check the status of all components:
xxxxxxxxxxkubectl get mongodbcommunity -n pulse-databaseskubectl get job pulse-mongodb-add-shards -n pulse-databaseskubectl logs job/pulse-mongodb-add-shards -n pulse-databaseskubectl exec -it pulse-mongodb-mongos-0 -n pulse-databases -- \ mongosh --eval "sh.status()"Architecture Overview
xxxxxxxxxx┌──────────────────────────────────────────────────────────┐│ Client Applications │└───────────────────────────┬──────────────────────────────┘ │ ┌─────────────▼─────────────┐ │ pulse-mongodb-mongos │ │ (mongos query routers) │ │ N = mongosCount │ └──┬──────────────────────┬──┘ │ │ ┌────────────▼──────────┐ ┌───────▼────────────────┐ │ pulse-mongodb-shard-0 │ │ pulse-mongodb-shard-N │ │ (shardsvr replset) │ │ (shardsvr replset) │ │ M = membersPerShard │ │ M = membersPerShard │ └───────────────────────┘ └─────────────────────────┘ │ │ ┌───────────────────────────────────┐ │ pulse-mongodb-configsvr │ │ (configsvr replica set) │ │ N = configServerCount │ └───────────────────────────────────┘All components share a common keyfile for internal authentication.
Using a Self-Hosted / Mirror Chart Repository
The Chart.yaml references repositories by using Helm aliases, such as @mongodb. To point at your own mirror, re-add the alias before running helm dependency update.
xxxxxxxxxxhelm repo add mongodb https://my-internal-registry.example.com/mongodb-chartshelm repo add elastic https://my-internal-registry.example.com/elastic-chartshelm dependency update ./helm-databasesEach repository alias can be overridden independently, which gives you per-database control over the chart source.
Configuration
Global Values
| Parameter | Description | Default |
|---|---|---|
global.imagePullSecrets | Image pull secrets for operator pods | [] |
global.openshift | Enable OpenShift-compatible security contexts | false |
Per-Database Values
Each database section in values.yaml has the same structure:
xxxxxxxxxx<database>: enabled: true <operator-alias>: {} cr: create: true name: pulse-<database> ...MongoDB
| Parameter | Description | Default |
|---|---|---|
mongodb.enabled | Deploy MCK operator + instance | true |
mongodb.cr.create | Create MongoDB CR(s) | true |
mongodb.cr.name | Instance name (base name for sharded components) | pulse-mongodb |
mongodb.cr.type | replicaSet or shardedCluster | replicaSet |
mongodb.cr.version | MongoDB version | 7.0.14 |
mongodb.cr.replicaSet.members | Replica set members (replicaSet mode) | 3 |
mongodb.cr.shardedCluster.shardCount | Number of shard replica sets | 2 |
mongodb.cr.shardedCluster.membersPerShard | Members per shard replica set | 3 |
mongodb.cr.shardedCluster.mongosCount | mongos router instances | 2 |
mongodb.cr.shardedCluster.configServerCount | Config server replica set members | 3 |
mongodb.cr.shardedCluster.keyfile.value | Custom keyfile string (auto-generated if empty) | "" |
mongodb.cr.storage.size | Data volume size | 10Gi |
mongodb.cr.auth.adminUser | Default admin username | pulse-admin |
mongodb.cr.auth.adminPassword | Default admin password (CHANGE THIS) | changeme |
PostgreSQL (CloudNativePG)
| Parameter | Description | Default |
|---|---|---|
postgresql.enabled | Deploy CNPG operator + cluster | true |
postgresql.cr.create | Create Cluster CR | true |
postgresql.cr.name | Cluster name | pulse-postgresql |
postgresql.cr.instances | Number of instances | 3 |
postgresql.cr.version | PostgreSQL major version | 16 |
postgresql.cr.storage.size | Data volume size | 10Gi |
postgresql.cr.bootstrap.database | Initial database name | pulse |
postgresql.cr.bootstrap.owner | Database owner | pulse |
Elasticsearch (ECK)
| Parameter | Description | Default |
|---|---|---|
elasticsearch.enabled | Deploy ECK operator + cluster | true |
elasticsearch.cr.create | Create Elasticsearch CR | true |
elasticsearch.cr.name | Cluster name | pulse-elasticsearch |
elasticsearch.cr.version | Elasticsearch version | 8.17.0 |
elasticsearch.cr.nodeSets | Node set definitions (count, storage, resources) | 1 set, 3 nodes, 20Gi |
VictoriaMetrics
| Parameter | Description | Default |
|---|---|---|
victoriametrics.enabled | Deploy VM operator + instance | true |
victoriametrics.cr.create | Create VMSingle CR | true |
victoriametrics.cr.name | Instance name | pulse-victoriametrics |
victoriametrics.cr.retentionPeriod | Data retention period | 30d |
victoriametrics.cr.storage.size | Data volume size | 10Gi |
Redis (OpsTree)
| Parameter | Description | Default |
|---|---|---|
redis.enabled | Deploy Redis operator + instance | true |
redis.cr.create | Create Redis CR | true |
redis.cr.name | Instance name | pulse-redis |
redis.cr.mode | Deployment mode: standalone, cluster, replication, sentinel | standalone |
redis.cr.clusterSize | Nodes (for cluster, replication, sentinel modes) | 3 |
redis.cr.version | Redis image tag | v7.2.6 |
redis.cr.storage.size | Data volume size | 5Gi |
redis.cr.exporter.enabled | Enable Prometheus exporter sidecar | true |
NATS
nats.enabled | Deploy NATS | true |
nats.global.image.pullSecretNames | List of image pull secret names for private registries | [] |
nats.container.image.repository | Custom NATS server image repository | nats |
nats.container.image.tag | Custom NATS server image tag | 2.11.10-alpine |
nats.container.image.registry | Custom image registry (overrides Docker Hub) | "" |
nats.container.image.fullImageName | Full image name (overrides registry + repo + tag) | "" |
nats.natsBox.enabled | Deploy nats-box diagnostic toolbox | false |
nats.config.cluster.enabled | Enable NATS clustering | true |
nats.config.cluster.replicas | Cluster replicas | 3 |
nats.config.jetstream.enabled | Enable JetStream persistence | true |
nats.config.jetstream.fileStore.pvc.size | JetStream PVC size | 5Gi |
For full NATS chart values, see the official NATS chart docs.
Operator-Only Install
To deploy only the operators without creating database instances, which is useful for shared operator installations, set cr.create: false:
xxxxxxxxxxhelm install pulse-db ./helm-databases \ --namespace pulse-databases \ --create-namespace \ --set mongodb.cr.create=false \ --set postgresql.cr.create=false \ --set elasticsearch.cr.create=false \ --set victoriametrics.cr.create=false \ --set redis.cr.create=falseYou can then create database instances separately by applying CRs with kubectl.
Skipping CRD Installation
If CRDs already exist in the cluster, from a prior install or another release, you may get ownership conflicts. Use these options to skip CRD installation:
xxxxxxxxxxhelm install pulse-db ./helm-databases \ --namespace pulse-databases \ --create-namespace \ --skip-crds \ --set postgresql.crds.create=false \ --set elasticsearch.installCRDs=false \ --set victoriametrics.crds.enabled=false| Database | How to skip CRDs |
|---|---|
| MongoDB | --skip-crds flag (MCK uses Helm-native crds/ directory) |
| PostgreSQL | postgresql.crds.create=false |
| Elasticsearch | elasticsearch.installCRDs=false |
| VictoriaMetrics | victoriametrics.crds.enabled=false |
| Redis | --skip-crds flag (CRDs are in Helm-native crds/ directory) |
| NATS | No CRDs |
Alternatively, adopt existing CRDs into your release:
xxxxxxxxxxkubectl label crd mongodbcommunity.mongodbcommunity.mongodb.com \ app.kubernetes.io/managed-by=Helm kubectl annotate crd mongodbcommunity.mongodbcommunity.mongodb.com \ meta.helm.sh/release-name=<RELEASE_NAME> \ meta.helm.sh/release-namespace=<NAMESPACE>OpenShift Support
Set global.openshift=true to enable OpenShift-compatible settings:
xxxxxxxxxxhelm install pulse-db ./helm-databases \ --namespace pulse-databases \ --create-namespace \ --set global.openshift=true \ --set postgresql.containerSecurityContext.runAsUser=null \ --set postgresql.containerSecurityContext.runAsGroup=nullThis will:
- Remove fixed
runAsUser/runAsGroupsettings from all CR pod templates (MongoDB, Elasticsearch, Redis, VictoriaMetrics, PostgreSQL) - Let OpenShift Security Context Constraints (SCCs) assign UIDs
- Avoid
privileged: truein all workloads
Built-in OpenShift support per operator
| Operator | OpenShift handling |
|---|---|
| ECK | Auto-detects OpenShift via config.setDefaultSecurityContext: "auto-detect" |
| VictoriaMetrics | Auto-adapts via global.compatibility.openshift.adaptSecurityContext: "auto" |
| OpsTree Redis | Built-in OpenShift support (openshift chart keyword) |
| CloudNativePG | Set postgresql.containerSecurityContext.runAsUser=null to clear hardcoded UID |
| MongoDB | CR template clears securityContext when global.openshift=true |
| NATS | Standard securityContext, runs as non-root by default |
Upgrading
xxxxxxxxxxhelm dependency update ./helm-databases helm upgrade pulse-db ./helm-databases \ --namespace pulse-databasesUninstalling
xxxxxxxxxxhelm uninstall pulse-db --namespace pulse-databasesCRDs are not automatically removed by Helm.
To remove CRDs manually, which deletes all custom resources, run:
kubectl get crd | grep -E 'mongodb|cnpg|elastic|victoriametrics|redis.opstreelabs' | awk '{print $1}' | xargs kubectl delete crdCommands to Install Databases on OpenShift
MongoDB
xxxxxxxxxxhelm install pulse-mongo ./helm-databases \ -n pulse-mongo --create-namespace \ -f helm-databases/values/mongo-only.yaml \ --set mongodb.cr.version="8.0.18" \ --set mongodb.cr.mongodImage="191579300362.dkr.ecr.us-east-1.amazonaws.com/acceldata/ad-database:testBuild-k8sqe" \ --set global.openshift=true \ --set mongodb.managedSecurityContext=true \ --set global.imagePullSecrets[0]=adreg \ --set mongodb.registry.imagePullSecrets=adreg \ --set global.imagePullPolicy=IfNotPresent \ --set global.storageClassName='gp2-csi' \ --set global.imageCredentials.password='<REDACTED_EXISTING_SECRET>' \ --set mongodb.cr.storage.size=50Gi \ --set mongodb.cr.resources.limits.cpu=1 \ --set mongodb.cr.resources.limits.memory=4Gi \ --set mongodb.cr.resources.requests.cpu=500m \ --set mongodb.cr.resources.requests.memory=2Gi \ --timeout 20mVictoriaMetrics
xxxxxxxxxxhelm install pulse-vm ./helm-databases \ -n pulse-vm --create-namespace \ --set victoriametrics.cr.auth.username=acceldata \ --set 'victoriametrics.cr.auth.password=D@t@Ops' \ --set mongodb.managedSecurityContext=true \ --set global.openshift=true \ --set nats.global.image.pullSecretNames[0]=adreg \ --set global.storageClassName='gp2-csi' \ --set global.imageCredentials.password='<REDACTED_EXISTING_SECRET>' \ --set victoriametrics.cr.vmstorage.storage.size=50Gi \ --set victoriametrics.cr.vmstorage.resources.limits.cpu=1 \ --set victoriametrics.cr.vmstorage.resources.limits.memory=4Gi \ --set victoriametrics.cr.vmstorage.resources.requests.cpu=500m \ --set victoriametrics.cr.vmstorage.resources.requests.memory=1Gi \ --set victoriametrics.cr.vmselect.storage.size=10Gi \ --set victoriametrics.cr.vmselect.resources.limits.cpu=1 \ --set victoriametrics.cr.vmselect.resources.limits.memory=2Gi \ --set victoriametrics.cr.vmselect.resources.requests.cpu=500m \ --set victoriametrics.cr.vmselect.resources.requests.memory=512Mi \ --set victoriametrics.cr.vminsert.resources.limits.cpu=1 \ --set victoriametrics.cr.vminsert.resources.limits.memory=2Gi \ --set victoriametrics.cr.vminsert.resources.requests.cpu=500m \ --set victoriametrics.cr.vminsert.resources.requests.memory=512Mi \ -f helm-databases/values/victoriametrics-only.yamlxxxxxxxxxxhelm upgrade pulse-vm ./helm-databases \ --namespace pulse-vm \ --reuse-valuesElastic
xxxxxxxxxxhelm install pulse-es ./helm-databases \ -n pulse-es --create-namespace \ --set global.openshift=true \ --set mongodb.managedSecurityContext=true \ --set elasticsearch.cr.auth.password="admin_password" \ --set elasticsearch.cr.auth.additionalUsers[0].username=pulse \ --set elasticsearch.cr.auth.additionalUsers[0].password="data@ops" \ --set elasticsearch.cr.auth.additionalUsers[0].roles[0]=superuser \ --set elasticsearch.cr.tls.p12.password="" \ --set elasticsearch.cr.httpPort=19013 \ --set elasticsearch.cr.tls.disabled=true \ --set nats.global.image.pullSecretNames[1]=adreg \ --set global.storageClassName='gp2-csi' \ --set global.imageCredentials.password='<REDACTED_EXISTING_SECRET>' \ --set elasticsearch.cr.nodeSets[0].name=default \ --set elasticsearch.cr.nodeSets[0].count=3 \ --set elasticsearch.cr.nodeSets[0].config.node\\.store\\.allow_mmap=true \ --set elasticsearch.cr.nodeSets[0].storage.size=50Gi \ --set elasticsearch.cr.nodeSets[0].resources.limits.cpu=1 \ --set elasticsearch.cr.nodeSets[0].resources.limits.memory=8Gi \ --set elasticsearch.cr.nodeSets[0].resources.requests.cpu=500m \ --set elasticsearch.cr.nodeSets[0].resources.requests.memory=4Gi \ -f helm-databases/values/elastic-only.yamlxxxxxxxxxxhelm upgrade pulse-es ./helm-databases \ --namespace pulse-es \ --reuse-valuesxxxxxxxxxxkubectl port-forward svc/pulse-elasticsearch-es-http -n pulse-es 19013:19013xxxxxxxxxxcurl -s -u "pulse:data@ops" \ -X PUT "http://localhost:19013/_index_template/pulse-defaults" \ -H 'Content-Type: application/json' \ -d '{ "index_patterns": ["*"], "priority": 1, "template": { "settings": { "number_of_replicas": 1 } } }'Postgres
xxxxxxxxxxhelm install pulse-pg ./helm-databases \ -n pulse-pg --create-namespace \ -f helm-databases/values/postgres-only.yaml \ --set postgresql.useOperator=false \ --set nats.global.image.pullSecretNames[0]=adreg \ --set global.storageClassName='gp2-csi' \ --set global.imageCredentials.password='<REDACTED_EXISTING_SECRET>' \ --set postgresql.standalone.storage.size=50Gi \ --set postgresql.standalone.resources.limits.cpu=1 \ --set postgresql.standalone.resources.limits.memory=4Gi \ --set postgresql.standalone.resources.requests.cpu=500m \ --set postgresql.standalone.resources.requests.memory=2Gi \ -f helm-databases/values/openshift.yamlNATS
xxxxxxxxxxhelm install pulse-nats ./helm-databases \ -n pulse-nats --create-namespace \ --set global.openshift=true \ -f helm-databases/values/nats-only.yaml \ --set nats.global.image.pullSecretNames[0]=adreg \ --set nats.loadBalancer.enabled=true \ --set global.storageClassName='gp2-csi' \ --set nats.config.jetstream.fileStore.pvc.storageClassName='gp2-csi' \ --set global.imageCredentials.password='<REDACTED_EXISTING_SECRET>' \ --set nats.config.jetstream.fileStore.pvc.size=20Gi \ --set nats.container.merge.resources.limits.cpu=1 \ --set nats.container.merge.resources.limits.memory=4Gi \ --set nats.container.merge.resources.requests.cpu=500m \ --set nats.container.merge.resources.requests.memory=2GiFor additional help, contact www.acceldata.force.com OR call our service desk +1 844 9433282
Copyright © 2026