Installing Sisense with Helm on an Existing Cluster (Multinode/Cloud)
Last updated: October 21, 2026
| Tier | Deployment |
|
|
You can install Sisense with Helm directly on a Kubernetes cluster that you already run: a cloud-managed cluster (Amazon EKS, Azure AKS, or Google GKE), an OpenShift cluster, or any other cluster that you manage. You install the Sisense Helm chart yourself, without the sisense.sh script. This is the recommended path for installing Sisense on an existing cluster.
To compare this method with the other installation methods, see Choosing an Installation Method. To install on a single server that stores the Sisense data on its own disk, see Manually Installing Sisense Helm Chart - Single Node.
When to Use This Method
Use this method when:
-
You already have a Kubernetes cluster, and Sisense runs in a namespace on it.
-
The cluster is shared with other workloads, or is governed by your own admission and RBAC policies.
-
No Linux machine can be given
sudo, or your operators work on Windows or macOS.
This method does not need a Linux install host, a Linux user, an SSH key, or sudo anywhere. Nothing runs on the cluster nodes. Run the commands from any computer with kubectl and helm and cluster-admin access to the cluster.
When you install with Helm directly, you perform the steps that sisense.sh would otherwise perform for you:
| What sisense.sh does | What you do instead |
|---|---|
| Creates the Sisense namespace. | Create the namespace with kubectl create namespace. |
| Labels the nodes with the Sisense node labels. | Label your node pool. See Labeling the Nodes. |
| Checks that every node can run at least 58 pods. | Check the pod capacity yourself. Helm does not check it. See Prerequisites. |
| Installs storage drivers and StorageClasses. | Use your existing ReadWriteMany (RWX) and ReadWriteOnce (RWO) StorageClasses, and name them in the values file. |
| When SSL is enabled, installs NGINX Gateway Fabric with a Gateway and a TLS secret. | Use your own Gateway, Ingress controller, or load balancer. See Exposing Sisense. |
| When enabled, installs Sisense internal monitoring and logging. | Optional. Install them separately. See Internal Monitoring. |
| Generates a complete values file and passes it on every upgrade. | Keep one complete values file under version control, and pass it on every helm upgrade. |
Prerequisites
-
General prerequisites: Checking the Prerequisites and Planning Your Configuration.
-
A running Kubernetes cluster, and a computer with
kubectlconfigured for that cluster (you can run commands such askubectl get nodes). -
Helm 3.13 or later. The chart reads live cluster objects while it renders, so you preview an installation with
helm install --dry-run=server, which requires Helm 3.13 or later. -
Kubernetes permissions for the identity that runs
helm. See Kubernetes Permissions. -
Each node that runs Sisense can run at least 58 pods. Helm does not check this. To see the pod capacity of your nodes, run:
Copykubectl get nodes -o custom-columns=NAME:.metadata.name,PODS:.status.capacity.pods -
Two StorageClasses (you can use one StorageClass for both if it supports both access modes):
-
A ReadWriteMany (RWX) StorageClass for the shared Sisense volume, a PVC named
storagethat all the Sisense services mount. -
A ReadWriteOnce (RWO) StorageClass for MongoDB, ZooKeeper, Dgraph, MongoDB Search, and Grafana.
For the requirements per platform, see Storage Requirements for Self-Deployment.
Storage Class installation exampleFor this example, assume there is an NFS server with an NFS path, so we will install an NFS Storage Class, and we will use it for both
RWXandRWO.CopySTORAGE_NAMESPACE=kube-system
helm repo add csi-driver-nfs https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts
helm install csi-driver-nfs -n ${STORAGE_NAMESPACE} csi-driver-nfs/csi-driver-nfs --version v4.4.0
kubectl --namespace=${STORAGE_NAMESPACE} get pods --selector="app.kubernetes.io/instance=csi-driver-nfs" --watch
# Wait until all pods are "Running" and then hit CTRL+CCreate the file
storageclass-nfs.yamlwith the following content:(Example for NFS server:
10.192.168.32)(Example for NFS path:
/mnt/share)Copy---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
server: <Your NFS server address>
share: <Your NFS server path>
# csi.storage.k8s.io/provisioner-secret is only needed for providing mountOptions in DeleteVolume
# csi.storage.k8s.io/provisioner-secret-name: "mount-options"
# csi.storage.k8s.io/provisioner-secret-namespace: "default"
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
- nfsvers=4.1Create the Storage Class
nfs-csiwith the following command:Copykubectl apply -f storageclass-nfs.yaml
# See that Storage Class is created:
kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-csi nfs.csi.k8s.io Delete Immediate false 43s -
-
Access from the nodes to the Sisense images in
quay.io/sisense_release, or a mirror of the images in your own registry (setglobal.imageRegistryandglobal.imagePullSecrets). -
A way to expose Sisense to users. See Exposing Sisense.
Kubernetes Permissions
The identity that runs helm creates every object that the chart renders. With the default global.clusterVisibility: true, these include ClusterRoles and ClusterRoleBindings, so use an identity with cluster-admin rights.
The chart also reads cluster-scoped objects while it renders, even in a namespace-scoped installation: it lists the cluster nodes and reads the namespace named monitoring. The identity therefore needs at least list on nodes and get on namespaces. If a namespace named monitoring exists, the chart also creates a Role and a RoleBinding in it.
To install Sisense without any cluster-wide RBAC for the Sisense services, see Installing Sisense without ClusterVisibility. For a full list of the privileges per installation method, see Privileges and Permissions for Self-Deployment.
Labeling the Nodes
Every Sisense platform pod requires a node with the following label, where <namespace> is the namespace that you install Sisense into:
node-<namespace>-Application=true
Pods do not schedule on nodes without this label. Note the following:
-
The label key is case-sensitive:
Applicationhas a capital A, and the value istrue. For example, for the namespacesisense, the label isnode-sisense-Application=true. -
Label the node pool or node group (in the AKS, EKS, or GKE node pool settings, or the equivalent in your platform), not individual nodes. A label that you add with
kubectl label nodeis lost when the autoscaler replaces the node, and the new node does not accept Sisense pods. On a cloud-managed cluster or OpenShift, you may not be able to usekubectl label nodeat all; use the provider's UI or CLI. -
sisense.sh also applies the role labels
node-<namespace>-Build=trueandnode-<namespace>-Query=true. These labels do not make a node eligible for Sisense platform pods; only the-Applicationlabel does. To keep the same labels as an installation with sisense.sh, you can add them to the nodes that should run ElastiCube builds and queries.
For example, on a cluster where you can label nodes directly:
NAMESPACE=sisense # for example
kubectl label node ${your_node_1} node-${NAMESPACE}-Application=true --overwrite=true
kubectl label node ${your_node_2} node-${NAMESPACE}-Application=true --overwrite=true
kubectl label node ${your_node_3} node-${NAMESPACE}-Application=true --overwrite=true
# Check which nodes carry the label:
kubectl get nodes -l node-${NAMESPACE}-Application=true
Note:
Nodes in cloud-managed node pools normally have no control-plane taint. If you want Sisense pods to run on control-plane nodes of a cluster that you manage yourself, remove their NoSchedule taint (for example, node-role.kubernetes.io/control-plane:NoSchedule or node-role.kubernetes.io/master:NoSchedule).
Preparing the Values File
Download the sample values file: multinode-values.yaml. The comments in the file explain each value. The file does not contain your namespace name, so you can use it for any namespace without editing namespace references.
For all the available parameters, see Sisense Helm Chart Parameters.
Values You Must Set
The chart defaults describe a single-node installation. On a multinode or cloud-managed cluster, set the following values. The sample file already contains them; replace the placeholders in angle brackets.
| Value | Set to | Why |
|---|---|---|
global.clusterMode.enabled
|
true
|
The default false mounts hostPath directories on the nodes. With true, all the services use the shared RWX volume, MongoDB, ZooKeeper, and Dgraph run as StatefulSets with their own volumes, and the pods are scheduled only on labeled nodes. |
global.storageClass
|
Your RWO StorageClass name (for example, gp3, managed-csi, or standard-rwo) |
MongoDB, ZooKeeper, Dgraph, and MongoDB Search create their volumes with this class. The default manual is only for single node; with it, these PVCs stay Pending. |
global.storageType
|
efs, fsx, nfs, azurefile, rook-ceph, or custom-rwx |
Describes the RWX storage. If you leave it empty, the build, query, and management services treat the storage as hostPath. Use Only |
sisense-utils.rwxScName
|
Your RWX StorageClass name | The StorageClass of the shared storage PVC. It overrides the class names that the chart derives from global.storageType or from global.kubernetesCloudProvider: azure. If no class is selected, the PVC uses the cluster default StorageClass, which must then support ReadWriteMany. |
mongodb.architecture and mongodb.replicaCount |
replicaset, and 3 (or 1 when global.highAvailability is false) |
The default standalone creates a MongoDB Deployment that waits for a single-node PVC (data-mongodb-0) that does not exist in cluster mode, so MongoDB stays Pending. |
zookeeper.replicaCount
|
3 (or 1 when global.highAvailability is false) |
The default is one ZooKeeper server. The chart builds the ZooKeeper ensemble from this value. Do not add a zookeeper.configuration block with server.N lines; set tunables such as zookeeper.maxClientCnxns as plain values. |
rabbitmq.replicaCount
|
3 (or 1, with rabbitmq.clustering.enabled: false, when global.highAvailability is false) |
The default is one RabbitMQ server. |
global.isKubernetesCloud and global.kubernetesCloudProvider |
On EKS, AKS, or GKE: true, and aws, azure, or gke |
Used for the internal load balancer annotations and for Azure Files sizing. The value for Google is gke. With azure, the shared volume requests at least sisense-utils.azureDefaultDiskSize (default 1200 Gi). |
global.isOpenshift
|
On OpenShift: true |
On OpenShift, also remove global.securityContext.seLinuxOptions from the values file and set sisense-utils.rwxScName. |
grafana.persistence.storageClassName
|
Optional: your RWO StorageClass name | Grafana does not use global.storageClass. If you do not set this value, Grafana uses the cluster default StorageClass. |
Also set the exposure values (see Exposing Sisense), and change any other values that you need, for example global.securityContext (runAsUser, runAsGroup), global.deploymentSize, or sisense-utils.timezone.
Namespace and Release Name
-
Use the namespace name as the Helm release name, as sisense.sh does. Several object names derive from the release name (for example,
<release>-mongodband<release>-zookeeper), so keep the same release name for the life of the installation. -
The sample file has no namespace references. The only namespace-dependent items in it are optional and commented out:
-
Node affinity blocks for MongoDB, ZooKeeper, RabbitMQ, and Grafana, which keep these pods on the Sisense nodes. Their label key contains the namespace (
node-<namespace>-Application). The other Sisense pods get this affinity from the chart automatically. -
The Grafana admin credentials. The chart defaults are
user-sisenseandpasswd-sisense. The Sisense API gateway signs in to this Grafana asuser-<namespace>/passwd-<namespace>, so if your namespace is notsisense, set them to match your namespace (for example,user-mynamespaceandpasswd-mynamespace). Do not set other values, or the Grafana dashboards in Sisense stop working.
-
-
If you reuse a values file from an earlier version of this page, remove its
zookeeper.configurationblock. Itsserver.Nlines contain host names that depend on the release name and namespace, and wrong host names prevent the ZooKeeper servers from forming a quorum.
Namespace-Scoped Installation
If Sisense must not have any cluster-wide permissions, install it in namespace-scoped mode. Set global.clusterVisibility: false and grafana.rbac.namespaced: true (or grafana.enabled: false). For what this mode turns off, see Installing Sisense without ClusterVisibility.
Internal Monitoring
If you want to use Sisense internal monitoring, install it first. See Installing/Updating Sisense Internal Monitoring. Internal monitoring is not supported in namespace-scoped mode. Then set the following values (they are commented out in the sample file):
-
global.monitoring.internal: true -
mongodb.metrics.enabled,rabbitmq.metrics.enabled, andzookeeper.metrics.enabled:true. These create ServiceMonitor objects, which require the Prometheus Operator CRDs that internal monitoring installs. Setmongodb.metrics.serviceMonitor.namespaceto your monitoring namespace. -
sisense-utils.monitoring_namespace: your monitoring namespace (defaultmonitoring). -
The Grafana Prometheus datasource
url:http://sisense-prom-operator-kube-prometheus.<monitoring-namespace>.svc:9090.
Without internal monitoring, keep all of these values off. The installation then does not need the Prometheus Operator CRDs.
Exposing Sisense
Two values must match the way users reach Sisense:
-
global.external_kube_apiserver_address: the full URL that users open in the browser, including the scheme and, if needed, the port. Sisense uses it as its system address. For example,https://sisense.example.comorhttp://10.0.0.5:30845. -
global.applicationDnsName: the host name only, without scheme or port, for examplesisense.example.com. The chart uses it as the host of the Ingress or HTTPRoute.
Choose one of the following options:
| Option | Values | Result |
|---|---|---|
| Gateway API HTTPRoute (recommended for HTTPS) | global.ssl.enabled: true, api-gateway.httpRoute.enabled: true, api-gateway.httpRoute.gatewayName, api-gateway.httpRoute.gatewayNamespace, and global.applicationDnsName |
The chart creates an HTTPRoute that attaches to a Gateway that you already have; the chart does not create the Gateway. global.applicationDnsName must be a host name, not an IP address. With an HTTPRoute, the chart also creates NGINX Gateway Fabric resources; if your Gateway is not NGINX Gateway Fabric, disable them. See Manually Installing Sisense Helm Chart - with SSL. |
| Cloud LoadBalancer (HTTP) | global.cloudLoadBalancer.enabled: true, optionally global.cloudLoadBalancer.isInternal: true with global.kubernetesCloudProvider set |
The service api-gateway-external becomes a LoadBalancer service on port 80, without TLS. isInternal adds the internal load balancer annotation for aws, azure, or gke. Do not combine with an HTTPRoute (the service is then not a LoadBalancer) or with global.ssl.enabled: true. |
| NodePort (default) | None; optionally global.gatewayPort (default 30845) |
The service api-gateway is a NodePort service on global.gatewayPort. Used when SSL, the cloud LoadBalancer, and the AWS ALB options are off, and global.gatewayPort is not 80. Set global.external_kube_apiserver_address to http://<node-address>:30845. |
| Ingress | api-gateway.ingress.enabled: true with api-gateway.ingress.annotations, or api-gateway.ingress.awsAlb: true with api-gateway.ingress.certificateArn, and global.applicationDnsName |
The chart creates an Ingress named sisense-ingress for global.applicationDnsName. The Ingress has no tls section, so TLS must be terminated by the Ingress controller or the load balancer (for example, an ALB certificate). When no HTTPRoute is enabled, the chart also creates this Ingress if global.ssl.enabled is true or global.gatewayPort is 80. |
Sisense Helm Chart Installation
-
Add the Sisense Helm repository, and run a quick update to sync with the remote repository:
Copyhelm repo add sisense-fusion https://data.sisense.com/linux/helm/charts/fusion
helm repo update -
List the available chart versions. Use the value in the CHART VERSION column, for example
2026.4.0, as the chart version in the following commands.Copyhelm search repo sisense-fusion/sisense --versions | head -
Create the namespace, and check that the nodes are labeled and that your StorageClasses exist:
CopyNAMESPACE=sisense # your namespace; also used as the release name
SISENSE_SEMVER=2026.4.0 # the chart version from the previous step
kubectl create namespace ${NAMESPACE}
kubectl get nodes -l node-${NAMESPACE}-Application=true # must list your Sisense nodes
kubectl get storageclass # must list your RWX and RWO classes -
Preview the installation. A server-side dry run renders the chart against your cluster without creating anything:
Copyhelm install ${NAMESPACE} sisense-fusion/sisense --version ${SISENSE_SEMVER} \
-n ${NAMESPACE} -f multinode-values.yaml --dry-run=server > sisense-render.yaml
grep -c 'hostPath:' sisense-render.yaml # expect 0 in cluster mode
grep -c '^kind: ClusterRole$' sisense-render.yaml # expect 0 in namespace-scoped mode
grep -A1 'KUBE_STORAGE_TYPE' sisense-render.yaml | grep -c hostpath # expect 0 -
Install Sisense using the values file:
Copyhelm upgrade --install ${NAMESPACE} sisense-fusion/sisense --version ${SISENSE_SEMVER} \
-n ${NAMESPACE} -f multinode-values.yaml --timeout 30m
After the post-install job completes, the following message appears (the message could be slightly different, depending on given values; for example, if using a LoadBalancer):
Continue with Post Installation.
Upgrading an Existing Sisense Installation
To upgrade, run the same command as for the installation, with the new chart version:
NAMESPACE=sisense # your namespace
RELEASE=sisense # the release name of the existing installation (see: helm list -n ${NAMESPACE})
SISENSE_SEMVER=<new chart version>
helm upgrade ${RELEASE} sisense-fusion/sisense --version ${SISENSE_SEMVER} \
-n ${NAMESPACE} -f multinode-values.yaml --timeout 30m
-
Always pass your complete values file. Do not use
--reuse-values: new chart versions can change default values, and--reuse-valueskeeps the old ones. -
Use the release name of the existing installation. Earlier versions of this page installed the release with the name
sisense. -
To preview the upgrade, run the same command with
--dry-run=server. -
Check the release notes for the versions between your current version and the new one. If the running MongoDB is older than version 7, the chart stops the upgrade with the message
Your current Sisense version is too old. Please first upgrade to Sisense version L2025.2.0, and then proceed with the newer installation.Upgrade to L2025.2.0 first, and then to the new version. -
Before every upgrade, a job adjusts the ownership of the files on the shared volume. On large volumes this can take time; increase
--timeoutif needed.
Post Installation
When you see the message above, the Sisense app is undergoing the deployment process. Use the following command to follow its progress until it is completed:
kubectl logs -f --namespace ${NAMESPACE} -l app.kubernetes.io/name=validator
Initially, you can see the services as they are being deployed:
When all of the services are up, the message Sisense installation process completed successfully appears.
To check the installation, run the following commands:
kubectl -n ${NAMESPACE} get pvc # all PVCs are Bound
kubectl -n ${NAMESPACE} get pods # no pods remain Pending
kubectl -n ${NAMESPACE} get svc api-gateway-external # LoadBalancer address, if you use a cloud LoadBalancer
kubectl -n ${NAMESPACE} get httproute,ingress # if you use an HTTPRoute or an Ingress
Once the installation is complete, some Sisense pods will remain in the Init state until the license activation. To activate the license, navigate to the Sisense web application URL (without extra paths such as /app/account/login) in your browser and enter your license credentials.
Enter your Sisense address, and run the activation.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Most pods are Pending, and the events say that no nodes match the node affinity. |
The node-<namespace>-Application=true label is missing or misspelled, or was lost when a node was replaced. |
Label the node pool. Check the namespace in the key and the capital A. See Labeling the Nodes. |
The PVCs of MongoDB, ZooKeeper, Dgraph, or MongoDB Search are Pending. |
global.storageClass is still manual, or the class does not exist or has no provisioner. |
Set global.storageClass to an existing RWO StorageClass. |
The PVC storage is Pending. |
No RWX StorageClass is selected, or the selected class does not support ReadWriteMany or does not exist. | Set sisense-utils.rwxScName to an existing RWX StorageClass. |
MongoDB runs as a Deployment (not a StatefulSet) and waits for the claim data-mongodb-0. |
mongodb.architecture is not set to replicaset. |
Set mongodb.architecture: replicaset and mongodb.replicaCount. |
helm install fails with nodes is forbidden or namespaces "monitoring" is forbidden. |
The identity that runs helm cannot read the cluster-scoped objects that the chart reads while it renders. |
Grant list on nodes and get on namespaces. See Kubernetes Permissions. |
helm install fails because creating a ClusterRole is forbidden. |
The identity has no cluster-wide rights, but global.clusterVisibility is still true, or Grafana is not namespaced. |
Use an identity with cluster-admin rights, or install in namespace-scoped mode. See Installing Sisense without ClusterVisibility. |
helm install fails with global.applicationDnsName (...) must be a hostname, not an IP address or Must provide global.applicationDnsName. |
An HTTPRoute is enabled, and global.applicationDnsName is empty or an IP address. |
Set global.applicationDnsName to a host name, or choose another exposure option. See Exposing Sisense. |
helm install fails with no matches for kind (for example, ClientSettingsPolicy or ServiceMonitor). |
An option that needs the NGINX Gateway Fabric or Prometheus Operator CRDs is enabled, but the CRDs are not installed. | Install the CRDs, or disable the option: api-gateway.clientSettingsPolicy.enabled, api-gateway.upstreamSettingsPolicy.enabled, and api-gateway.snippetsFilter.enabled for NGINX Gateway Fabric; the metrics.enabled values for Prometheus. |
kubectl -n ${NAMESPACE} describe deployment query shows KUBE_STORAGE_TYPE: hostpath. |
global.storageType is empty. |
Set global.storageType (for example, custom-rwx) and run helm upgrade. |
| The Sisense web application does not load. | The exposure values do not match the way users reach Sisense, or the installation has not completed. | Check the validator log (see Post Installation), and check global.external_kube_apiserver_address and global.applicationDnsName. |