Grafana on Kubernetes with Helm

Grafana · Advanced · 12 min

Most production Grafanas run in Kubernetes, and the chart's sidecar pattern is how teams ship dashboards with their applications.

The grafana/grafana Helm chart (repository https://grafana.github.io/helm-charts) deploys a Deployment, Service, optional Ingress and a PersistentVolumeClaim. The values you set first:

  • Admin credentials: admin.existingSecret pointing at a Secret with admin-user and admin-password, rather than adminPassword in plain values.
  • Persistence: persistence.enabled: true keeps the SQLite database and plugins across restarts; for more than one replica use an external PostgreSQL/MySQL via grafana.ini values instead, since SQLite can't be shared.
  • grafana.ini as a YAML map, rendered to the config file; env and envFromSecret for GF_ variables.
  • datasources: a provisioning file inline in values (datasources.yaml), typically pointing at the in-cluster Prometheus Service URL.
  • dashboardProviders plus dashboards (from grafana.com ids or local JSON) for a static set.

The flexible way to ship dashboards is the sidecar: with sidecar.dashboards.enabled: true, a sidecar container watches ConfigMaps (optionally across all namespaces) carrying the label grafana_dashboard: "1", writes their JSON to the dashboards folder and Grafana picks them up. Each team then commits a ConfigMap with its dashboard next to its application manifests. sidecar.datasources and sidecar.alerts do the same for data sources and alert rules. Annotations such as grafana_folder sort dashboards into folders.

kube-prometheus-stack bundles Prometheus Operator, Prometheus, Alertmanager, node-exporter, kube-state-metrics and this Grafana chart (configured under the grafana: key) with a full set of Kubernetes dashboards and the sidecar already enabled, which is the fastest route to cluster monitoring. The Grafana Operator is an alternative that manages dashboards and data sources as custom resources.

Example

# values.yaml for the grafana/grafana chart
admin:
  existingSecret: grafana-admin          # keys: admin-user, admin-password
persistence:
  enabled: true
  size: 10Gi
grafana.ini:
  server:
    root_url: https://grafana.example.com
  dashboards:
    min_refresh_interval: 10s
datasources:
  datasources.yaml:
    apiVersion: 1
    datasources:
      - name: Prometheus
        uid: prom-main
        type: prometheus
        url: http://prometheus-server.monitoring.svc:9090
        isDefault: true
        jsonData: {timeInterval: 15s}
sidecar:
  dashboards:
    enabled: true
    label: grafana_dashboard
    searchNamespace: ALL
    folderAnnotation: grafana_folder
---
# A team's dashboard, shipped next to its app
apiVersion: v1
kind: ConfigMap
metadata:
  name: api-dashboard
  namespace: api
  labels: {grafana_dashboard: "1"}
  annotations: {grafana_folder: Services}
data:
  api-overview.json: |
    {"uid": "api-overview", "title": "API overview", "panels": [] }
# helm upgrade --install grafana grafana/grafana -n monitoring -f values.yaml

Remember

  • Admin password from a Secret, persistence on, data sources provisioned in values
  • The dashboards sidecar loads any ConfigMap labelled grafana_dashboard=1
  • kube-prometheus-stack ships Prometheus, Alertmanager and Grafana with dashboards together

Watch out for

  • Scaling the Deployment to two replicas on SQLite and a ReadWriteOnce volume; the second pod never starts or sees different data.

Check yourself

  1. How does a team add its dashboard to Grafana deployed with the chart's sidecar enabled?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: grafana.com/docs/grafana/latest/setup-grafana/installation/kubernetes/