Keep your dashboards in Git, not in Grafana's own database. A dashboard you build by clicking in the Grafana UI lives only in that one Grafana's database. If the pod moves or is rebuilt, Grafana comes up without that dashboard. Stored in Git as JSON and loaded on startup, dashboards survive: every cluster gets the same views, changes go through review, and a rebuilt Grafana comes back with all of them. ## The sidecar loads dashboards from ConfigMaps The Grafana installation runs a sidecar which watches for ConfigMaps that carry a label and imports any dashboard JSON inside them. A ConfigMap is a Kubernetes object that holds text, here the dashboard's JSON. Loading dashboards this way, with no one clicking, is called provisioning. Put a dashboard's JSON in a ConfigMap with that label, and it appears in Grafana: ```yaml title="dashboard-configmap.yaml" apiVersion: v1 kind: ConfigMap metadata: name: cluster-overview-dashboard namespace: monitoring labels: grafana_dashboard: "1" # the label the sidecar watches for data: cluster-overview.json: | { "title": "Cluster overview", "panels": [ ... ] } ``` Organize dashboards into folders by setting a `grafana_folder` annotation, so a fleet's dashboards do not land in one flat list. ## Deliver them with GitOps GitOps means your cluster's configuration lives in Git, and a tool applies whatever is there. Commit those ConfigMaps to the repository your cluster syncs from, and Argo CD (or Flux) applies them like any other manifest. See [Set up Argo CD](/docs/hetzner/apalla/clusters/gitops/set-up-argo-cd). Now a dashboard change is a pull request: someone reviews it, it merges, and it rolls out to every cluster the app targets. No one edits a dashboard in production by hand. ## Template per cluster and namespace Template variables let one dashboard serve every cluster and every tenant. A template variable is a dropdown in Grafana that swaps what the panels show. Give a dashboard a `cluster` variable, bound to the external label you set in [Long-term storage and remote-write](/docs/hetzner/apalla/observability/metrics/long-term-storage-and-remote-write), and a `namespace` variable. For an agency, one reviewed set of dashboards then serves the whole fleet, each client seeing their own cluster through the same panels. See [Multi-cluster observability](/docs/hetzner/apalla/observability/multi-cluster/multi-cluster-observability). ## Generate large sets with Grafonnet Hand-written dashboard JSON is verbose and easy to break. For a large set, generate it: Grafonnet (a Jsonnet library) builds dashboards from code, so panels are reusable functions instead of copied JSON. It is worth the setup once you maintain more than a handful of dashboards or template heavily across a fleet.