monitoring: Game-Host-Anbindung nach der Gegen-Uebergabe fertigstellen

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.
This commit is contained in:
Thore Cimbal
2026-08-20 12:00:00 +00:00
parent ba59518ef0
commit a07c6eda09
3 changed files with 174 additions and 23 deletions
+11 -8
View File
@@ -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.
@@ -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", "(.*)")
+111 -15
View File
@@ -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"