Heute wollen wir uns wieder mal mit Monitoring beschäftigen. Bei Kubernetes interessiert vor allem der Resourcenverbrauch von Pods und Containern. Alles messen kann man mit Prometheus.
cAdvisor ist ein Projekt der Firma Google, wie auch das ganze Kubernetes Projekt von Google stammt. Es geht um Messwerte und Kapazitäten von laufenden Containern, um eine bessere Resourcenplanung im Ökoprojekt hinzukriegen. Diese Metriken werden über eine API zur Verfügung gestellt. Eine typische Metrik ist zum Beispiel:
container_cpu_usage_seconds_total
Eine scrape_config sieht im Prometheus etwa so aus:
- job_name: 'kubernetes-nodes-cadvisor'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor
Es wird also direkt auf die Kubernetes-API im Scope der Nodes zugegriffen, um dort die Messwerte zu bekommen. Diese entstehen im Linux-Kernel des Nodes und werden durch die jeweilige Container-Engine geleitet. Ein Umweg, wie es scheint, in CRI Pods und Container Metriken soll es einen direkten Weg geben, diese Metriken abzurufen. Da wir hier auf Hostebene sind, gibt es keinen Kubernetes-Namespace als Label, da nur Linux Namespaces existieren, die mit dem Kubernetes-Namensvetter nix zutun haben. Schade eigentlich, denn so kann man die Scrape-Config nicht weiter eingrenzen, um etwa nur Metriken von einem Kubernetes-Namespace zu bekommen. Der Weg dazu ist etwas umständlich: Man müsste in der TSDB über die Prometheus Admin API nicht gewünschte Metriken löschen.
Kube State Metrics ist neben cAdvisor der zweite Teil vom Prometheus Community Helm Chart, um Container Metriken zu bekommen. Eine typische Metrik ist hier etwa
kube_deployment_created
Es wird also viel über den Status von Resourcen im Kubernetes-Cluster erzählt. Interessant ist das für die Alarmierung, wenn man etwa wissen will, ob ein Deployment nicht läuft oder in einem komischen Zustand ist. Hier sind wir vollständig in der Kubernetes-Welt angekommen. Ich kann also die Messwerte auf Kubernetes-Namespaces einschränken.
Als letztes und am wenigsten beachtet gibt es Metriken der Container-Engine. Ein typischer Wert ist hier
containerd_cri_image_pulls_total
Andere Werte sind noch:
Alles interessante Werte, die es zu scrapen gibt. Bloss dazu brauch man erstmal einen Scrape-Punkt im Prometheus. Normalerweise gibt es da Exporter, bloss für diesen Dienst ist die Auswahl rar. Entweder weil es zu wenig Interesse an diesen Werte gibt, oder weil es zu trivial ist, diese zu sammeln.
In der Container-Engine muss man das Sammeln der Metriken und Ausgabe über einen Endpunkt erstmal einschalten. Bei containerd sieht das etwa so aus:
# cat /etc/containerd/config.toml
# https://github.com/containerd/containerd/blob/main/docs/ops.md
[metrics]
address = "127.0.0.1:1338"
Für Crio metrics funktioniert das ähnlich.
Wenn man grosszügig ist, ersetzt man 127.0.0.1
durch 0.0.0.0
und schon lauscht der Dienst auf allen Netzwerkinterfaces des Nodes.
Wir bräuchten dann nur noch ein daemonset
um einen Pod auf allen Nodes zu starten, der uns durch einen Proxy Zugang zu diesen Port gewährt:
Ist natürlich ein Denkfehler. Wir sind auf dem Localhost des Pods und nicht des Hosts, auch mit hostNetwork
Wir brauch also schon etwas, was den Verkehr vom Pod-Network auf den Host weiterleitet. Das geht mit Socat:
Voila, auf Port 8080 haben wir die versionierten Container Metriken und können die mit einer scrape_config
abholen.
- job_name: 'containerd-metrics-proxy'
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- kube-system
relabel_configs:
- source_labels: [__meta_kubernetes_service_name]
separator: ;
regex: metrics-proxy
replacement: $1
action: keep
- source_labels: [__meta_kubernetes_service_name]
target_label: job
- source_labels: [__meta_kubernetes_endpoint_port_name]
target_label: port
metrics_path: /v1/metrics
Übrigens: Alle verwendeten Container Images gibt es auf https://github.com/mcsps/docker-images.
Viel Spass!