From 72756babae160b06ec3e42b5c31c2b2ce0170610 Mon Sep 17 00:00:00 2001 From: mm Date: Sun, 13 Sep 2026 21:17:48 +0200 Subject: [PATCH] feat(proxmox): pvesh-basierter exec-Input statt inputs.proxmox (kein Token/ACL noetig) --- install.sh | 14 ++++++++-- scripts/proxmox-ve.sh | 63 +++++++++++++++++++++++++++++++++++++++++++ telegraf/proxmox.conf | 15 +++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) create mode 100755 scripts/proxmox-ve.sh diff --git a/install.sh b/install.sh index f0aec85..37c039f 100755 --- a/install.sh +++ b/install.sh @@ -250,8 +250,18 @@ fetch_conf telegraf/base.conf /etc/telegraf/telegraf.conf rm -f /etc/telegraf/telegraf.d/*.conf [ "$HAS_DOCKER" -eq 1 ] && { fetch telegraf/docker.conf /etc/telegraf/telegraf.d/docker.conf; usermod -aG docker telegraf 2>/dev/null || true; } case "$ROLE" in - proxmox) [ -n "$PVE_TOKEN" ] || log "HINWEIS: --pve-token fehlt; VM/CT-Metriken bleiben aus. Token anlegen: pveum user token add telegraf@pve monitoring -privsep 1 && pveum acl modify / -token 'telegraf@pve!monitoring' -role PVEAuditor" - fetch_conf telegraf/proxmox.conf /etc/telegraf/telegraf.d/proxmox.conf ;; + proxmox) : # pvesh-Weg braucht keinen Token (siehe unten) + fetch scripts/proxmox-ve.sh /etc/telegraf/proxmox-ve.sh + chmod 0755 /etc/telegraf/proxmox-ve.sh + # pvesh-Weg: braucht keinen Token und keine ACL (laeuft als root) + cat > /etc/telegraf/telegraf.d/proxmox.conf <<'EOF' +[[inputs.exec]] + interval = "30s" + timeout = "25s" + data_format = "prometheus" + commands = ["/etc/telegraf/proxmox-ve.sh"] +EOF + log "Proxmox: pvesh-Input aktiv (VM/CT-Metriken, kein API-Token noetig)." ;; apache) fetch_conf telegraf/apache.conf /etc/telegraf/telegraf.d/apache.conf; usermod -aG adm telegraf 2>/dev/null || true ;; docker|none) ;; *) die "Unbekannte Rolle: $ROLE" ;; diff --git a/scripts/proxmox-ve.sh b/scripts/proxmox-ve.sh new file mode 100755 index 0000000..c66e2dc --- /dev/null +++ b/scripts/proxmox-ve.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# proxmox-ve.sh — VM- und Container-Metriken direkt vom PVE-Host. +# +# Läuft als root auf dem PVE-Knoten und nutzt `pvesh` (lokale API mit vollen +# Rechten). Damit entfällt der API-Token komplett — kein Sys.Audit, keine ACL. +# +# Ausgabe im Prometheus-Format (data_format = "prometheus" in der Telegraf-Conf): +# proxmox_vm_cpu_usage{vmid="1001",name="tunnel",type="qemu",status="running"} 0.42 +# +# Aufruf durch Telegraf (inputs.exec) oder manuell zum Testen. + +set -eu + +command -v pvesh >/dev/null 2>&1 || { echo "# pvesh nicht gefunden — kein PVE-Host" >&2; exit 0; } + +TMP="$(mktemp)"; trap 'rm -f "$TMP"' EXIT +pvesh get /cluster/resources --output-format json > "$TMP" 2>/dev/null || true +[ -s "$TMP" ] || exit 0 + +python3 - "$TMP" <<'PY' +import json, sys, re + +def esc(s): + return str(s).replace('\\', '\\\\').replace('"', '\\"').replace('\n', ' ') + +try: + data = json.load(open(sys.argv[1])) +except Exception as e: + print(f"# JSON-Fehler: {e}", file=sys.stderr); sys.exit(0) + +rows = data.get("data", data) if isinstance(data, dict) else data +if not isinstance(rows, list): + sys.exit(0) + +def emit(name, labels, value): + if value is None: return + lab = ",".join(f'{k}="{esc(v)}"' for k, v in labels.items() if v is not None) + print(f"{name}{{{lab}}} {value}") + +for r in rows: + typ = r.get("type") + if typ not in ("qemu", "lxc"): # node/storage überspringen + continue + if r.get("template"): # Templates nicht als Gast zählen + continue + if str(r.get("vmid", "")) == "": # nur Gäste mit vmid + continue + L = {"vmid": r.get("vmid"), "name": r.get("name"), "node": r.get("node"), + "type": typ, "status": r.get("status")} + # cpu ist ein Anteil 0..1 der zugewiesenen Kerne + cpu = r.get("cpu") + if cpu is not None: + emit("proxmox_vm_cpu_usage", L, round(float(cpu) * 100, 2)) + emit("proxmox_vm_cpu_cores", L, r.get("maxcpu")) + emit("proxmox_vm_mem_bytes", L, r.get("mem")) + emit("proxmox_vm_mem_max_bytes", L, r.get("maxmem")) + emit("proxmox_vm_disk_bytes", L, r.get("disk")) + emit("proxmox_vm_disk_max_bytes", L, r.get("maxdisk")) + emit("proxmox_vm_net_in_bytes", L, r.get("netin")) + emit("proxmox_vm_net_out_bytes", L, r.get("netout")) + emit("proxmox_vm_uptime_seconds", L, r.get("uptime")) + emit("proxmox_vm_running", L, 1 if r.get("status") == "running" else 0) +PY diff --git a/telegraf/proxmox.conf b/telegraf/proxmox.conf index 7983d16..1c95fdc 100644 --- a/telegraf/proxmox.conf +++ b/telegraf/proxmox.conf @@ -17,3 +17,18 @@ response_timeout = "20s" # vmid und status als Tags: sonst sind VM-Metriken nicht pro Gast zuordenbar additional_vmstats_tags = ["vmid", "status"] + +# ============================================================ +# EMPFOHLEN: Metriken direkt per pvesh (kein Token, keine ACL) +# Läuft als root auf dem PVE-Knoten. Der Installer aktiviert das automatisch +# mit --role proxmox, wenn pvesh vorhanden ist. +# +# Warum nicht inputs.proxmox? Das Plugin fragt zuerst /nodes//dns ab und +# braucht dort Sys.Audit. Schlägt das fehl, liefert es KOMPLETT nichts — +# ohne Logmeldung. Der pvesh-Weg umgeht die gesamte Rechte-Thematik. +# ============================================================ +[[inputs.exec]] + interval = "30s" + timeout = "25s" + data_format = "prometheus" + commands = ["/etc/telegraf/proxmox-ve.sh"]