node-exporter-DaemonSet in CrashLoopBackOff (4880 Restarts) + Cluster-Scrape seit 2026-08-01 tot #45

Closed
opened 2026-08-01 01:57:00 +00:00 by sorb · 3 comments
Owner

Aufgedeckt durch das Alerting aus #32, unmittelbar nach dessen Rollout auf CFGMON (2026-08-01). Es sind zwei getrennte Probleme, von denen nur das zweite neu ist.

Diagnostiziert von CFGMON aus, per kube-state-metrics und den remote-geschriebenen Serien — auf dem Host selbst wurde nichts geprüft, dort steht kein kubectl zur Verfügung. Vollständiger Befund im Backlog: MATRIX-05.

1. Der Pod crasht seit Monaten (chronisch, nicht neu)

Messwert Stand 2026-08-01
Pod prometheus-node-exporter-4wwn7, Restarts 4880, davon 1970 in 7 Tagen
Vorgängerpod …-fv7hj, Zählerstand vor 30 Tagen 13918
aktuelle Rate ~12/h — entspricht dem CrashLoopBackOff-Deckel von 5 min
last_terminated_reason Error (Exit ≠ 0, kein OOMKill)
waiting_reason / ready CrashLoopBackOff / 0

Das besteht mindestens seit 30 Tagen. Neu ist nicht das Problem, sondern seine Sichtbarkeit — die Regel KubePodRestartLoop kam erst mit #32 dazu. Wie beim Synapse-Port hat das Alerting damit einen stillen Altfehler aufgedeckt.

Vermutete Ursache, nicht verifiziert: Der Pod läuft mit hostNetwork: true und will Port 9100 auf dem Host binden. Dort hört bereits ein eigenständiger node-exporter — derselbe, den CFGMON als Job k3s_host_node direkt auf 10.0.0.2:9100 scrapt und der 2706 Metriken sauber ausliefert. Zwei Exporter, ein Port; der Pod bekäme address already in use und beendete sich sofort, was zu reason: Error ohne OOM passt.

Zum Bestätigen auf dem Host:

ss -lntp | grep :9100
kubectl -n monitoring logs prometheus-node-exporter-4wwn7 --previous | tail -20

2. Der Cluster-Scrape ist am 2026-08-01 um 01:19 UTC ausgefallen (akut)

Messwert Stand
up-Mittel 24 h für prometheus-node-exporter.monitoring.svc.cluster.local:9100 98,3 %
Zustandswechsel in 24 h 1 — einmal runter, nicht zurück
Host-Uptime 77,6 Tage → kein Reboot

Ein Pod, der 12× pro Stunde stirbt, kann kein Target sein, das zu 98 % up ist. Geantwortet hat also nie der Pod, sondern der eigenständige Exporter über die Host-IP. Der Pod hat hostNetwork, sein Pod-IP ist die öffentliche 49.13.132.245, dorthin zeigt der Service-Endpoint — und dort kommt seit 01:19 nichts mehr.

Von CFGMON aus gemessen:

Pfad Ergebnis
10.0.0.2:9100 (privat) offen, 2706 Metriken
49.13.132.245:9100 (öffentlich) keine Antwort
49.13.132.245:80 / :443 offen — Host lebt

Ohne Reboot heißt das: die Erreichbarkeit auf 9100 wurde in der Nacht eingeengt. Zwei Möglichkeiten, von außen nicht unterscheidbar:

  1. Der Exporter bindet jetzt 10.0.0.2:9100 statt 0.0.0.0:9100.
  2. Eine ufw-Regel wurde geändert — die dokumentierte Allow-Liste führt 9100 ohnehin nicht auf, die private Zustellung muss also über eine Interface- oder Subnetz-Regel laufen.

Das fällt zeitlich exakt in das Fenster der Synapse-Portkorrektur derselben Nacht. Prüfen mit ss -lntp | grep :9100 und ufw status numbered.

Fix — es ist ein node-exporter zu viel

Weg B (Vorschlag): Den DaemonSet-Exporter abschalten (nodeExporter.enabled: false in den kube-prometheus-stack-Values) und das Cluster-Alloy statt auf den Service-Namen direkt auf 10.0.0.2:9100 zeigen lassen. Beendet den Crashloop und erhält die enge Bindung ans private Netz, die gerade erst gesetzt wurde.

Weg A: Den eigenständigen Exporter stilllegen und dem DaemonSet den Port überlassen. Ebenfalls sauber, aber er bindet dann wieder 0.0.0.0 — also auch die öffentliche IP, abgesichert nur noch durch ufw und die Cloud-Firewall. Das nähme die Einschränkung zurück.

Nebenbefund — Job-Label kollidiert zwischen zwei Hosts

Das Label prometheus.scrape.node_exporter existiert zweimal, weil CFGMONs Alloy und das Cluster-Alloy ihre Scrape-Komponente gleich benennen:

up=1  instance=node-exporter:9100                               -> CFGMON  (Kernel 6.8.0-136-generic)
up=0  instance=prometheus-node-exporter.monitoring.svc...:9100  -> MATRIX

Die Serien kollidieren nicht, instance trennt sie. Aber jede Abfrage, die nur nach job filtert, mischt zwei Maschinen — und in Alarmtexten steht dann ein Job-Name, der nicht sagt, welcher Host gemeint ist. Ein External Label auf der Remote-Write-Seite dieses Clusters (cluster="matrix") würde das trennen.


Die beiden zugehörigen Alarme (KubePodRestartLoop und TargetDown) sind auf CFGMON bewusst nicht stummgeschaltet — sie zeigen auf ein offenes Problem und melden sich mit repeat_interval: 4h alle vier Stunden, bis der doppelte node-exporter aufgelöst ist.

Aufgedeckt durch das Alerting aus #32, unmittelbar nach dessen Rollout auf CFGMON (2026-08-01). Es sind **zwei getrennte Probleme**, von denen nur das zweite neu ist. Diagnostiziert von CFGMON aus, per kube-state-metrics und den remote-geschriebenen Serien — **auf dem Host selbst wurde nichts geprüft**, dort steht kein `kubectl` zur Verfügung. Vollständiger Befund im Backlog: [MATRIX-05](https://rohana.axion1337.de/sorb/Backlogs/src/branch/main/hosts/matrix.md). ## 1. Der Pod crasht seit Monaten (chronisch, **nicht** neu) | Messwert | Stand 2026-08-01 | |---|---| | Pod `prometheus-node-exporter-4wwn7`, Restarts | **4880**, davon 1970 in 7 Tagen | | Vorgängerpod `…-fv7hj`, Zählerstand vor 30 Tagen | 13918 | | aktuelle Rate | ~12/h — entspricht dem CrashLoopBackOff-Deckel von 5 min | | `last_terminated_reason` | `Error` (Exit ≠ 0, **kein** OOMKill) | | `waiting_reason` / `ready` | `CrashLoopBackOff` / `0` | Das besteht mindestens seit 30 Tagen. Neu ist nicht das Problem, sondern seine Sichtbarkeit — die Regel `KubePodRestartLoop` kam erst mit #32 dazu. Wie beim Synapse-Port hat das Alerting damit einen stillen Altfehler aufgedeckt. **Vermutete Ursache, nicht verifiziert:** Der Pod läuft mit `hostNetwork: true` und will Port 9100 auf dem Host binden. Dort hört bereits ein eigenständiger node-exporter — derselbe, den CFGMON als Job `k3s_host_node` direkt auf `10.0.0.2:9100` scrapt und der 2706 Metriken sauber ausliefert. Zwei Exporter, ein Port; der Pod bekäme `address already in use` und beendete sich sofort, was zu `reason: Error` ohne OOM passt. Zum Bestätigen auf dem Host: ``` ss -lntp | grep :9100 kubectl -n monitoring logs prometheus-node-exporter-4wwn7 --previous | tail -20 ``` ## 2. Der Cluster-Scrape ist am 2026-08-01 um 01:19 UTC ausgefallen (akut) | Messwert | Stand | |---|---| | `up`-Mittel 24 h für `prometheus-node-exporter.monitoring.svc.cluster.local:9100` | 98,3 % | | Zustandswechsel in 24 h | **1** — einmal runter, nicht zurück | | Host-Uptime | 77,6 Tage → **kein Reboot** | Ein Pod, der 12× pro Stunde stirbt, kann kein Target sein, das zu 98 % up ist. Geantwortet hat also nie der Pod, sondern der eigenständige Exporter über die Host-IP. Der Pod hat `hostNetwork`, sein Pod-IP ist die öffentliche `49.13.132.245`, dorthin zeigt der Service-Endpoint — und dort kommt seit 01:19 nichts mehr. Von CFGMON aus gemessen: | Pfad | Ergebnis | |---|---| | `10.0.0.2:9100` (privat) | offen, 2706 Metriken | | `49.13.132.245:9100` (öffentlich) | **keine Antwort** | | `49.13.132.245:80` / `:443` | offen — Host lebt | Ohne Reboot heißt das: die Erreichbarkeit auf 9100 wurde in der Nacht eingeengt. Zwei Möglichkeiten, von außen nicht unterscheidbar: 1. Der Exporter bindet jetzt `10.0.0.2:9100` statt `0.0.0.0:9100`. 2. Eine `ufw`-Regel wurde geändert — die dokumentierte Allow-Liste führt 9100 ohnehin nicht auf, die private Zustellung muss also über eine Interface- oder Subnetz-Regel laufen. Das fällt zeitlich exakt in das Fenster der Synapse-Portkorrektur derselben Nacht. Prüfen mit `ss -lntp | grep :9100` und `ufw status numbered`. ## Fix — es ist ein node-exporter zu viel **Weg B (Vorschlag):** Den DaemonSet-Exporter abschalten (`nodeExporter.enabled: false` in den kube-prometheus-stack-Values) und das Cluster-Alloy statt auf den Service-Namen direkt auf `10.0.0.2:9100` zeigen lassen. Beendet den Crashloop und erhält die enge Bindung ans private Netz, die gerade erst gesetzt wurde. **Weg A:** Den eigenständigen Exporter stilllegen und dem DaemonSet den Port überlassen. Ebenfalls sauber, aber er bindet dann wieder `0.0.0.0` — also auch die öffentliche IP, abgesichert nur noch durch `ufw` und die Cloud-Firewall. Das nähme die Einschränkung zurück. ## Nebenbefund — Job-Label kollidiert zwischen zwei Hosts Das Label `prometheus.scrape.node_exporter` existiert zweimal, weil CFGMONs Alloy und das Cluster-Alloy ihre Scrape-Komponente gleich benennen: ``` up=1 instance=node-exporter:9100 -> CFGMON (Kernel 6.8.0-136-generic) up=0 instance=prometheus-node-exporter.monitoring.svc...:9100 -> MATRIX ``` Die Serien kollidieren nicht, `instance` trennt sie. Aber jede Abfrage, die nur nach `job` filtert, mischt zwei Maschinen — und in Alarmtexten steht dann ein Job-Name, der nicht sagt, welcher Host gemeint ist. Ein External Label auf der Remote-Write-Seite dieses Clusters (`cluster="matrix"`) würde das trennen. --- Die beiden zugehörigen Alarme (`KubePodRestartLoop` und `TargetDown`) sind auf CFGMON **bewusst nicht stummgeschaltet** — sie zeigen auf ein offenes Problem und melden sich mit `repeat_interval: 4h` alle vier Stunden, bis der doppelte node-exporter aufgelöst ist.
Author
Owner

Host-Prüfung durchgeführt (2026-08-01 ~03:55, per SSH auf MATRIX) — die Portkonflikt-These ist bestätigt, die Firewall-These widerlegt:

  1. Crashloop-Ursache bewiesen: Pod-Log des letzten Absturzes endet mit listen tcp 0.0.0.0:9100: bind: address already in use; den Port hält der systemd-Dienst prometheus-node-exporter (PID 1036). Der DaemonSet-Pod (hostNetwork: true, 4883 Restarts) kann nie binden → doppelter Exporter, deckt sich mit MATRIX-05.
  2. ufw unangetastet: user.rules/user6.rules mtime 29.04., keine 9100-Regel für extern (nur Anywhere ALLOW 10.0.0.0/16). Es ist heute Nacht keine Regel „mitgewandert". 49.13.132.245:9100 war extern nie freigegeben; der 200er vom Host selbst läuft über Loopback. Der reale CFGMON-Pfad 10.0.0.2:9100 (privates Netz) antwortet unverändert.
  3. Warum der Service-Pfad „bis 01:19 funktionierte": kube-proxy hat aktuell -m comment "monitoring/prometheus-node-exporter:metrics has no endpoints" -j REJECT für die ClusterIP gesetzt. Vorher zeigte der Endpoint des hostNetwork-Pods (Pod-IP = Host-IP) in dessen „Ready"-Momenten auf den gesunden systemd-Exporter — der Service lieferte also nur zufällig über den Port-Konkurrenten des eigenen Pods. Seit der Endpoint dauerhaft NotReady ist, rejected kube-proxy. Kausalzusammenhang mit den Alloy-Restarts (01:14/01:20 UTC) bleibt unbewiesen; der Grundfehler ist Monate alt.

Fix-Empfehlung (Weg A): k8s-DaemonSet + Service prometheus-node-exporter entfernen und den Alloy-Scrape darauf streichen — der systemd-Exporter auf dem Host ist die etablierte Quelle (CFGMON scrapt ihn direkt via 10.0.0.2) und das DaemonSet liefert exakt dieselben Host-Metriken doppelt. Das beendet Crashloop, beide Alarme und die Metrik-Doppelung in einem Schritt. Weg B (systemd-Dienst weg, DaemonSet behalten) würde den CFGMON-Scrape-Pfad brechen und mehr umbauen als nötig.

**Host-Prüfung durchgeführt (2026-08-01 ~03:55, per SSH auf MATRIX) — die Portkonflikt-These ist bestätigt, die Firewall-These widerlegt:** 1. **Crashloop-Ursache bewiesen**: Pod-Log des letzten Absturzes endet mit `listen tcp 0.0.0.0:9100: bind: address already in use`; den Port hält der **systemd-Dienst** `prometheus-node-exporter` (PID 1036). Der DaemonSet-Pod (`hostNetwork: true`, 4883 Restarts) kann nie binden → doppelter Exporter, deckt sich mit MATRIX-05. 2. **ufw unangetastet**: `user.rules`/`user6.rules` mtime **29.04.**, keine 9100-Regel für extern (nur `Anywhere ALLOW 10.0.0.0/16`). Es ist heute Nacht keine Regel „mitgewandert". `49.13.132.245:9100` war extern nie freigegeben; der 200er vom Host selbst läuft über Loopback. Der reale CFGMON-Pfad `10.0.0.2:9100` (privates Netz) antwortet unverändert. 3. **Warum der Service-Pfad „bis 01:19 funktionierte"**: kube-proxy hat aktuell `-m comment "monitoring/prometheus-node-exporter:metrics has no endpoints" -j REJECT` für die ClusterIP gesetzt. Vorher zeigte der Endpoint des hostNetwork-Pods (Pod-IP = Host-IP) in dessen „Ready"-Momenten auf den **gesunden systemd-Exporter** — der Service lieferte also nur zufällig über den Port-Konkurrenten des eigenen Pods. Seit der Endpoint dauerhaft NotReady ist, rejected kube-proxy. Kausalzusammenhang mit den Alloy-Restarts (01:14/01:20 UTC) bleibt unbewiesen; der Grundfehler ist Monate alt. **Fix-Empfehlung (Weg A)**: k8s-DaemonSet + Service `prometheus-node-exporter` entfernen und den Alloy-Scrape darauf streichen — der systemd-Exporter auf dem Host ist die etablierte Quelle (CFGMON scrapt ihn direkt via 10.0.0.2) und das DaemonSet liefert exakt dieselben Host-Metriken doppelt. Das beendet Crashloop, beide Alarme und die Metrik-Doppelung in einem Schritt. Weg B (systemd-Dienst weg, DaemonSet behalten) würde den CFGMON-Scrape-Pfad brechen und mehr umbauen als nötig.
Author
Owner

Erledigt (2026-08-01 ~05:15): Fix deployt und beidseitig bestätigt.

  • gitops 93ee6a3 (Weg A): node-exporter-HelmRelease + Alloy-Scrape entfernt, Flux hat gepruned — DaemonSet/Service/Pod restlos weg (der Pod stand zuletzt bei 4886 Restarts).
  • Beide Alarme haben sich im Alerts-Raum selbst aufgelöst (TargetDown 04:15, KubePodRestartLoop 04:58 — Letzterer verzögert, weil increase(...[1h]) erst das Stunden-Fenster leeren muss) und sind per Edit abgehakt.
  • Host-Metriken laufen unverändert über den systemd-Exporter → CFGMON (10.0.0.2:9100, verifiziert).
  • Backlog MATRIX-05 ist mit vollständiger Beweiskette geschlossen; ufw-These widerlegt (Regeldateien seit April unangetastet).

Damit sind alle drei vom neuen Alerting (#32) aufgedeckten Altfehler abgearbeitet: Synapse-Port , node-exporter , GAME-01 eingegrenzt + gesilenced bis 04.08.

**Erledigt** (2026-08-01 ~05:15): Fix deployt und beidseitig bestätigt. - gitops `93ee6a3` (Weg A): node-exporter-HelmRelease + Alloy-Scrape entfernt, Flux hat gepruned — DaemonSet/Service/Pod restlos weg (der Pod stand zuletzt bei 4886 Restarts). - Beide Alarme haben sich im Alerts-Raum selbst aufgelöst (TargetDown 04:15, KubePodRestartLoop 04:58 — Letzterer verzögert, weil `increase(...[1h])` erst das Stunden-Fenster leeren muss) und sind per Edit abgehakt. - Host-Metriken laufen unverändert über den systemd-Exporter → CFGMON (`10.0.0.2:9100`, verifiziert). - Backlog MATRIX-05 ist mit vollständiger Beweiskette geschlossen; ufw-These widerlegt (Regeldateien seit April unangetastet). Damit sind alle drei vom neuen Alerting (#32) aufgedeckten Altfehler abgearbeitet: Synapse-Port ✅, node-exporter ✅, GAME-01 eingegrenzt + gesilenced bis 04.08.
sorb closed this issue 2026-08-01 03:14:41 +00:00
Author
Owner

Migriert nach git.lab: axion1337.chat/axion1337.chat-gitops#44 (nur im Lab bzw. via VPN erreichbar — das Lab ist seit 2026-08-01 die Quelle der Wahrheit, siehe gitops#48). Weiterarbeit dort; dieses Gitea-Issue bleibt als Verweis stehen.

**Migriert nach git.lab**: [axion1337.chat/axion1337.chat-gitops#44](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/44) (nur im Lab bzw. via VPN erreichbar — das Lab ist seit 2026-08-01 die Quelle der Wahrheit, siehe gitops#48). Weiterarbeit dort; dieses Gitea-Issue bleibt als Verweis stehen.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sorb/axion1337.chat-gitops#45