529 lines
26 KiB
Markdown
529 lines
26 KiB
Markdown
# netbird-telegraf-installer
|
|
|
|
Ein Befehl, und eine Node liefert Metriken + Logs an die zentrale Observability auf dem imac.
|
|
Der Ausgang läuft über den **NetBird-Reverse-Proxy** (`imac-prometheus.x05.idx.wf`, `imac-loki.x05.idx.wf`)
|
|
mit **Bearer-Token** — dadurch funktioniert der Installer auch auf Maschinen, die **kein NetBird-Peer** sind
|
|
(Büro-LAN, Kundenlaptop, CGNAT, VM ohne Client).
|
|
|
|
## Diagnose: „Logs kommen nicht an"
|
|
|
|
Ein Befehl zeigt, warum:
|
|
|
|
```sh
|
|
curl -fsSL https://gitea.m-m.bio/mm/netbird-telegraf-installer/raw/branch/main/install.sh \
|
|
| sh -s -- --diagnose
|
|
```
|
|
|
|
Er prüft genau die Stellen, die schon **still** versagt haben (kein `E!` in keinem Log):
|
|
|
|
| Prüfung | Warum |
|
|
|---|---|
|
|
| Dienst-Benutzer + Gruppen | Telegraf läuft als `telegraf`, nicht als root |
|
|
| Jede Datei aus der `files`-Liste | Existenz, Größe, **Lesbarkeit aus Sicht des Dienst-Benutzers** |
|
|
| Parser-Lauf ohne Filter | echte `E!`-Zeilen sichtbar machen |
|
|
| Offset-Zustand | erklärt, warum eine bestehende Datei „leer" wirkt |
|
|
|
|
Beispielausgabe:
|
|
|
|
```
|
|
-- Logpfade aus der aktiven Conf --
|
|
OK /var/log/apache2/keyhelp/access.log (75 Bytes)
|
|
NICHT LESBAR /home/users/u1/logs/d1/access.log (Benutzer telegraf) ← URSACHE
|
|
-> 3 Pfade, 2 lesbar, 0 leer, 1 nicht lesbar
|
|
```
|
|
|
|
**Wichtig:** `initial_read_offset = "saved-or-end"` heißt, dass beim **ersten** Lauf nur **Neues** gelesen wird. Bestehende Zeilen kommen erst mit neuen Zugriffen — für einen sofortigen Test eine Seite aufrufen und ein Intervall abwarten.
|
|
|
|
## Der Konfig-Test prüft ALLE Dateien
|
|
|
|
Ein Detail, das schon eine Node lahmgelegt hat: **Nie mit `--input-filter` prüfen.**
|
|
|
|
```sh
|
|
# FALSCH — validiert nur die gefilterten Plugins:
|
|
telegraf --config … --config-directory … --test --input-filter cpu:mem
|
|
|
|
# RICHTIG — parst alle Dateien, genau wie der Dienststart:
|
|
telegraf --config … --config-directory … --test --test-wait 1
|
|
```
|
|
|
|
Mit `--input-filter cpu:mem` überspringt Telegraf alle übrigen Konfigdateien. Ein ungültiges Feld in `telegraf.d/apache.conf` lief damit durch, der Installer meldete **„OK — Node liefert"**, und erst der Dienststart scheiterte danach mit:
|
|
|
|
```
|
|
Job for telegraf.service failed because the control process exited with error code.
|
|
```
|
|
|
|
Der Installer prüft deshalb ohne Filter und wertet nur echte Parser-Fehler (`E! … loading config file`) als Abbruch — nicht jede Warnung, denn ein fehlendes Input-Binary (`nvidia-smi`) zeigt sich erst beim Start, nicht beim Parsen.
|
|
|
|
## Apache-Logs
|
|
|
|
Mit `--role apache` (oder automatisch, wenn `apache2ctl`/`httpd` gefunden wird) bindet der Installer Apache ein — auf **zwei** Wegen aus derselben Datei:
|
|
|
|
| Ziel | Was | Wofür |
|
|
|---|---|---|
|
|
| **Loki** | jede Zeile roh | Fehlersuche im Einzelfall |
|
|
| **Prometheus** | `apache_access` mit Tags `resp_code`, `verb` | Request-Rate, Status-Klassen, Error-Rate — Panels und Alerts |
|
|
|
|
### Logpfade werden automatisch gesammelt
|
|
|
|
Der Installer **sammelt alle passenden Muster** — nicht nur das erste. Auf einem KeyHelp-Host laufen zwei Strukturen parallel, und die globale Standarddatei ist leer:
|
|
|
|
| Panel | Pfadmuster |
|
|
|---|---|
|
|
| **KeyHelp** | `/home/users/<user>/logs/<domain>/access.log` (**zweistufig**, pro Domain) |
|
|
| **KeyHelp** | `/var/log/apache2/<vhost>/access.log` (z. B. `keyhelp/access.log`) |
|
|
| Plesk | `/var/www/vhosts/<domain>/logs/access_log` |
|
|
| cPanel | `/usr/local/apache/domlogs/<domain>` |
|
|
| Klassisch | `/var/log/apache2/access.log`, `/var/log/httpd/access_log` |
|
|
|
|
Verifiziert auf x22: Die Requests liegen unter `/home/users/classi/logs/classi.parts/access.log` **und** `/var/log/apache2/keyhelp/access.log`, während `/var/log/apache2/access.log` **0 Bytes** hat. Ein Input auf die leere Datei hätte still nichts geliefert — leere Standarddateien werden per `-s`-Test ausgeschlossen.
|
|
|
|
Alle gefundenen Pfade landen als TOML-Liste in der Conf:
|
|
|
|
```toml
|
|
files = ["/var/log/apache2/*/access.log", "/home/users/*/logs/*/access.log"]
|
|
```
|
|
|
|
Jede Serie trägt ein `path`-Tag, damit man in Grafana nach Datei filtert. Überschreiben mit `--apache-log <pfad>` (mehrere Pfade leerzeichengetrennt).
|
|
|
|
**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:
|
|
|
|
| Ort | Rechte | Was hilft |
|
|
|---|---|---|
|
|
| `/var/log/apache2/…` | `root:adm 0640` | `usermod -aG adm telegraf` |
|
|
| `/home/users/<user>/logs/…` | `<user>:<user> 0640` | **`adm` hilft nicht** — ACL nötig |
|
|
|
|
Der Installer setzt dafür **ACLs** (`setfacl -R -m u:telegraf:rX` plus eine Default-ACL, damit neue Domain-Ordner das Recht erben). Das `acl`-Paket wird bei Bedarf nachinstalliert. Der Dienst bleibt im eingeschränkten Konto — kein `root` nötig.
|
|
|
|
Danach folgt ein **Gegentest**: Der Installer liest eine echte Logdatei als Dienst-Benutzer. Meldet er
|
|
|
|
```
|
|
[netbird-telegraf] Gegentest: 'telegraf' kann Apache-Logs lesen (…)
|
|
```
|
|
|
|
ist die Kette nachweislich in Ordnung.
|
|
|
|
### Glob-Muster statt Einzelpfade
|
|
|
|
Die Conf enthält **Muster**, nicht die expandierten Dateinamen:
|
|
|
|
```toml
|
|
files = ["/var/log/apache2/*/access.log", "/home/users/*/logs/*/access.log"]
|
|
```
|
|
|
|
Damit wird eine **neu angelegte Domain sofort erfasst**, ohne dass der Installer erneut laufen muss. (Der Installer schaltet beim Rendern `set -f` ein — sonst würde die Shell die Muster selbst auflösen und feste Pfade in die Conf schreiben.)
|
|
|
|
### `/etc/default/telegraf` wird gesourct — Werte müssen gequotet sein
|
|
|
|
Diese Datei wird mit `. /etc/default/telegraf` eingelesen (vom Installer und von der Telegraf-Unit). Ein **ungequoteter** Wert mit Leerzeichen bricht das Sourcing ab — bei mehreren Logpfaden versucht die Shell, den zweiten Pfad als Befehl auszuführen:
|
|
|
|
```
|
|
sh: /etc/default/telegraf: /home/users/classi/logs/classi.parts/access.log: Permission denied
|
|
```
|
|
|
|
Der Installer schreibt `APACHE_LOG='…'` deshalb **mit einfachen Anführungszeichen**. Zusätzlich liest er die Datei über `load_defaults` ein, das syntaktisch kaputte Dateien sichert und überschreibt statt abzubrechen — eine Node lässt sich so auch dann reparieren, wenn ihre Defaults-Datei bereits defekt ist.
|
|
|
|
### Zwei Fallstricke
|
|
|
|
**1. `from_beginning` existiert bei `inputs.tail` nicht.** Ein solcher Block lässt den Dienst beim Start hart scheitern — `systemctl start` schlägt fehl und **alle** Metriken fallen aus, nicht nur die Apache-Logs:
|
|
|
|
```
|
|
E! loading config file /etc/telegraf/telegraf.d/apache.conf failed:
|
|
plugin inputs.tail: line 2: configuration specified the fields ["from_beginning"],
|
|
but they were not used ... does not exist in this version
|
|
```
|
|
|
|
Richtig ist `initial_read_offset = "saved-or-end"` (Default) — damit wird beim ersten Lauf nicht die komplette Historie ausgeschüttet. Für einen Test gegen eine vorgefüllte Datei `"beginning"` setzen.
|
|
|
|
**2. Die Grok-Muster heißen `COMMON_LOG_FORMAT` und `COMBINED_LOG_FORMAT`** — nicht `HTTPD_COMMON_LOG`/`HTTPD_COMBINED_LOG_FORMAT`. Die `HTTPD_*`-Namen aus anderen Grok-Sammlungen kennt Telegraf nicht:
|
|
|
|
```
|
|
E! [inputs.tail] Creating parser: no pattern found for %{HTTPD_COMBINED_LOG_FORMAT}
|
|
```
|
|
|
|
Die Reihenfolge in `grok_patterns` ist spezifisch → allgemein, damit die VHost-Varianten (`example.com:80 ...`) vor der einfachen Form greifen.
|
|
|
|
### Response-Time
|
|
|
|
Common und Combined Log Format enthalten **keine** Antwortzeit. Für `resp_time` in den Metriken muss das LogFormat in Apache erweitert werden:
|
|
|
|
```apache
|
|
LogFormat "%h %l %u %t \"%r\" %>s %b \"%D\" \"%{User-agent}i\"" combined_time
|
|
CustomLog ${APACHE_LOG_DIR}/access.log combined_time
|
|
```
|
|
|
|
`%D` = Dauer in Mikrosekunden. Danach im Grok-Muster als Feld ergänzen. Ohne diese Änderung sind alle anderen Werte trotzdem verfügbar — nur die Antwortzeit fehlt.
|
|
|
|
## Auto-Updater und Force-Updater
|
|
|
|
Der Installer hält sich auf den Nodes selbst aktuell.
|
|
|
|
### Prüfen
|
|
|
|
```sh
|
|
sh install.sh --version # installierte + verfügbare Version
|
|
sh install.sh --check # Exit 0 = aktuell, Exit 10 = Update verfügbar
|
|
```
|
|
|
|
Beides braucht **keinen Token** und **kein root** — gut für Monitoring-Checks.
|
|
|
|
### Auto-Updater (systemd-Timer)
|
|
|
|
```sh
|
|
sh install.sh --name <node> --token <T> --install-update-timer daily
|
|
sh install.sh --name <node> --token <T> --install-update-timer 30min
|
|
sh install.sh --name <node> --token <T> --install-update-timer weekly
|
|
```
|
|
|
|
Legt `telegraf-installer-update.timer` an (Default `daily` 04:30, ±15 min Streuung).
|
|
Der Lauf ist billig: Es werden nur `VERSION` und der SHA des Installers verglichen.
|
|
Erst bei Abweichung lädt er den Installer und ruft sich mit `--update-only` auf.
|
|
Log: `/var/log/telegraf-installer-update.log`.
|
|
|
|
`--update-only` fasst **nur** `telegraf.d/`-Konfs und Hilfsscripts an: kein
|
|
Paket-Update, `/etc/default/telegraf` (und damit der Token) bleibt unberührt,
|
|
kein Neustart wenn sich nichts geändert hat.
|
|
|
|
Warum Version **und** Hash: Die `VERSION` erkennt neue Auslieferungen, der SHA
|
|
auch Korrekturen ohne Versionssprung (z. B. ein Fix an `journal-tail.sh`).
|
|
Ohne den Hash bliebe eine Node mit fehlerhaftem Script stehen.
|
|
|
|
### Force-Updater
|
|
|
|
```sh
|
|
sh install.sh --force-update --name <node> --token <T>
|
|
```
|
|
|
|
Schreibt Konfs und Scripts **immer** neu, sichert sie vorher nach
|
|
`/var/backups/telegraf-<zeitstempel>/` und startet den Dienst neu. Schlägt der
|
|
Konfig-Test fehl, wird automatisch zurückgerollt. Idempotent — mehrfaches
|
|
Ausführen ist folgenlos. Das Werkzeug nach einem kaputten Update oder wenn
|
|
jemand Dateien von Hand verändert hat.
|
|
|
|
Entfernen: `sh install.sh --remove-update-timer`
|
|
|
|
### Windows
|
|
|
|
```powershell
|
|
.\install.ps1 -Name <node> -Token <T> -Check # Versionsvergleich
|
|
.\install.ps1 -Name <node> -Token <T> -InstallUpdateTask # taeglich
|
|
.\install.ps1 -Name <node> -Token <T> -InstallUpdateTask -UpdateInterval hourly
|
|
.\install.ps1 -Name <node> -Token <T> -ForceUpdate
|
|
.\install.ps1 -RemoveUpdateTask
|
|
```
|
|
|
|
Die Aufgabe `\NetBirdTelegraf\Update` läuft mit denselben Semantiken
|
|
(Version + Hash, nur bei Änderung). Log:
|
|
`%ProgramData%\netbird-telegraf\update.log`.
|
|
|
|
### Marker auf der Node
|
|
|
|
| Datei | Inhalt |
|
|
|---|---|
|
|
| `/etc/telegraf/CONFIG_VERSION` | zuletzt installierte Repo-Version |
|
|
| `/etc/telegraf/INSTALLER_SHA` | SHA256 des Installers zum Installationszeitpunkt |
|
|
| `/etc/telegraf/REPO_RAW` | genutzte Repo-Quelle (GitHub-Mirror, Testserver) |
|
|
|
|
`REPO_RAW` ist per Umgebungsvariable überschreibbar — nützlich für Tests,
|
|
Mirrors oder einen eigenen Fork.
|
|
|
|
### Docker-Nodes (kein journalctl im Image)
|
|
|
|
Läuft Telegraf als **Container** (offizielles `telegraf`-Image), ist der Journal-Weg nicht möglich: das Image ist Debian ohne `systemd` und hat **kein `journalctl`**; `/hostfs` ist zudem read-only. Dafür gibt es `scripts/syslog-tail.sh` — es liest die **Syslog-Dateien des Hosts** unter `/hostfs/var/log/`.
|
|
|
|
**Drei Fallstricke, die alle still scheitern** (kein `E!`, das Panel bleibt einfach leer):
|
|
|
|
1. **`--config-directory` muss im Command stehen.** Der Standard-CMD im Image ist nur `telegraf` und liest ausschließlich `/etc/telegraf/telegraf.conf`. Alles in `telegraf.d/` wird ohne diesen Schalter **ignoriert**. In `docker-compose.yml`:
|
|
```yaml
|
|
command: --config /etc/telegraf/telegraf.conf --config-directory /etc/telegraf/telegraf.d
|
|
```
|
|
2. **Gruppe `adm` ergänzen** (`group_add: ["4"]`). Der Entrypoint des Images setzt Telegraf per `setpriv` auf **uid 999** — unabhängig von `user:` im Compose. `/var/log/syslog` gehört Gruppe `adm` (Modus 640), als uid 999 also nicht lesbar. Ohne `adm` gibt das Script nichts aus.
|
|
3. **State-Verzeichnis muss schreibbar sein** (`SYSLOG_STATE_DIR`). Voreinstellung ist `/tmp/telegraf-syslog`. Zeigt es auf ein nicht schreibbares Verzeichnis (z. B. `/var/lib/...` als uid 999), kann der Offset nie gespeichert werden — das Script landet bei **jedem** Lauf im Erstanlauf-Zweig und liefert dauerhaft nichts. Seit der aktuellen Version warnt es in dem Fall auf stderr.
|
|
|
|
**Output-Filter mitziehen:** `outputs.loki` filtert per `namepass`. Enthält der Block `namepass = ["docker_log"]`, wird das `journal`-Measurement verworfen und die System-Logs kommen nie an — auch wenn der Input läuft. `journal` ergänzen; im Remote-Write-Output gehört es in `namedrop` (Logs haben in Prometheus nichts zu suchen).
|
|
|
|
**Kein Zeitstempel im erzeugten Line Protocol.** Die Syslog-Zeit ist lokal (`+02:00`), `mawk` (Standard im Image) kennt keine Zeitzonen-Offsets — selbst berechnete Werte lagen 2 h in der Zukunft und Loki wies jeden Push ab: `has timestamp too new`. Ohne Zeitstempel stempelt Telegraf beim Einsammeln.
|
|
|
|
## System-Logs (PVE und Nicht-Docker-Hosts)
|
|
|
|
Bis Version dieses Abschnitts lieferten nur **Docker-Container** Logs nach Loki
|
|
(`inputs.docker_log`) — PVE-Knoten und alle Hosts ohne Docker also gar nichts.
|
|
Jetzt werden zusätzlich **journald-Logs** übertragen.
|
|
|
|
**Wie:** `scripts/journal-tail.sh` liest `journalctl -o json` inkrementell und
|
|
gibt Influx Line Protocol aus (`inputs.exec`). Der Cursor steckt in jeder
|
|
Journal-Zeile (`__CURSOR`) und wird in `/var/lib/telegraf-journal/cursor`
|
|
gespeichert — keine Duplikate, kein Verlust bei Neustart oder Rotation.
|
|
|
|
**Warum nicht `inputs.journal`:** Das Plugin existiert in den offiziellen
|
|
Telegraf-Builds **nicht** (Docker-Image und InfluxData-Debian-Paket 1.40
|
|
geprüft; es braucht einen Build mit systemd-Headern).
|
|
|
|
**Warum nicht `/var/log/syslog`:** Auf PVE (Debian ohne rsyslog) existiert die
|
|
Datei nicht. `ls /var/log/` zeigt dort `journal/`, `pve/`, `pveproxy/`,
|
|
`pve-firewall.log`, `ceph/`, `corosync/` — aber kein `syslog`.
|
|
|
|
**Feintuning** in `/etc/default/telegraf`:
|
|
|
|
| Variable | Default | Bedeutung |
|
|
|---|---|---|
|
|
| `JOURNAL_PRIORITY` | `warning` | `warning`, `err`, `info`, `debug` |
|
|
| `JOURNAL_MAX_LINES` | `500` | Obergrenze pro Lauf (Flutschutz) |
|
|
| `JOURNAL_BUDGET` | `15` | Sekunden, die `journalctl` lesen darf |
|
|
| `JOURNAL_SINCE` | — | nur beim **ersten** Lauf, z. B. `-1h` |
|
|
|
|
Standardmäßig werden **Warnungen und schlimmer** übertragen. Für Debugging
|
|
`JOURNAL_PRIORITY=info` setzen und Telegraf neu starten.
|
|
|
|
**Labels in Loki:** `unit` (z. B. `pvedaemon.service`), `ident`, `priority`,
|
|
`jhost` (Journal-Hostname), dazu `host`/`node` von Telegraf. Das `jhost`-Label
|
|
heißt bewusst nicht `host` — dieser Name gehört Telegrafs global_tag, sonst
|
|
filtert das Dashboard nach dem falschen Knoten.
|
|
|
|
## Der Token — zuerst lesen
|
|
|
|
Jeder Aufruf braucht `--token <TOKEN>`. Ohne Token bricht das Script mit
|
|
`FEHLER: Kein Token: --token <Bearer-Token> angeben` ab.
|
|
|
|
Den Token legt man im NetBird-Dashboard an: **`https://x05.idx.wf` → Reverse Proxy →
|
|
Service `imac-prometheus` → Authentication → Header → Preset „Bearer Token"**.
|
|
Für `imac-loki` denselben Wert eintragen (oder einen zweiten, dann aber getrennt halten).
|
|
|
|
Token nie in dieses Repo schreiben — er landet ausschließlich in `/etc/default/telegraf` (Modus 0600) auf der Zielmaschine.
|
|
|
|
## Linux — Debian, Ubuntu, Proxmox VE, RHEL/Rocky/Alma/Fedora, Alpine, sonstige
|
|
|
|
```sh
|
|
curl -fsSL https://gitea.m-m.bio/mm/netbird-telegraf-installer/raw/branch/main/install.sh \
|
|
| sudo sh -s -- --name <node-name> --token <BEARER-TOKEN>
|
|
```
|
|
|
|
| Option | Bedeutung |
|
|
|---|---|
|
|
| `--name <n>` | Node-Name im Dashboard (Default: `hostname -s`) |
|
|
| `--token <t>` | **Pflicht.** Bearer-Token des Reverse-Proxys |
|
|
| `--collector <ip>` | Direktweg innerhalb des NetBird statt Reverse Proxy (z. B. `100.83.134.46`); braucht dann keinen Token-Zwang, aber die Node muss Peer sein |
|
|
| `--role proxmox\|apache\|docker\|none` | Zusatz-Profil; Default `auto` erkennt Proxmox, Docker und Apache selbst |
|
|
| `--apache-log <pfad>` | Access-Log (Default `/var/log/apache2/access.log`) |
|
|
| `--uninstall` | alles entfernen |
|
|
|
|
**Root-Rechte:** Das Script braucht sie (Dienst, `/etc/telegraf`). Wo du **schon root** bist — PVE-Knoten, Hetzner-/Root-Server wie x17, LXC-Container, minimale Debian-Installationen — **kein `sudo`**: dort ist es oft gar nicht installiert und der erste Befehl bricht mit `sudo: command not found` ab. Auf normalen Desktops/Servern mit eigenem Benutzer (Ubuntu-Desktop, ROG): `| sudo sh -s -- …`.
|
|
|
|
**Prüfen statt raten:** `id -u` — kommt `0`, ohne `sudo`. Das Script prüft es selbst und bricht mit klarer Meldung ab, wenn es nicht root ist.
|
|
|
|
Ablauf: Paketquelle von InfluxData (apt/dnf/apk) oder statisches Binary (amd64/arm64/armv7) → `/etc/telegraf/telegraf.conf` + `telegraf.d/` aus diesem Repo → `/etc/default/telegraf` mit NODE_NAME, PROM_URL, LOKI_URL, TELEGRAF_TOKEN → systemd-Dienst `telegraf`, enabled, Konfig-Test vor dem Start.
|
|
|
|
### Direktweg (Node ist NetBird-Peer)
|
|
|
|
```sh
|
|
curl -fsSL …/install.sh | sudo sh -s -- --name <node> --token <TOKEN> --collector 100.83.134.46
|
|
```
|
|
|
|
### Proxmox VE
|
|
|
|
**Kein API-Token nötig.** Der Installer nutzt `pvesh` direkt (Telegraf läuft für diese Rolle
|
|
als root — das Drop-in `10-proxmox-root.conf` setzt das). Damit entfällt die gesamte
|
|
Token-/ACL-Thematik.
|
|
|
|
> Warum nicht `inputs.proxmox`? Das Plugin fragt als Erstes `/nodes/<node>/dns` ab und
|
|
> braucht dort `Sys.Audit`. Schlägt das fehl, liefert es **komplett nichts** — ohne
|
|
> Logmeldung. Mehrere ACL-Versuche (`PVEAuditor` auf `/`, auf `/nodes`, auf `/nodes/<node>`,
|
|
> eigene Rolle mit `Sys.Audit`) blieben auf PVE 8 mit `403` erfolglos.
|
|
|
|
Dann auf **jedem PVE-Knoten** (auf dem Host selbst, nicht in einer VM).
|
|
**Auf PVE (und auf Root-Servern wie x17) gibt es kein `sudo`** — du bist dort bereits root, also ohne `sudo`:
|
|
|
|
```sh
|
|
curl -fsSL https://gitea.m-m.bio/mm/netbird-telegraf-installer/raw/branch/main/install.sh \
|
|
| sh -s -- --name <PVE-KNOTENNAME> --token <BEARER-TOKEN> --role proxmox
|
|
```
|
|
|
|
> Auf Debian/Ubuntu/Normalnutzer dagegen `| sudo sh -s -- …` verwenden. Das Script prüft `id -u` selbst und bricht mit klarer Meldung ab, wenn es nicht root ist.
|
|
|
|
Der Installer erkennt den PVE-Knoten selbst (`pvesh get /nodes`) und legt das systemd-Drop-in
|
|
`10-proxmox-root.conf` an — Telegraf läuft für diese Rolle als **root**, weil `pvesh` root verlangt.
|
|
|
|
Liefert pro Gast: `proxmox_vm_cpu_usage_percent`, `_cpu_cores`, `_mem_bytes`, `_mem_max_bytes`,
|
|
`_mem_usage_percent`, `_swap_bytes`, `_disk_bytes`, `_disk_max_bytes`, `_diskread/_diskwrite_bytes_total`,
|
|
`_net_in/_net_out_bytes_total`, `_uptime_seconds`, `_running` — je mit `vmid`, `name`, `node`, `type`, `status`.
|
|
Plus die normalen Host-Metriken des Knotens.
|
|
|
|
> **Wenn nach der Installation keine VM-Metriken kommen:** `systemctl cat telegraf | grep User` muss
|
|
> `User=root` zeigen. Vorher prüfen: `pvesh get /cluster/resources --output-format json` muss als root
|
|
> Daten liefern. Als Nicht-root gibt `pvesh` nur `ipcc_send_rec[...] failed` aus — ohne Fehler im Log.
|
|
|
|
### Apache
|
|
|
|
Wird automatisch erkannt (`apache2ctl`/`httpd`). Access-Log geht roh nach Loki. Für Request-Metriken `inputs.apache` in `telegraf/apache.conf` einschalten (braucht mod_status).
|
|
|
|
## Windows — PowerShell als Administrator
|
|
|
|
```powershell
|
|
Set-ExecutionPolicy Bypass -Scope Process -Force
|
|
& ([scriptblock]::Create((iwr -useb https://gitea.m-m.bio/mm/netbird-telegraf-installer/raw/branch/main/install.ps1))) -Name ROG -Token <BEARER-TOKEN>
|
|
```
|
|
Installiert nach `C:\Program Files\Telegraf`, Dienst `telegraf`; liefert CPU/RAM/Disk/Net/Dienste + Eventlog (Warnung/Fehler). `-Uninstall` entfernt alles.
|
|
|
|
## GPU-Metriken
|
|
|
|
| Hersteller | Erkennung | Metriken |
|
|
|---|---|---|
|
|
| NVIDIA | `nvidia-smi -L` funktioniert | Auslastung, VRAM, Temperatur, Leistung, Takte, P-State |
|
|
| AMD | `rocm-smi` vorhanden | Auslastung, Temperatur, Leistung, VRAM (via `scripts/gpu-rocm.sh`) |
|
|
| Intel | `/dev/dri/renderD128` | Hinweis im Log — `intel_gpu_top` wird nicht automatisch erfasst |
|
|
|
|
AMD liefert sieben Metriken (Auslastung, VRAM genutzt/gesamt, Temperatur edge/junction/memory, Leistung). NVIDIA entsprechend über `inputs.nvidia_smi`.
|
|
|
|
Im Dashboard: Row **GPU** (Auslastung, Speicher, Temperatur, Leistung). Leere Panels heißen: keine GPU-Node im Mesh.
|
|
|
|
**Beim Aktualisieren des AMD-Scripts** (falls `rocm-smi` seine Spalten ändert) beide Dateien neu holen — Script **und** Conf, und `data_format` muss `prometheus` bleiben:
|
|
|
|
```sh
|
|
sudo curl -fsSL …/scripts/gpu-rocm.sh | sudo tee /etc/telegraf/gpu-rocm.sh >/dev/null
|
|
sudo chmod +x /etc/telegraf/gpu-rocm.sh
|
|
sudo sh -c 'cat > /etc/telegraf/telegraf.d/gpu.conf <<EOF
|
|
[[inputs.exec]]
|
|
interval = "30s"
|
|
timeout = "20s"
|
|
data_format = "prometheus"
|
|
commands = ["/etc/telegraf/gpu-rocm.sh"]
|
|
EOF'
|
|
sudo systemctl restart telegraf
|
|
```
|
|
Im Docker-Betrieb muss der Treiber im Container verfügbar sein (`nvidia-container-toolkit` bzw. `--device /dev/dri`); als systemd-Dienst ist das automatisch der Fall.
|
|
|
|
## Prüfen
|
|
|
|
```sh
|
|
TOKEN=<BEARER-TOKEN>
|
|
curl -s -H "Authorization: Bearer $TOKEN" \
|
|
"https://imac-prometheus.x05.idx.wf/api/v1/query?query=system_uptime{node=\"<node-name>\"}"
|
|
journalctl -u telegraf -f
|
|
```
|
|
Im Grafana-Dashboard „NetBird Observability — Overview“ erscheint die Node automatisch im Node-Filter.
|
|
Grafana selbst: `http://100.83.134.46:3000` (nur im NetBird, Login `admin`).
|
|
|
|
## Docker-Host ohne root
|
|
|
|
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.
|
|
|
|
## Alte Logs archivieren (Historie nachträglich auswertbar machen)
|
|
|
|
`inputs.tail` liest mit `initial_read_offset = "saved-or-end"` nur **Neues** — die
|
|
vorhandene Historie bleibt unausgewertet. Dafür gibt es ein eigenes Skript, das
|
|
dieselben Zeilen parst und als Prometheus-Blöcke ablegt:
|
|
|
|
```sh
|
|
# Auf der Node: erst messen (ändert nichts)
|
|
curl -fsSL <raw>/scripts/x22-log-archive.sh -o /root/archiv.sh
|
|
bash /root/archiv.sh # Bestandsaufnahme
|
|
|
|
# dann archivieren
|
|
bash /root/archiv.sh --backfill # erzeugt apache-archive.openmetrics + tar.gz
|
|
```
|
|
|
|
Das Skript prüft seine eigene Ausgabe **vor** der Übergabe: Zeitraum, Einheit
|
|
(Sekunden) und ein **Zukunfts-Check** — Punkte nach „jetzt" werden gemeldet, weil
|
|
sie später beim Import die Zeitreferenz verschieben würden.
|
|
|
|
Eingespielt wird **nur in die Archiv-Instanz**, nie in die Produktions-TSDB:
|
|
|
|
```sh
|
|
scp /root/apache-archive/apache-archive.openmetrics mm@<imac>:/tmp/
|
|
ssh mm@<imac> 'sudo /usr/local/bin/prom-archive-import.sh --file /tmp/apache-archive.openmetrics'
|
|
```
|
|
|
|
Geparst werden Access- **und** Error-Logs, inklusive rotierter `.log.1`/`.log.N.gz`.
|
|
Was entsteht: `apache_archive_requests_total` (je Domain/Status/Methode/Stunde),
|
|
`_response_bytes_total`, `_unique_clients`, `_errors_total` (je Level),
|
|
`_log_lines_total`. Als Datasource in Grafana einhängen
|
|
(`http://archive-prometheus:9090`) — Live und Archiv sind dann getrennt abfragbar.
|
|
|
|
## 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.
|
|
- Telegraf läuft als Benutzer `telegraf` (Docker-Socket read-only via Gruppe `docker`, Apache-Logs via Gruppe `adm`).
|
|
- **Ausnahme `--role proxmox`:** systemd-Drop-in setzt `User=root`, weil `pvesh` root benötigt. Nur auf PVE-Hosts, wo du ohnehin root bist.
|
|
- Dieses Repo ist öffentlich und enthält keine Secrets.
|