fix(apache): Sekunden-Kollision behoben (log_time + converter) — Node lieferte gar nichts mehr
Echte x22-Logs: 2000 Zeilen -> 286 Kollisionen (duplicate sample). Telegraf uebernimmt den Log-Zeitstempel; bei mehreren Treffern pro Sekunde kollidiert der +1ms-Aufschlag mit echten Zeilen. Prometheus weist den Batch ab, Telegraf retryt endlos -> FIFO steht -> Node liefert GAR NICHTS mehr. Fix: eigenes Grok-Muster mit log_time als Feld (Telegraf nutzt eigene ns-Uhr) + processors.converter, damit resp_code/verb Tags bleiben. Gemessen: 2000/2000 Samples, 0 Kollisionen. Ausserdem: Einheiten-Waechter im Archiver (ms statt s -> Abbruch statt nutzloser Block).
This commit is contained in:
1 parent
5a213eb580
commit
5483a4fea8
7 files changed
+626
-7
No files matched your search
@@ -87,6 +87,66 @@ Jede Serie trägt ein `path`-Tag, damit man in Grafana nach Datei filtert. Über
|
||||
|
||||
**Zusätzlich** wird die `CustomLog`-Direktive aus `/etc/apache2` bzw. `/etc/httpd` ausgewertet — die verlässlichste Quelle, `${APACHE_LOG_DIR}` wird aufgelöst.
|
||||
|
||||
### Sekunden-Kollisionen: der stille Totalausfall
|
||||
|
||||
**Symptom.** Ein Node liefert **gar nichts** mehr — nicht nur die Apache-Metriken,
|
||||
sondern auch `system_uptime`, CPU, Disk. Andere Nodes laufen normal.
|
||||
|
||||
**Ursache.** Access-Logs haben nur **Sekunden**-Auflösung:
|
||||
|
||||
```
|
||||
138.199.15.193 - - [14/Sep/2026:01:16:49 +0200] "GET /image/x HTTP/1.1" 200 25454
|
||||
```
|
||||
|
||||
Telegraf übernimmt einen erkannten Zeitstempel als **Sample-Zeit**. Treffen
|
||||
mehrere Zeilen auf dieselbe Sekunde, vergibt es `+1 ms` Aufschlag pro Zeile.
|
||||
Bei hoher Last läuft dieser Aufschlag in die nächste Sekunde und kollidiert mit
|
||||
echten Zeilen derselben Serie:
|
||||
|
||||
```
|
||||
duplicate sample for timestamp 1789340156000; overrides not allowed:
|
||||
existing 25646, new value 14178
|
||||
```
|
||||
|
||||
Prometheus weist den Batch ab. Telegraf **wiederholt ihn endlos** — die
|
||||
Remote-Write-Queue steht, und weil sie blockiert, kommt vom ganzen Node kein
|
||||
Sample mehr an.
|
||||
|
||||
**Gemessen** an echten x22-Logs (2000 Zeilen): **286 Kollisionen**, 1098 statt
|
||||
2000 eindeutige Zeitstempel.
|
||||
|
||||
**Fix.** Im eigenen Grok-Muster heißt das Zeitfeld **`log_time`** statt `ts`:
|
||||
|
||||
```toml
|
||||
grok_custom_patterns = '''
|
||||
APACHE_LINE (?:%{HOSTNAME:vh}(?::%{NUMBER:vport})? )?%{IPORHOST:client_ip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:log_time}\] ...
|
||||
'''
|
||||
```
|
||||
|
||||
Telegraf erkennt kein Zeitfeld mehr und stempelt mit **eigener Uhr in
|
||||
Nanosekunden**. Die Log-Zeit bleibt als Feld erhalten. Gemessen: 2000 von 2000
|
||||
Samples, **0 Kollisionen**.
|
||||
|
||||
Damit `resp_code` und `verb` weiterhin **Tags** sind (das eingebaute Muster
|
||||
liefert sie als Tags, ein eigenes Muster als Felder — sonst brechen Panels, die
|
||||
danach filtern):
|
||||
|
||||
```toml
|
||||
[[processors.converter]]
|
||||
namepass = ["apache_access"]
|
||||
order = 1
|
||||
[processors.converter.fields]
|
||||
tag = ["resp_code", "verb"]
|
||||
```
|
||||
|
||||
**Diagnose.** `--diagnose` zeigt ein `E!` bzw. die Fehlerzeile; zentral im
|
||||
Prometheus-Log:
|
||||
|
||||
```sh
|
||||
docker logs observability-prometheus 2>&1 | grep -c "duplicate sample"
|
||||
docker logs observability-prometheus 2>&1 | grep -c "Out of order"
|
||||
```
|
||||
|
||||
### Leserechte: der stille Killer
|
||||
|
||||
Auf x22 waren **64 von 84 Logpfaden für `telegraf` unlesbar** — `inputs.tail` meldet das **nicht**, es liefert einfach nichts, und der Node sieht „aktiv" aus. Zwei verschiedene Rechte-Welten:
|
||||
@@ -412,6 +472,22 @@ Wer kein sudo hat, aber in der Gruppe `docker` ist: Container-Variante aus
|
||||
[netbird-observability/stacks/telegraf-node](https://gitea.m-m.bio/mm/netbird-observability) (privates Repo).
|
||||
Dort ist `network_mode: host` gesetzt — ohne das sieht Telegraf nur `lo`+`eth0` statt der echten Interfaces.
|
||||
|
||||
## Archiv-Import: Schutzschichten
|
||||
|
||||
Alte Logs lassen sich als Prometheus-Blöcke archivieren (`scripts/apache-log-archive.py`).
|
||||
Der Import in eine **laufende** TSDB ist heikel — drei Fehler sind möglich, alle
|
||||
still:
|
||||
|
||||
| Fehler | Folge | Schutz |
|
||||
|---|---|---|
|
||||
| Zeitstempel in **Millisekunden** statt Sekunden | Blöcke im Jahr 58.662, Prometheus verwirft sie als „too far into the future" | Einheiten-Wächter im Skript (Abbruch ab Jahr 2100) |
|
||||
| Block reicht in die **Zukunft** | Prometheus verschiebt seine Zeitreferenz, **alle** Live-Samples gelten als „too old" — alle Nodes fallen aus | Zukunft-Prüfung in `prom-archive-import.sh` (Abbruch, Toleranz 5 min) |
|
||||
| **`rm -rf <tsdb>/01M*`** beim Aufräumen | Glob trifft **alle** Blöcke → gesamte Historie gelöscht | kein Glob; nur exakte Block-IDs; Pflicht-Snapshot vorher |
|
||||
|
||||
Deshalb: **Archiv-Blöcke nie in die Produktions-TSDB**, sondern in die getrennte
|
||||
Instanz (`stacks/archive-prometheus`, Port 9091). Sie nimmt keine Live-Daten an
|
||||
und kann die Produktion nicht beeinflussen.
|
||||
|
||||
## Sicherheit
|
||||
|
||||
- Der Proxy verlangt Bearer-Token; das Header wird vor dem Weiterleiten entfernt und liegt damit nicht bei Prometheus/Loki.
|
||||
|
||||
Reference in new issue
Block a user