In Cloud-Native-Umgebungen stoßen klassische Monitoring-Tools an ihre Grenzen, wenn sie kurzlebige Objekte wie Container überwachen. Diese Lücke schließt Prometheus, das Kubernetes dank der konzeptionellen Ähnlichkeit, des einfachen Aufbaus und einer weitreichenden Automatisierung passgenau ergänzt.
Kubernetes [1] erleichtert es Admins enorm, Container-basierte Infrastrukturen zu verteilen. Sie müssen sich im Prinzip keine Gedanken mehr darüber machen, wo Applikationen laufen oder ob ausreichend Ressourcen bereitstehen. Wollen sie aber eine optimale Leistung sicherstellen, kommen sie meist nicht daran vorbei, die Applikationen, die Container, in denen sie laufen, und Kubernetes selbst zu überwachen.
| Kommando | Effekt |
|---|---|
| »minikube dashboard« | Öffnet das Kubernetes-Dashboard im Browser |
| »minikube service –namespace=monitoring prometheus« | Ruft den Dienst »prometheus« im Browser auf |
| »minikube service –namespace=monitoring –url prometheus« | Gibt die URL zum Service »prometheus« aus |
Wie Prometheus funktioniert, lässt sich unter [2] nachlesen, der aktuelle Artikel wirft ein Licht auf die Zusammenarbeit mit Kubernetes. Dank seiner eingebauten Service Discovery holt sich Prometheus selbstständig über das Kubernetes-API Informationen über die Containerplattform, die laufenden Container, Dienste und Anwendungen. Der Admin muss die Konfiguration von Prometheus nicht ändern, wenn Pods starten oder sterben oder wenn neue Knoten im Cluster auftauchen: All dies erkennt Prometheus.
Sehr erhebend
Neben üblichen Daten wie CPU-Auslastung, Speichernutzung oder Festplattendurchsatz interessieren in einer Kubernetes-Umgebung auch die Metriken von Containern, Pods, Deployments und den laufenden Anwendungen. Der Artikel will zeigen, wie Admins mit Prometheus und Grafana am einfachsten Informationen über ihren Kubernetes-Cluster sammeln und visualisieren. Eine Demo-Umgebung liefert Eindrücke davon, welche Einblicke in eine Kubernetes-Installation Prometheus gewährt.
Listing 1
02-prometheus-configmap.yml (Auszug 1)
01 [...] 02 - job_name: 'kubernetes-apiservers' 03 kubernetes_sd_configs: 04 - role: endpoints 05 scheme: https 06 tls_config: 07 ca_file: /var/run/[...]/ca.crt 08 insecure_skip_verify: true 09 bearer_token_file: /var/run/[...]/token 10 [...]
Die Konfiguration von Prometheus orientiert sich dabei am offiziellen Beispiel [3]. Beim Abfragen der Metriken über das Kubernetes-API genügt beispielsweise der Auszug aus Listing 1. Und schon lassen sich dank der Service Discovery in Prometheus eine Menge Metriken abrufen, wie Abbildung 1 zeigt.

Abbildung 1: Mit ein paar Handgriffen und dem Kubernetes-API spürt der Admin verschiedene Metriken auf.
Etikettiert
Der wohl größte Vorteil im Zusammenspiel von Prometheus und Kubernetes dürfte aber der Support für Label sein. Sie sind in Kubernetes die einzige Möglichkeit, gezielt auf Pods, Services und andere Objekte zuzugreifen oder diese zu identifizieren. Es ist daher wichtig, dass Prometheus diese Label erkennt und beibehält. Die Service Discovery der Software legt diese Informationen temporär in so genannten Meta Label ab. Mit Hilfe von Relabeling-Regeln wandelt Prometheus diese dann in gültige Prometheus-Label um und verwirft die Meta Label, sobald es die Überwachungsziele erzeugt hat.
Listing 2
02-prometheus-configmap.yml (Auszug 2)
01 [...] 02 - action: labelmap 03 regex: __meta_kubernetes_service_label_(.+) 04 - source_labels: [__meta_kubernetes_namespace] 05 action: replace 06 target_label: kubernetes_namespace 07 - source_labels: [__meta_kubernetes_service_name] 08 action: replace 09 target_label: kubernetes_name 10 [...]
Den Relabeling-Prozess beschreibt ein Blogpost [4] im Detail. Die Regeln sehen zum Beispiel aus wie in Listing 2. Am Ende kennt Prometheus dann die Label, die auch Kubernetes seinen Nodes, Applikationen und Services zuordnet.
Prom Night
Mit der mächtigen Abfragesprache Prom QL [5] und anhand dieser Label definieren Admins Graphen oder Alarme. So definiert Kubernetes die Label aus Listing 3, die eine daraus resultierende Prometheus-Metrik quasi erbt:
my_app_metric{app="myapp",mylabel="myvalue",[...]}
Prometheus erzeugt für jedes weitere Label eine eigene Zeitreihe. Jedes Label fügt der Metrik »my_app_metric« eine weitere Dimension hinzu, die Prometheus wiederum als separate Zeitreihe speichert. Die Software kommt bereits jetzt mit Millionen von Zeitreihen zurecht, dennoch soll Version 2.0 [6] noch extremere Kubernetes-Umgebungen mit Tausenden Knoten abdecken.
Von Dauer oder flüchtig?
Vor der Installation von Prometheus sollte der Administrator überlegen, ob er die Software innerhalb oder außerhalb der Kubernetes-Umgebung installieren will. Eine Installation außerhalb lässt für das dauerhafte Speichern der Daten alle Optionen offen. Auch arbeitet das Monitoring autark vom überwachten System.
Listing 3
Label-Beispiel
01 metadata: 02 labels: 03 app: myapp 04 mylabel: myvalue
Eine Integration in Kubernetes richtet er jedoch deutlich einfacher ein, das betrifft sowohl das Netzwerk als auch die Authentifizierung. Mit Persistent Volumes [7] oder Stateful Sets [8] verfügt Kubernetes inzwischen über Möglichkeiten, Daten dauerhaft zu behalten. Betreibt er ein weiteres Monitoring von außen, spricht wenig dagegen, dass der Admin Prometheus mit Kubernetes verknüpft.
Ausprobiert
Um die oben ausgeführten Informationen zu veranschaulichen, wird der Artikel demonstrieren, wie ein Admin auf Basis von Minikube [9] einen eigenen kleinen Kubernetes-Cluster mit Prometheus-Aufsatz laufen lässt. Minikube bietet die einfachste Möglichkeit, Kubernetes auf seinem eigenen Rechner zu testen, egal ob dieser Linux, OS X oder Windows verwendet. Wer die Schritte nachvollziehen möchte, findet unter [10] eine Installationsanleitung. Einen neuen Kubernetes-Cluster erzeugt der Befehl »minikube start«, je nach Basissystem setzt Minikube noch ein installiertes Virtualbox oder »kubectl« voraus.
Vollständige Listings der im Artikel gezeigten Auszüge bietet das Linux-Magazin online [11] und auf der DELUG-DVD an. Das betrifft vor allem die Yaml-Files mit den Kubernetes-Definitionen (»*.yml«): Der Nutzer entpackt sie in ein Arbeitsverzeichnis, um sie später mit »kubectl« an Kubernetes zu senden. Die mit den Yaml-Dateien erzeugten Inhalte speichert Kubernetes intern und erzeugt daraus entsprechende Objekte wie Namespaces, Deployments oder Services.
Da die folgenden Schritte Minikube betreffen, spart der Artikel weiterführende Themen wie persistentes Speichern und die mit Kubernetes 1.6 eingeführte Role Based Access Control (RBAC, [12]) aus; Prometheus lässt sich aber auch damit kombinieren.
Namens-Tag
Um die Ressourcen einzelner User oder eine Nutzergruppe auf einem physischen Cluster voneinander zu isolieren, verwendet Kubernetes Namespaces. Für das Beispielprojekt erzeugt der Admin den Namespace »monitoring«:
kubectl create -f 01-monitoring-namespace.yml
Will er einfach nachvollziehen, was in dem kleinen Kubernetes-Cluster passiert, startet er die Administrationsoberfläche über »minikube dashboard«. Hier wählt er dann den Namespace »monitoring« wie es Abbildung 2 zeigt.
Der nächste Schritt widmet sich dann schon Prometheus. Die Software gibt es als offizielles Docker-Image [13], allerdings ohne jede Konfiguration. Um nicht für jede Änderung ein neues Image bauen zu müssen, packt der Admin die Kubernetes-Konfiguration als Datenobjekt »prometheus.yml« in eine Config Map [14] mit dem Namen »prometheus-configmap«.
Listing 4
03-prometheus-deployment.yml
01 apiVersion: apps/v1beta1
02 kind: Deployment
03 metadata:
04 labels:
05 app: prometheus
06 name: prometheus
07 namespace: monitoring
08 spec:
09 replicas: 1
10 template:
11 metadata:
12 labels:
13 app: prometheus
14 spec:
15 containers:
16 - image: prom/prometheus:v1.6.3
17 name: prometheus
18 args:
19 - -config.file=/etc/prometheus/prometheus.yml
20 - -storage.local.path=/prometheus
21 ports:
22 - containerPort: 9090
23 volumeMounts:
24 - mountPath: /etc/prometheus
25 name: prometheus-volume-config
26 - mountPath: /prometheus
27 name: prometheus-volume-data
28 volumes:
29 - name: prometheus-volume-config
30 configMap:
31 name: prometheus-configmap
32 - emptyDir: {}
33 name: prometheus-volume-data
Die config Map kann er anschließend unabhängig ändern, löschen oder neu anlegen:
kubectl create -f 02-prometheus-configmap.yml
So genannte Deployments [15] liefern Deklarationen, um Pods und Replica-Sets zu aktualisieren. Das Kubernetes-Deployment für Prometheus (Listing 4) bindet die gerade angelegte Config Map als neues Volume mit dem Namen »prometheus-volume-config« per Volume-Mount in den Pfad »/etc/prometheus/prometheus.yml« ein. Das stellt eine Verbindung zwischen Prometheus und seiner Konfiguration her:
kubectl create -f 03-prometheus-deployment.yml
Das Verzeichnis, das die Prometheus-Datenbank speichert, konfiguriert der Admin ebenfalls als »volume«, konkret als »emptyDir«. Es verwirft die Daten beim Neustart des Prometheus-Pod, für ein produktives Setup sollte er hier besser persistente Volumes verwenden.
Fehlt noch ein passender Dienst für Prometheus, um einfach auf die laufende Prometheus-Instanz zuzugreifen:
kubectl create -f 04-prometheus-service.yml
Der Service lässt sich dann etwa über »kubectl« auf den Schirm rufen (Listing 5). An dieser Stelle der Hinweis, dass Minikube Services mitunter als »pending« (noch ausstehend) anzeigt. Keine Sorge, sie funktionieren trotzdem.
Ausschau halten
Anwendungen, die Metriken im Prometheus-Format bereitstellen, findet die Monitoring-Software auch automatisch. Dafür muss der Admin sie zuvor mit bestimmten Annotations im Key-Value-Format versehen, die auch ein Beispiel in der Dokumentation beschreibt (Listing 6, [3]).
Listing 5
Dienste im Namespace monitoring
01 # kubectl get service --namespace=monitoring 02 NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE 03 prometheus 10.0.0.221 <pending> 9090:31244/TCP 1m
Solche Anmerkungen macht sich die nächste Komponente zunutze: der »node_exporter«[16]. Er erhebt Daten über die Clusterknoten, etwa zur Speichernutzung, zum Netzwerkdurchsatz oder zur CPU-Auslastung. Will sich der Administrator nicht selbst darum kümmern, dass die Software auf jedem Knoten läuft, startet er den »node_exporter« als so genanntes Daemon Set [17]. Dieser Schritt stellt schlicht sicher, dass auf jedem Knoten eine eigene Instanz von »node_exporter« läuft: Kommt ein neuer Knoten hinzu, ruft Kubernetes dort automatisch eine neue Instanz auf.
Listing 6
Beispiel für Annontations
01 [...] 02 metadata: 03 annotations: 04 prometheus.io/scrape: 'true' 05 prometheus.io/port: '9100' 06 [...]
Den »node_exporter« staffiert der Admin mit den oben erwähnten Annotations aus, wodurch Prometheus alle seine Instanzen ohne weitere Konfiguration findet – was den manuellen Konfigurationsaufwand für den Admin merklich vermindert:
kubectl create -f 05-node-exporter.yml
Damit der »node_exporter« allerdings Zugriff auf sämtliche Informationen des Hostsystems erhält, muss ihn der Admin mit erweiterten Rechten ausstatten, was eine Ergänzung in seiner Yaml-Datei erfordert:
securityContext: privileged: true
Damit greift die Instanz des »node_exporter« auf Ressourcen des Hosts zugreifen und liest etwa dessen »/proc«-Dateisystem aus. Wie das geht, zeigt Listing 7.
Listing 7
05-node-exporter.yml
01 [...] 02 hostPID: true 03 hostIPC: true 04 hostNetwork: true 05 [...] 06 volumeMounts: 07 - name: proc 08 mountPath: /host/proc 09 [...] 10 volumes: 11 - name: proc 12 hostPath: 13 path: /proc 14 [...]
Am Ziel
Nach diesen wenigen Schritten ist Prometheus einsatzbereit und stellt nach dem Aufruf über
minikube service prometheus --namespace=monitoring
eine Menge verschiedener Metriken bereit. Grafana [18] verschafft dem Admin schließlich mit Hilfe grafischer Mittel einen schönen Überblick über den Kubernetes-Cluster:
kubectl create -f 06-grafana-deployment.yml kubectl create -f 07-grafana-service.yml minikube service grafana --namespace=monitoring
Beim Einrichten von Grafana hilft ein vom Autor erstelltes Skript [11], das eine Datenquelle für Prometheus anlegt und zwei nützliche Dashboards für Kubernetes ([19], [20]) importiert:
./configure_grafana.sh
Hat er sich mit den gleichlautenden Benutzernamen und Passwort »admin« angemeldet, wählt der Systemverwalter aus dem Drop-down-Menü die eben erstellten Dashboards aus und erkundet, wie es Abbildung 3 zeigt, welche Informationen der Minikube-Cluster herausrückt.

Abbildung 3: Dashboards, etwa Grafana, helfen beim Visualsieren der beim Monitoring gesammelten Daten.
Unter [18] wartet inzwischen eine Reihe von Dashboards rund um Kubernetes [21]. Hier ist jedoch oft Ausprobieren angesagt: Mitunter scheinen die Entwickler andere Relabeling-Regeln zu verwenden, dann bleiben ganze Bereiche leer. Da das Anpassen der Abfragen recht aufwändig sein kann, eignen sich diese Dashboards eher als ein guter Startpunkt für selbst geschriebene.
Was noch?
Bislang hat der Admin schon eine Menge Informationen über den Kubernetes-Cluster gesammelt, aber da geht noch mehr. Ein interessantes Unterprojekt von Kubernetes heißt »kube-state-metrics«[22]:
kubectl create -f 08-kube-state-metrics-deployment.yml kubectl create -f 09-kube-state-metrics-service.yml
Es holt sich ebenfalls aus dem Kubernetes-API Informationen über vorhandene Objekte und generiert daraus neue Metriken. Die stellt es in einer für Prometheus kompatiblen Form bereit [23]. So liefert es dem Administrator zum Beispiel Hinweise, falls Nodes keine neuen Pods mehr akzeptieren (»unschedulable«) oder Pods auf der Abschussliste stehen. Das komplette Monitoring im Kubernetes-Dashboard zeigt Abbildung 4.

Abbildung 4: Am Ende des kleinen Experiments zeigt das Dashboard von Minikube verschiedenste Werte zu Kubernetes an.
Fazit
Die Demo-Umgebung vermittelt einen Eindruck davon, wie der Admin seinen Kubernetes-Cluster überwacht. Diverse Metriken informieren ihn, was aktuell im Cluster geschieht. Doch weiteres Feintuning hilft: Er kann das produktive Monitoring-System noch um den Alertmanager erweitern und sollte das persistente Speichern von Daten berücksichtigen. Einen interessanten Ansatz verfolgt der Prometheus-Operator von Core OS ([24], [25]), mit dem er ohne viel Aufwand produktionsreifes Kubernetes-Monitoring installiert.
Infos
- Kubernetes: https://kubernetes.io
- Michael Kraus, “Licht ins Dunkel”: Linux-Magazin 06/17, S. 28, https://www.linux-magazin.de/Ausgaben/2017/06/Prometheus
- Beispiel aus der Kubernetes-Dokumentation: https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml
- Mehr zu Relabeling: https://www.robustperception.io/life-of-a-label/
- Prom QL: https://prometheus.io/docs/querying/basics/
- Prometheus 2.0: https://coreos.com/blog/prometheus-2.0-storage-layer-optimization
- Persistent Volumes: https://kubernetes.io/docs/concepts/storage/persistent-volumes/
- Stateful Sets: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
- Minikube: https://github.com/kubernetes/minikube
- Minikube installieren: https://github.com/kubernetes/minikube#installation
- Listings zum Artikel: https://www.linux-magazin.de/static/listings/magazin/2017/08/kubernetes-monitoring/
- RBAC: https://github.com/prometheus/prometheus/blob/master/documentation/examples/rbac-setup.yml
- Prometheus-Docker-Image: https://hub.docker.com/r/prom/prometheus/
- Config Map: https://kubernetes.io/docs/tasks/configure-pod-container/configmap/
- Deployments: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
- »node_exporter«-Image: https://hub.docker.com/r/prom/node-exporter/
- Daemon Set: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
- Grafana: https://grafana.com
- »node_exporter«-Dashboard: https://grafana.com/dashboards/22
- Kubernetes Pod-Dashboard: https://grafana.com/dashboards/737
- Kubernetes-Dashboards: https://grafana.com/dashboards?dataSource=prometheus&search=Kubernetes
- »kube-state-metrics«: https://github.com/kubernetes/kube-state-metrics
- Metriken: https://github.com/kubernetes/kube-state-metrics/tree/master/Documentation
- Prometheus-Operator: https://github.com/coreos/prometheus-operator
- Doku zum Prometheus-Operator: https://coreos.com/operators/prometheus/docs/latest/







