Deploying Grafana on Kubernetes with the Helm chart: what the chart configures for you
A Helm chart is a packaged way to install Grafana and its configuration into a Kubernetes cluster, and most of that configuration lives in the chart's values.yaml file. A successful install gives you running pods, a service and the supporting objects, but it does not make the instance production ready. Persistence, the database, secrets and ingress still need decisions from you. A chart fits best when your team already deploys with Helm and wants one set of values per environment. A plain manifest suits a small team that wants every object visible in Git without a templating layer. The Grafana Operator fits better when you run many Grafana instances and want dashboards, data sources and alert rules managed as custom resources. The Grafana installation docs list Helm charts for Kubernetes alongside Linux packages and Docker images, so the chart is one supported install path among several.
Set the persistence, database, secrets and ingress values before the first install. Enable persistence so the data directory, which holds the default SQLite database, survives pod restarts. The installation docs say SQLite does not scale for production, so once you run more than one replica you need MySQL 8.0 or later, or PostgreSQL 12 or later, shared across active-active servers behind a load balancer. Reference an existing Kubernetes Secret for the admin password instead of writing it into values.yaml, and confirm the key name your pinned chart version documents. Give each plugin in values.yaml an explicit version so an upgrade does not change it silently. The chart can create the ingress object, but the hostname, TLS certificate and root_url must still match your DNS and proxy.
Confirm who stands behind the chart before you rely on it. A community chart is maintained by its contributors, and Grafana's own support terms may not cover it, so ask Grafana Labs and read the chart's changelog for the version you plan to pin. Check the cluster as well. The Kubernetes project maintained 1.37, 1.36 and 1.35 as of September 2026, so a cluster on an older minor version needs an upgrade plan before Grafana upgrades can be tested. Record the chart version, image tag, values file and Secret names in version control so a rebuild is repeatable. A quote for this work should name who installs the chart, who owns the database and TLS certificates, and which values are set in the first release.
Helm values for persistence, secrets and an external database
This table compares the chart values most teams set when they deploy Grafana with the community Helm chart: persistence, the admin credential, the external database, plugins and ingress. Read each row for when the option fits, what it changes in the cluster, and what to confirm against the chart version you pin, because key names differ between chart releases.
| Value area | When it fits | What it changes in the cluster | Confirm for your chart version |
|---|---|---|---|
| Persistence (persistence.enabled, storage size, storage class) | A single replica with SQLite, or any setup where dashboards and plugin files must survive pod restarts | Creates a PersistentVolumeClaim mounted at the Grafana data path, so local state outlives the pod | Exact key names, the mount path, and whether an existing claim can be referenced instead of created |
| Admin credential (existing Secret reference) | Any cluster where the admin password must not sit in values.yaml or in version control | Reads the admin user and password from a Secret you created, so the chart does not generate or print a password | The key names the Secret must contain and whether the chart expects the password key or a user key as well |
| External database (type, host, name, user, password reference) | Production and multiple replicas, using MySQL 8.0 or later or PostgreSQL 12 or later, since SQLite does not scale for production | Points Grafana configuration at the shared database so replicas read the same state, with credentials passed from a Secret | Whether database settings go through values or grafana.ini overrides, and how TLS modes are expressed |
| Replica count (replicas) | Two or more replicas only after the database is external and alerting duplicate notifications is planned | Runs several Grafana pods behind the Service, all sharing one database | Confirm the Grafana HA guidance for alerting and Grafana Live limitations before raising the count |
| Plugins (plugins list) | Plugins the team needs at every start, on connected clusters that can reach the plugin catalog | Installs listed plugins into the pod at startup, so the image stays unchanged but start time and outbound access depend on the install | Plugin ID and version format, and whether restricted networks need a baked image instead |
| Ingress (ingress.enabled, hosts, TLS secret) | Exposing Grafana through an ingress controller you already run, with TLS terminated at the edge | Creates an Ingress object that routes a hostname to the Grafana Service, and needs root_url set to match the public address | Ingress class name, annotation keys for your controller, and the TLS secret name |
| Grafana configuration (grafana.ini section) | Settings the chart does not expose as named values, such as security headers or cookie options | Writes configuration into the mounted config, so changes roll the pods | Which sections the chart accepts and whether any key is overridden by an environment variable |
Single replica or high availability: which values change
A single replica suits a small team that can accept a short outage while the pod restarts, upgrades or is rescheduled. In this model the chart runs one Grafana pod, and persistence is the setting that matters most, because a pod without a persistent volume loses its local SQLite database and any dashboards or users created through the UI. The default database is SQLite 3, and the Grafana installation docs size small deployments under 25 concurrent users at 2 cores and 2 to 4 GB of RAM, so sizing is usually modest.
- Persistence on: enable the chart's persistence option so the SQLite file survives pod restarts.
- Single replica count: keep the replica count at one, since SQLite does not support multiple writers.
- Restart tolerance: plan for a short gap during rollouts and node drains, and tell users when maintenance happens.
- Backups: back up the persistent volume or the database file on a schedule you can restore from.
- Scale path: decide early whether the team may outgrow this model, because moving to an external database later requires a migration.
Before you go live, confirm the storage class supports the access mode you chose and test a pod deletion to see how long the instance is unavailable.
Multiple replicas suit shared dashboards and alerting that teams cannot afford to lose during restarts. The Grafana high availability docs call for two or more active-active Grafana servers behind a load balancer, all sharing a MySQL or PostgreSQL database. SQLite is not suitable for production or high availability, so the external database is a prerequisite, not an option. The chart's replica count and database settings must both change together, or the extra pods will fail to coordinate.
- External database: point the chart at MySQL 8.0 or later, or PostgreSQL 12 or later, and store the credentials in a Kubernetes Secret.
- Replica count: set two or more replicas only after the database connection works on every pod.
- Load balancing: expose the Grafana service through an ingress or load balancer that spreads traffic across pods.
- Database-backed auth tokens: rely on the database so a user session works on any node, instead of depending on one pod's local state.
- Persistence: keep dashboards and provisioned files in the database or in provisioning, since local volumes are not shared between pods.
Confirm the database is itself highly available and backed up, because Grafana cannot work around a single failed database.
Alerting and real-time features need the most attention in a multi-replica setup. The Grafana high availability docs note that alerting needs additional configuration to avoid duplicate notifications, because each replica can evaluate rules and send messages. The same docs say Grafana Live has limitations in HA, so live streaming features may behave differently from a single instance. These limits are the reason a multi-replica chart is not a simple replica count change.
- Duplicate notifications: review the high availability alerting settings in the docs before enabling alerting on more than one pod.
- Notification test: trigger a test alert and count how many messages each receiver gets.
- Grafana Live: test the live streaming panels and features your teams use across two or more pods.
- Routing ownership: decide which team owns contact points so changes are not made on one pod only.
- Upgrades: check the alerting and Live behavior on each new minor version before rolling it out.
Before you rely on multi-replica alerting, ask your vendor or your own test team to confirm the current alerting HA configuration for the Grafana version you deploy.
Switching from one replica to several is a set of coordinated value changes, not one edit. The chart's replica count, persistence, database connection and secret references must all agree with each other. Changing only the replica count usually leaves each pod on its own SQLite file, which produces inconsistent dashboards and users. Review the values file as a unit so the single-replica and HA configurations stay traceable.
- Replica count: raise it only after the external database and secrets are in place.
- Database block: set the database type, host, port and credential references for the external database.
- Persistence: reassess whether local volumes are still needed once the database holds state.
- Secrets: reference existing Secrets for admin and database passwords, rather than writing them in values.
- Ingress and proxy headers: confirm the external URL and forwarded headers match the load balancer setup.
After the change, check that every pod reports the same database and that a login on one pod is accepted on another.
Installing Grafana on Kubernetes with Helm, step by step
This sequence takes a Kubernetes cluster you control to a Grafana release installed from a pinned community chart, with persistence, credentials kept out of the values file, an external database for multiple replicas, plugins, and an ingress login path that you have checked end to end.
Confirm cluster version and storage class
The platform engineer checks that the cluster runs a Kubernetes minor version the team can still patch, and that a StorageClass exists that can provision a PersistentVolume with the access mode Grafana needs for its data directory. Confirm with the cluster owner which StorageClass is approved for stateful workloads and whether it supports volume expansion. Check the current support window on the Kubernetes releases page before choosing the version. Done when
kubectl versionreports the expected server version andkubectl get storageclassshows the approved class marked as the one you intend to use. Record both values in your change ticket so the install can be reproduced later.Add the chart repository and pin a version
The platform engineer adds the Grafana chart repository with
helm repo add, runshelm repo update, and lists available chart versions withhelm search repo. Choose a specific chart version rather than the latest, and record the chart version and the Grafana application version it deploys, since the chart and the Grafana release do not always move together. Because the chart is community maintained, confirm the chart's source and release notes with your own review process before pinning it. Done whenhelm show chartreturns the pinned version and you have saved the chart version in version control alongside the values file.Create admin and database secrets outside values
The security or platform engineer creates a Kubernetes Secret in the target namespace that holds the initial admin password and the database username and password, using
kubectl create secret genericor your secrets manager's sync tool. Keep these values out of values.yaml and out of Git. Remember that Kubernetes Secrets are stored unencrypted in etcd by default, so confirm with the cluster owner that encryption at rest is enabled and that RBAC limits who can read the namespace. Done whenkubectl get secretlists the Secret with the expected keys and no plaintext appears in the chart repository.Write values for persistence, database and plugins
The platform engineer writes a values file that enables persistence and points it at the StorageClass confirmed earlier, references the Secret for admin credentials, sets the database type to PostgreSQL or MySQL with the connection details, and lists the plugins to install in the plugins section. Grafana's database guidance requires MySQL 8.0 or later or PostgreSQL 12 or later for production and high availability, so SQLite is not suitable once you run more than one replica. Set replicas above one only after the external database and shared sessions are in place. Done when
helm templaterenders without errors and the rendered Deployment shows the expected environment variables and volume claim.Install into a dedicated namespace
The platform engineer runs
helm installwith the pinned chart version, the values file and a dedicated namespace created with--create-namespace, using--waitso Helm reports when the rollout completes. Keep the release name and namespace in the runbook. Before installing, confirm your Helm and cluster versions are supported together. Done when Helm reports the release as deployed andhelm statusshows the revision you expect. If the install fails,helm uninstallremoves the release, but check whether the PersistentVolumeClaim remains and whether it holds data you need before deleting it.Verify pods and persistent volume claims
The platform engineer checks that Grafana pods reach the Ready state, that the PersistentVolumeClaim is Bound, and that the logs show Grafana connecting to the configured database without migration errors. Run
kubectl get pods,kubectl get pvcandkubectl logsin the namespace. To confirm persistence, restart one pod and verify that dashboards and the admin user survive. Done when the pod restarts cleanly, the claim stays bound to the same volume, and the test dashboard is still present afterward.Verify ingress login and data source connections
The platform engineer opens the public hostname configured in the ingress, confirms TLS is served with the expected certificate, and signs in with a non-admin test account as well as the admin account. Then test each data source from the Grafana UI and run a simple query. Confirm the root URL matches the hostname to avoid OAuth redirect problems later. Ask your ingress team which controller handles the host and whether WebSocket support is needed for Grafana Live. Done when the login page loads over HTTPS, both accounts sign in, and every data source reports a successful connection test.
Roll back a failed upgrade
Before any chart or Grafana upgrade, the platform engineer records the current revision with
helm historyand backs up the database. If the upgrade fails or the new pods do not become Ready, runhelm rollbackto the recorded revision and confirm the pods return to Ready and the login path works. Note that a database migration applied by a newer Grafana release may not be reversible by rolling back the image, so restore from the database backup if the schema changed. Done when the rollback revision shows as deployed, the pods are Ready, and a test login and data source query succeed.
How Kubernetes and Grafana upgrades stay in step with the chart
Plan the Grafana chart, the Grafana image tag and the Kubernetes version as one upgrade, because a change to any of the three can break the others. Grafana major releases arrive about once a year in April or May, minor releases about every other month, and patch releases at least monthly. Each minor release is supported for 9 months, and the last minor release of a major version for 15 months, according to Grafana's upgrade guidance. Your chart version pins a default image tag, so check which Grafana version a given chart release deploys before you accept a chart bump, and confirm with the chart maintainers how they track Grafana releases. Overriding the image tag in values.yaml can move Grafana ahead of or behind what the chart was tested with, so record every override in version control.
On the Kubernetes side, the project maintains the three most recent minor releases, so a cluster on an older minor version will soon fall outside support. The Kubernetes version skew policy requires kube-apiserver to be upgraded one minor version at a time, before kube-controller-manager, kube-scheduler and kubelets. Kubelets may run up to three minor versions behind kube-apiserver, which gives node pools room to lag but does not remove the need to keep moving. Confirm the supported minor versions on the Kubernetes releases page at the time you plan, because the support window moves with each release.
Build a test environment that mirrors production before any upgrade. It should run the same chart version, the same values files, the same external database and the same Kubernetes minor version as the target. Run the chart upgrade there first, confirm that the database migration completes, that dashboards and data sources load, that plugins still start, and that ingress and login work. Back up the Grafana database before each production change. Then schedule the cluster upgrade, the chart upgrade and any Grafana image change in a sequence your team has rehearsed, with a rollback path for each step.
Securing the admin secret, database credentials and ingress
A Grafana Helm release touches several secrets at once: the admin login, the database password, and the TLS certificate at the edge. Each one needs a home outside values files, a protected path through the cluster, and a check after install. The cards below cover the decisions that connect them.
Keep the admin password out of values
Do not place the admin password in values.yaml or commit it to a Git repository. Reference a pre-created Kubernetes Secret for the admin credentials instead, and generate the password outside the repository. Check that rendered manifests from helm template contain no plaintext credentials before any pipeline publishes them, and confirm who can read that Secret in the namespace.
Encrypt Secrets in etcd
Kubernetes stores Secrets unencrypted in etcd by default, so the database password and admin credentials are only as protected as the etcd data and its backups. Ask your cluster team whether encryption at rest is enabled for Secrets, and whether etcd snapshots are encrypted and access-controlled. Restrict get, list and watch on Secrets in the Grafana namespace to the people and service accounts that need them.
Use an external secret store
The Secrets Store CSI Driver mounts secrets from an external store into pods, so the database password need not live as a long-lived Kubernetes Secret. This moves the control to the external store's access policy and rotation process. It adds a driver, a provider and a dependency at pod start, so confirm that your platform supports the driver and that your store's rotation works with Grafana's restart behavior.
Apply Grafana hardening settings
Set secure and SameSite cookies, a Content Security Policy, Trusted Types, and domain verification against DNS rebinding in the Grafana configuration. Hide the version from unauthenticated users and require authentication for the metrics endpoint. Set these through the chart's configuration values, then test login, dashboards and any plugins, because a strict Content Security Policy can break panels that load external scripts.
Enforce Pod Security Standards
Apply a Pod Security Standards level to the Grafana namespace with the pod-security admission labels, and confirm the chart's pod spec passes the chosen level. Typical checks include running as non-root, dropping capabilities, and disabling privilege escalation. Test the release in a non-production namespace first, because a stricter level can block init containers or sidecars the chart adds for plugins or database access.
Terminate TLS at the ingress
Terminate TLS at the ingress controller with a certificate issued for the Grafana hostname, and keep the ingress host, root_url and cookie settings consistent so OAuth redirects work. Confirm who renews the certificate and how renewal failures are alerted. Decide whether traffic between the ingress and the Grafana pod is also encrypted, and document that choice for your security review.
What teams ask before running Grafana on Kubernetes with Helm
What does it cost to run Grafana on Kubernetes with Helm?
The chart itself is free to use, so the cost is the labor to install, configure, test and operate it, plus the infrastructure underneath. Effort rises with the number of environments, the database you attach, how many identity and plugin decisions you make, and how mature your cluster is. Ask any partner for a fixed-scope quote built from a written list of deliverables, environments and integrations, and check which items are one-time (design, build, handover) and which recur (upgrades, patching, support retainers). Hosting costs for the cluster, storage and a managed database also belong in your own budget.
How long does a first Grafana Helm install take?
The duration depends on what is being built around the chart rather than the chart install itself. Persistence, a production-grade database, ingress with TLS, identity integration, plugin delivery and a restore test each add work, and the number of environments multiplies it. Your cluster's readiness matters too: available storage classes, network policy, DNS and certificate automation can each delay a first install. Ask for a timeline that lists these dependencies separately so you can see which ones your team controls.
Can our in-house platform team deploy Grafana with Helm alone?
Yes, a team that already runs Kubernetes workloads with Helm, GitOps tooling and secret management can usually handle a single-environment install from the chart documentation. The harder parts are decisions that outlast the install: choosing an external database, configuring authentication, setting upgrade cadence, and proving backups and restores work. Grafana's upgrade guidance describes minor releases every other month and patch releases at least monthly, so someone must own that cycle. Decide early whether your team will absorb that ongoing work or contract it.
What do we need to provide for a Grafana Helm engagement?
Plan to provide cluster access with rights to create namespaces, workloads, services, ingress and secrets, plus a place to run Helm and store values in version control. You will also need a PostgreSQL or MySQL database for multi-replica use, DNS records for the Grafana hostname, TLS certificates from your certificate authority or cert-manager, and an identity provider for sign-in. Name owners for each item before work starts, because access requests and certificate approvals are often the longest waits.
Who supports a community Grafana Helm chart, and how do we get a supported path?
Community charts are maintained by volunteers and the wider community, so they carry no vendor support commitment on their own. Grafana Labs offers Grafana Enterprise and Grafana Cloud with commercial support, but those are different products with their own licensing and pricing, so confirm which applies to you on the licensing and pricing pages. For a supported path around the open-source chart, confirm in writing what a partner covers: installation, upgrades, patch handling, incident response and the version of the chart it will run. DeployOpen delivers that work as fixed-scope engagements or retainers, with a written scope agreed beforehand.
Is the Grafana Helm chart enough for high availability?
The chart can run several replicas, but high availability depends on more than the replica count. Grafana's documentation describes two or more active-active servers behind a load balancer sharing a MySQL or PostgreSQL database, because SQLite does not scale for production. Alerting needs extra configuration to avoid duplicate notifications, and Grafana Live has limitations in high-availability setups. You also need a highly available database, session and token handling that works across nodes, and tested restores. Treat the chart as the packaging layer and design the rest separately.
Which Helm values and secrets are the most common sources of trouble?
The recurring problems involve persistence, admin credentials and database settings. Without persistence enabled, dashboards and local state can disappear when a pod is rescheduled. Admin passwords should come from a Kubernetes Secret rather than plain values in Git, and Kubernetes stores Secrets unencrypted in etcd by default unless you configure encryption at rest. Plugins listed in values can slow startup or fail when the cluster has no outbound access, and ingress mistakes often surface as OAuth redirect errors. Review each of these in your values file before the first production release.
Limits to confirm in your cluster before you install
The community Helm chart gives you a working Grafana quickly, but it does not settle who supports it, which Grafana version it ships, or which features need Enterprise. Confirm each item below against your cluster, your data and your support obligations before you write values.yaml.
Chart maintainer and support terms
The community chart is maintained outside Grafana Labs' commercial support, so the upstream project is not a support contract. Confirm who publishes and patches the chart, how security fixes reach it, and who you call when a release breaks your deployment. If your policy requires a vendor or partner to answer for production issues, write that requirement into the scope before you choose this path.
Chart version against Grafana image version
The chart version and the Grafana image tag are separate version numbers, and a chart release may default to an older or newer Grafana than you expect. Pin both in values.yaml, read the chart's default image tag, and confirm it falls inside a Grafana minor release that still receives patches. Plan upgrades so the chart and image move together.
Grafana Live and alerting with multiple replicas
Grafana's high availability docs say Grafana Live has limitations when several servers run, and alerting needs extra configuration to avoid duplicate notifications. Before you raise replicas above one, test live dashboard updates through your ingress and confirm that only one alert evaluation path notifies your on-call channel. Record the result as an acceptance test.
Enterprise-only authentication features
The chart deploys Grafana with the settings you supply, and it does not add SAML, team sync, active sync or SCIM provisioning. Those features are available only in Grafana Enterprise and Grafana Cloud, so if your identity team expects SAML or SCIM, confirm the edition before you design user onboarding. Open-source options such as generic OAuth or Entra ID still need their own redirect URLs and secrets.
Storage class and persistent volume backups
Persistence keeps the SQLite file and plugins across pod restarts only when the volume is bound and its storage class supports the access mode you need. Confirm the storage class, reclaim policy and snapshot behavior with your storage team. For multiple replicas, use an external database instead, because SQLite does not scale for production. Test a restore of the volume before go-live.
Kubernetes version support window
Kubernetes maintains only the three most recent minor releases, so a cluster on an older minor may fall outside the support window while Grafana still runs. Check your cluster's current minor version and its end-of-life date against your upgrade calendar. Plan Kubernetes upgrades one minor version at a time, and retest the chart after each step.
How DeployOpen scopes, delivers and supports a Grafana Helm deployment
DeployOpen works on Grafana on Kubernetes through a written scope that fixes what the chart deployment covers before any build starts. The work runs inside your own clusters and cloud accounts, and the handover leaves your team with the values files, runbooks and documentation to operate the instance.
How we scope
- Engagements are fixed-scope, with the chart version, cluster target, persistence, database and ingress design agreed in writing first.
- The written scope names which data sources, plugins and authentication methods are included, so the values file reflects an agreed list.
- Confirm with us whether you need an external database for multiple replicas, since that choice changes the cost and effort of the build.
How we build
- Chart values are kept in version control, with admin credentials sourced from Kubernetes Secrets rather than typed into values files.
- Persistence, ingress and TLS are configured and tested against your cluster's storage class and ingress controller before go-live.
- Plugins are declared in values and checked for installation on a staging release before they reach production.
How we hand over
- You receive the Helm values, the deployment documentation and a record of the decisions made during scoping and build.
- Handover includes a walkthrough of upgrade steps, including how to change the chart and Grafana image tags safely.
- Operating runbooks cover admin secret rotation, restoring persistent storage and what to check after a replica or node failure.
How we support
- Ongoing support, upgrades and continuous testing are available as a retainer after handover.
- Ask for the support scope in writing, including who handles chart upgrades and Grafana minor releases in your environment.
- Community Helm charts are maintained by their own communities, so confirm with the chart maintainers which versions they support before you commit.

