Grafana und Helm - Teil 2 | Dashboards & Sidecars
Im ersten Artikel dieser Grafana Serie haben wir das Setup von Grafana mit Helm in einem Kubernetes-Cluster zusammengefasst.
Als nächstes gehen wir auf die Dashboardentwicklung und das Deployment ein.
Bevor Du ein Dashboard von Grund auf neu entwickelst, solltest Du - z.B. in GitHub Repositories oder bei Grafana selbst - kurz recherchieren, ob es bereits ein ähnliches Dashboard gibt.
Dabei können allerdings Anpassungen notwendig sein, weil beispielsweise eine Umbenennung der Metriken vorgenommen wurde.
In den meisten Fällen reicht ein auf diese Weise gefundenes Dashboard trotz Anpassungen nicht aus und Du musst ein neues entwickeln. Die Erstellung eines Grafana Dashboards für Kubernetes und einen daran anschließenden Development Life Cycle, wollen wir nun erklären.
Als Vorbereitung auf diesen Artikel solltest Du vorher den ersten Teil und den Beitrag zu Helm lesen.
\
Ausgangssituation
Wie am Ende von Grafana und Helm - Teil 1 beschrieben, haben wir ein Kubernetes Cluster mit dem Namespace monitoring, worin ein whoami-Service sowie Prometheus und Grafana laufen. Von unserem whoami-Service werden Metriken exportiert, die wir über Prometheus mit Grafana visualisieren möchten.
Eine genaue Beschreibung zur Reproduktion ist ebenfalls im ersten Teil des Tutorials zu finden.
\
Grafana Dashboards - Development Life Cycle
Im Folgenden stellen wir eine der - unserer Meinung nach - sinnvollsten Varianten des Development Life Cycles von Grafana Dashboards vor.
Erstellen eines Grafana Dashboards
Zunächst stellen wir Schritt für Schritt die Erstellung eines Grafana Dashboards vor.
\
- Anlegen eines neuen Dashboards über die UI unserer Grafana-Instanz.
\ - Hinzufügen eines Panels (über “Add Query” oder “Choose Visualization”) und Konfiguration der Queries und der Anzeige.
\ - Anpassen der Zeitspanne und des Aktualisierungsinstervalls (Last 6 hours > Quick ranges/Custom range).
\ - Anlegen der oben verwendeten Variable
$Handler
und speichern des Dashboards über Settings > General/Variables.
\ - Weitere individuelle Anpassungen (Hinzufügen von weiteren Panels, Gruppierung in “Rows”, etc.).
\ - Über Share dashboard > Export > View JSON exportieren und speichern.
Am Ende erhalten wir ein Dashboard, das (wenn die richtigen Metriken mit korrekten Labels exportiert werden) universell eingesetzt werden kann, indem es beim Laden die Variable “Handler” automatisch mit Werten befüllt, für die die Metrikhttp_requests_total
existiert. Um umfangreichere Dashboards zu bauen und bspw. die Funktionsweise von Variablen besser zu verstehen, empfehlen wir einen Blick in die Grafana bzw. Prometheus Dokumentation.
Das erstellte Dashboard haben wir als JSON zur Verfügung gestellt:
variable-dashboard.json
Was dann?
Der nächste Schritt ist das Dashboard als Kubernetes-ConfigMap, wie in Teil 1 beschrieben, zu speichern, um es beim Deployment von Grafana mit auszuliefern.
Dabei solltest Du auf eventuelle Fehlerquellen achten. Beispielsweise bietet Grafana die Möglichkeit dynamische Legenden zu erstellen:
In diesem Beispiel wird der Graph nach HTTP-Codes aufgeteilt, sodass wir nicht nur die “2xx” pro Sekunde angezeigt bekommen, sondern auch alle anderen Codes. Diese sind dann korrekt beschriftet in der Legende wiederzufinden.
Allerdings wird es jetzt - nachdem man das Dashboard als JSON exportiert und in eine ConfigMap eingefügt hat - ein Problem beim Deployment geben.
Will man sein Grafana Helm Chart mit dem neuen Dashboard deployen, passiert Folgendes:
Vorraussetzung: Wir befinden uns in unserem Grafana Helm Chart
$ helm install -n grafana --namespace monitoring .
Error: parse error in "grafana/templates/my-dashboard-cm.yaml": template: grafana/templates/my-dashboard-cm.yaml:71: function "code" not defined
Helm interpretiert die doppelten geschwungengen Klammern als Versuch ein Template einzubinden, welches (höchstwahrscheinlich) nicht existiert.
Um das zu umgehen, bieten sich zwei Möglichkeiten an.
- Entweder: Ersetzen von
{{
und}}
durch{{ "{{" }}
bzw.{{ "}}" }}
. (Praktisch bei wenigen, vereinzelten Vorkommen) - Oder: Modifikation der ConfigMap; statt das Dashboard direkt im Manifest der ConfigMap zu speichern, laden wir es mit Helm aus einer JSON Datei in die ConfigMap.
templates/my-dashboard-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-dashboard-name
labels:
grafana_dashboard: "1"
data:
k8s-dashboard.json: |-
{{ (.Files.Glob "dashboards/variable-dashboard.json").AsConfig | indent 2 }}
\
dashboards/variable-dashboard.json
Wenn alle Probleme behoben wurden, kannst Du dein Grafana Deployment upgraden, um zu kontrollieren, ob alles so funktioniert, wie gewünscht:
$ helm upgrade grafana [-f my-own-values.yaml] .
$ kubectl get secret -n monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
$ kubectl port-forward -n monitoring svc/grafana 3000:80
Weil Grafana als Sidecar für die Dashboards ein Image benutzt, das beobachtet ob sich an den ConfigMaps etwas ändert, werden dabei übrigens nicht nur Änderungen an Dashboards berücksichtigt, sondern auch neue bzw. gelöschte Dashboards.
Hinweis: Dies gilt nicht für Datasources und Plugins!
\
Fazit
Unter Umständen kann es sehr aufwändig sein existierende Dashboards an die eigenen Bedürfnisse anzupassen. Du solltest Dir also vorher darüber im Klaren sein, was Du brauchst und, ob es nicht einfacher ist ein neues Dashboard zu entwickeln.
Die Autodeploy-Sidecar-Container der Grafana Helm Installation für Dashboards und Datasources sind eine gute Möglichkeit einen ersten Development Life Cycle für Grafana Ressourcen zu enwickeln und zu automatisieren.
Warum es trotzdem manchmal zu Störungen kommt und welche Probleme in größeren Umgebungen mit vielen Entwicklerteams und geteilten Grafana Instanzen auftreten, erklären wir im nächsten Post.
In unserem Kubernetes-Lab gehen wir auf das Thema Monitoring am Beispiel Grafana ein, hier geht’s zu den Trainings.
- Jan