From a07c6eda091e71540389ee65132ae1ac67f18d23 Mon Sep 17 00:00:00 2001 From: Thore Cimbal Date: Thu, 20 Aug 2026 12:00:00 +0000 Subject: [PATCH] monitoring: Game-Host-Anbindung nach der Gegen-Uebergabe fertigstellen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Die Host-Seite ist deployt und verifiziert; der Betreiber hat drei Abweichungen zu ba59518 gemeldet, alle uebernommen: 1. pterodactyl_exporter zeigt auf 9810 statt 9531. Der alte Exporter (loens2) hat NIE funktioniert - er rief die Client-API mit einem Application-Key ueber http auf und lieferte null pterodactyl_*-Metriken. Ersetzt durch einen, der die Panel-MariaDB read-only liest und keinen API-Key braucht. 2. metric_relabel_configs sind hinzugekommen. Sie lebten bisher im lokalen Prometheus des Game-Hosts und gehoeren immer dem SCRAPENDEN Prometheus - mit dessen Rueckbau also hierher. Ohne sie waeren Gameserver nur unter ihrer UUID sichtbar und je Serie rund 20 container_label_* uebrig geblieben; erwartete Serienzahl faellt von 3615 auf ~1700. 3. instance = gameserver statt pterodactyl, damit Metrik und Log denselben Schluessel tragen (promtail setzt host=gameserver). Kostet keine Historie - die Targets sind am 2026-08-20 zum ersten Mal ueberhaupt up gegangen. Neu: gameserver-rules.yml nimmt den Join Container-UUID -> Klarname vorweg. cAdvisor kennt Gameserver nur unter ihrer UUID, und Relabeling kann keine zweite Metrik nachschlagen. Mit promtool gegen die hier tatsaechlich laufende Version 3.3.1 geprueft (die Uebergabe nutzte 3.0.0): Konfiguration gueltig, 2 Regeldateien, 5 Regeln. ⚠️ Die Uebergabe nennt --force-recreate wegen der Inode-Falle (#0083). Fuer Prometheus gilt das hier NICHT mehr: Das Verzeichnis wird gemountet (./prometheus:/etc/prometheus), genau um diese Falle zu beseitigen. Ein restart bzw. SIGHUP genuegt. --- monitoring/README.md | 19 ++-- monitoring/prometheus/gameserver-rules.yml | 52 +++++++++ monitoring/prometheus/prometheus.yml | 126 ++++++++++++++++++--- 3 files changed, 174 insertions(+), 23 deletions(-) create mode 100644 monitoring/prometheus/gameserver-rules.yml diff --git a/monitoring/README.md b/monitoring/README.md index 5b7afed..e37a711 100644 --- a/monitoring/README.md +++ b/monitoring/README.md @@ -72,8 +72,11 @@ Dashboard-JSONs innerhalb eines bestehenden Providers werden laufend nachgezogen Metriken (`flux`, `kube_state_metrics`, `synapse`). - **Log-Push eingehend** auf `:3100` (Loki) von externen Alloys. - **Scrape ausgehend**: k3s-Host (`10.0.0.2:9100`), Game-Host privat ueber den - vSwitch (`10.0.0.4:9100`, `:8081` cadvisor, `:9531` pterodactyl_exporter). + vSwitch (`10.0.0.4:9100`, `:8081` cadvisor, `:9810` gameserver-exporter). cadvisor liegt dort auf 8081, weil Host-Port 8080 von coolify-proxy belegt ist. + Der Exporter auf `:9810` loest den alten auf `:9531` ab -- jener rief die + Client-API mit einem Application-Key ueber http auf und lieferte deshalb nie + eine einzige `pterodactyl_*`-Metrik. - `cadvisor` und `traefik` werden gescraped, laufen aber in **anderen** Stacks (cadvisor: Portainer-Stack `thread-net-git`; beide haengen im externen `traefik`-Netz). @@ -141,13 +144,13 @@ selbst nicht melden koennen. - `9090`, `3100`, `9100` sind auf der oeffentlichen IP ohne Auth erreichbar (Docker umgeht ufw). Per **Hetzner Cloud Firewall** auf die IPs der bekannten Absender einschraenken. -- Game-Host: Die Targets zeigen seit 2026-08-20 auf die private Adresse - `10.0.0.4` (management #0002). **Voraussetzung auf dem Host**: Die - Exporter-Container veroeffentlichen ihre Ports bisher gar nicht -- `docker ps` - zeigt `9100/tcp` ohne `0.0.0.0`-Mapping, sie sind nur im Docker-Netz erreichbar. - Solange das so ist, bleiben die Targets down; die Adresse ist dann nur eine - andere. Veroeffentlichen auf `10.0.0.4`, **nicht** auf `0.0.0.0` -- sonst stehen - sie wieder im Internet. +- Game-Host: **erledigt**. Host-Seite am 2026-08-20 deployt und verifiziert, die + Ports liegen auf `10.0.0.4` (nicht `0.0.0.0` -- das umginge ufw). Der lokale + Prometheus/Grafana/Loki-Stack des Game-Hosts ist zurueckgebaut; er liefert nur + noch Sammler, promtail schickt nach `10.0.0.3:3100`. + Das Label-Konzept des Game-Hosts lebte in `metric_relabel_configs` und ist mit + dem Rueckbau hierher gewandert -- ohne es blieben Container nur unter ihrer UUID + sichtbar und je Serie rund 20 `container_label_*` uebrig. - Loki `table_manager` ist deprecated; Retention-Enforcement laeuft aktuell nicht ueber den Compactor -- bei Gelegenheit auf Compactor-Retention umstellen. diff --git a/monitoring/prometheus/gameserver-rules.yml b/monitoring/prometheus/gameserver-rules.yml new file mode 100644 index 0000000..e826ff6 --- /dev/null +++ b/monitoring/prometheus/gameserver-rules.yml @@ -0,0 +1,52 @@ +# Recording Rules fuer den Game-Host (management #0002). +# +# Materialisiert die Verknuepfung Container-UUID -> Klarname. cAdvisor kennt +# Gameserver nur unter ihrer UUID, weil Wings die Container so benennt und kein +# Namens-Label setzt. Relabeling kann das nicht aufloesen - es kann keine zweite +# Metrik nachschlagen. Diese Regeln schreiben deshalb alle 30 s Serien fort, die +# den Klarnamen bereits mitbringen, damit ihn nicht jedes Panel neu joinen muss. +# +# label_replace setzt zusaetzlich "display" auf den Klarnamen. Damit bedeutet +# display in JEDER Quelle dasselbe - in Loki, in den cAdvisor-Serien und hier: +# der Name, den Menschen lesen sollen. +# +# Uebernommen aus der Uebergabe des Game-Host-Betreibers vom 2026-08-20; dort +# gegen Prometheus 3.0.0 mit `promtool check rules` geprueft. +groups: + - name: gameserver + interval: 30s + rules: + - record: gameserver:cpu_cores + expr: | + label_replace( + sum by (uuid) (rate(container_cpu_usage_seconds_total{uuid!=""}[2m])) + * on (uuid) group_left(server_name, game) pterodactyl_server_info, + "display", "$1", "server_name", "(.*)") + + - record: gameserver:memory_working_set_bytes + expr: | + label_replace( + sum by (uuid) (container_memory_working_set_bytes{uuid!=""}) + * on (uuid) group_left(server_name, game) pterodactyl_server_info, + "display", "$1", "server_name", "(.*)") + + - record: gameserver:memory_limit_bytes + expr: | + label_replace( + max by (uuid) (container_spec_memory_limit_bytes{uuid!=""} > 0) + * on (uuid) group_left(server_name, game) pterodactyl_server_info, + "display", "$1", "server_name", "(.*)") + + - record: gameserver:network_receive_bytes_per_second + expr: | + label_replace( + sum by (uuid) (rate(container_network_receive_bytes_total{uuid!=""}[2m])) + * on (uuid) group_left(server_name, game) pterodactyl_server_info, + "display", "$1", "server_name", "(.*)") + + - record: gameserver:network_transmit_bytes_per_second + expr: | + label_replace( + sum by (uuid) (rate(container_network_transmit_bytes_total{uuid!=""}[2m])) + * on (uuid) group_left(server_name, game) pterodactyl_server_info, + "display", "$1", "server_name", "(.*)") diff --git a/monitoring/prometheus/prometheus.yml b/monitoring/prometheus/prometheus.yml index 92f572e..79d90f0 100644 --- a/monitoring/prometheus/prometheus.yml +++ b/monitoring/prometheus/prometheus.yml @@ -3,6 +3,8 @@ global: rule_files: - /etc/prometheus/alerts.yml + # Join Container-UUID -> Klarname, einmal vorweggenommen (#0002). + - /etc/prometheus/gameserver-rules.yml alerting: alertmanagers: @@ -46,36 +48,130 @@ scrape_configs: labels: instance: "k3s-host" - # Game-Host: privat ueber den vSwitch statt ueber die oeffentliche IP (management - # #0002). Bis 2026-08-20 standen hier 157.90.155.206:9100 und :8080 - beide Ports - # waren von aussen gefiltert, die Targets seit dem ersten Scrape dauerhaft down. + # ========================================================================== + # Game-Host, privat ueber den vSwitch (management #0002). # - # ⚠️ Voraussetzung auf dem Game-Host: Die Exporter-Container veroeffentlichen ihre - # Ports gar nicht (docker ps zeigt "9100/tcp" ohne 0.0.0.0-Mapping) - sie sind nur - # im Docker-Netz erreichbar. Sie muessen auf 10.0.0.4 veroeffentlicht werden, nicht - # auf 0.0.0.0: Letzteres oeffnete sie wieder oeffentlich, was dieses Issue vermeidet. + # Bis 2026-08-20 zeigten die Targets auf 157.90.155.206 und waren seit dem + # ersten Scrape nie up. Ursache war nicht die Firewall, sondern: Die + # Exporter-Container veroeffentlichten ihre Ports gar nicht. # - # cadvisor liegt bewusst auf Host-Port 8081, nicht 8080: Dort haengt bereits - # coolify-proxy (traefik) auf 0.0.0.0:8080, ein Bind auf 10.0.0.4:8080 kollidierte. + # Host-Seite deployt und verifiziert am 2026-08-20 (Uebergabe des Game-Host- + # Betreibers). Ports auf 10.0.0.4, NICHT auf 0.0.0.0 - letzteres umginge ufw. + # cadvisor liegt host-seitig auf 8081, weil coolify-proxy 0.0.0.0:8080 haelt. + # + # metric_relabel_configs gehoeren immer dem SCRAPENDEN Prometheus. Der + # Game-Host hatte sein Label-Konzept lokal; mit dem Rueckbau seines eigenen + # Prometheus wandert es hierher, sonst faellt es ersatzlos weg. + # + # instance = "gameserver" statt "pterodactyl": Damit tragen Metrik und Log + # denselben Schluessel - promtail setzt host="gameserver". Kostet keine + # Historie, die Targets sind am 2026-08-20 zum ersten Mal ueberhaupt up + # gegangen. + # ========================================================================== + - job_name: "pterodactyl_host_node" static_configs: - targets: ["10.0.0.4:9100"] labels: - instance: "pterodactyl" + host: gameserver + relabel_configs: + - target_label: instance + replacement: gameserver + metric_relabel_configs: + # node-exporter meldet als nodename die UTS-Kennung SEINES Containers. + # Betrifft nur node_uname_info und repariert $nodename in "Node Exporter + # Full". Der Host setzt zusaetzlich hostname: gameserver - beides zusammen + # ist widerspruchsfrei. + - source_labels: [nodename] + regex: '.+' + target_label: nodename + replacement: gameserver - job_name: "gameserver_cadvisor" static_configs: - targets: ["10.0.0.4:8081"] labels: - instance: "pterodactyl" + host: gameserver + relabel_configs: + - target_label: instance + replacement: gameserver + metric_relabel_configs: + # 1) Gameserver-Container heissen nur nach ihrer UUID. In ein eigenes + # Label kopieren, damit der Join auf pterodactyl_server_info moeglich + # wird - siehe gameserver-rules.yml. + - source_labels: [name] + regex: '([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})' + target_label: uuid + replacement: '$1' - # Pterodactyl-eigene Metriken (Server, Spieler, Auslastung je Instanz). Laeuft auf - # dem Game-Host schon seit drei Monaten, war aber nie angebunden. + # 2) "display" = der Name, den Menschen lesen sollen. Zwei Stufen: roher + # Container-Name, dann ohne die 24-stellige Coolify-Kennung. + # "homepage-pqr9de7xmm8s5cpm2yss69s3" -> "homepage" + - source_labels: [name] + regex: '(.+)' + target_label: display + replacement: '$1' + - source_labels: [name] + regex: '(.+)-[a-z0-9]{24}' + target_label: display + replacement: '$1' + + # 3) Wings setzt an Gameserver-Containern gar keine Docker-Labels - ohne + # diese zwei Regeln blieben sie als einzige ohne app/stack. + - source_labels: [name] + regex: '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' + target_label: app + replacement: 'gameserver' + - source_labels: [name] + regex: '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' + target_label: stack + replacement: 'pterodactyl' + + # 4) Sprechende Kurzlabels. Die Coolify-Regel steht jeweils HINTER der + # Compose-Regel und ueberschreibt sie: com.docker.compose.project + # liefert die Kennung, coolify.resourceName den sprechenden Namen. + - source_labels: [container_label_com_docker_compose_service] + regex: '(.+)' + target_label: app + replacement: '$1' + - source_labels: [container_label_coolify_serviceName] + regex: '(.+)' + target_label: app + replacement: '$1' + - source_labels: [container_label_com_docker_compose_project] + regex: '(.+)' + target_label: stack + replacement: '$1' + - source_labels: [container_label_coolify_resourceName] + regex: '(.+)' + target_label: stack + replacement: '$1' + + # 5) Rund 20 container_label_* je Serie (Image-Hashes, Traefik-Router, + # Pfade) fliegen raus. + - regex: 'container_label_.*' + action: labeldrop + + # 6) container_*-Serien ohne name sind systemd-cgroup-Slices, die + # node-exporter ohnehin abdeckt. machine_*-Metriken bleiben erhalten, + # deshalb muss __name__ hier mitgreifen. + - source_labels: [__name__, name] + regex: 'container_.+;' + action: drop + + # Port 9810, NICHT 9531: Der bisherige Exporter (loens2) auf 9531 hat nie + # funktioniert - er rief die Client-API mit einem Application-Key auf und ueber + # http statt https und lieferte deshalb null pterodactyl_*-Metriken. Ersetzt + # durch einen Exporter, der die Panel-MariaDB read-only liest und gar keinen + # API-Key braucht. - job_name: "pterodactyl_exporter" static_configs: - - targets: ["10.0.0.4:9531"] + - targets: ["10.0.0.4:9810"] labels: - instance: "pterodactyl" + host: gameserver + relabel_configs: + - target_label: instance + replacement: gameserver # CVE-Exporter (gitops#47) - job_name: "cve_exporter"