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.existingSecretpointing at a Secret withadmin-userandadmin-password, rather thanadminPasswordin plain values. - Persistence:
persistence.enabled: truekeeps the SQLite database and plugins across restarts; for more than one replica use an external PostgreSQL/MySQL viagrafana.inivalues instead, since SQLite can't be shared. - grafana.ini as a YAML map, rendered to the config file;
envandenvFromSecretforGF_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.yamlRemember
- 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.