Installing Sisense with Helm on an Existing Cluster (Multinode/Cloud)

Last updated: October 21, 2026

Tier Deployment
Enterprise On-Prem

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 kubectl configured for that cluster (you can run commands such as kubectl 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:

    Copy
    kubectl 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 storage that 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.

  • Access from the nodes to the Sisense images in quay.io/sisense_release, or a mirror of the images in your own registry (set global.imageRegistry and global.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: Application has a capital A, and the value is true. For example, for the namespace sisense, the label is node-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 node is 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 use kubectl label node at all; use the provider's UI or CLI.

  • sisense.sh also applies the role labels node-<namespace>-Build=true and node-<namespace>-Query=true. These labels do not make a node eligible for Sisense platform pods; only the -Application label 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:

Copy
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 custom-rwx for any RWX class that you name in sisense-utils.rwxScName.

Only fsx changes how Sisense works; it also requires sisense-utils.fsxDnsName and sisense-utils.fsxMountName. If you do not set sisense-utils.rwxScName, the values efs, fsx, nfs, and rook-ceph expect StorageClasses named aws-efs, aws-fsx, nfs-csi, and rook-cephfs-r3.

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>-mongodb and <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-sisense and passwd-sisense. The Sisense API gateway signs in to this Grafana as user-<namespace> / passwd-<namespace>, so if your namespace is not sisense, set them to match your namespace (for example, user-mynamespace and passwd-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.configuration block. Its server.N lines 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, and zookeeper.metrics.enabled: true. These create ServiceMonitor objects, which require the Prometheus Operator CRDs that internal monitoring installs. Set mongodb.metrics.serviceMonitor.namespace to your monitoring namespace.

  • sisense-utils.monitoring_namespace: your monitoring namespace (default monitoring).

  • 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.com or http://10.0.0.5:30845.

  • global.applicationDnsName: the host name only, without scheme or port, for example sisense.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

  1. Add the Sisense Helm repository, and run a quick update to sync with the remote repository:

    Copy
    helm repo add sisense-fusion https://data.sisense.com/linux/helm/charts/fusion
    helm repo update
  2. 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.

    Copy
    helm search repo sisense-fusion/sisense --versions | head
  3. Create the namespace, and check that the nodes are labeled and that your StorageClasses exist:

    Copy
    NAMESPACE=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
  4. Preview the installation. A server-side dry run renders the chart against your cluster without creating anything:

    Copy
    helm 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
  5. Install Sisense using the values file:

    Copy
    helm 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):

HelmInstallSuccess

Continue with Post Installation.

Upgrading an Existing Sisense Installation

To upgrade, run the same command as for the installation, with the new chart version:

Copy
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-values keeps 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 --timeout if 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:

ServicesDeployment

When all of the services are up, the message Sisense installation process completed successfully appears.

SingleHelm InstallSuccess

To check the installation, run the following commands:

Copy
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.

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.