Wie spielen die Akteure zusammen?

Monitoring in diesem Stack basiert auf einem klaren Pull-Prinzip: Prometheus fragt aktiv bei den Datenquellen an – nicht umgekehrt. Jede Komponente hat eine klar definierte Rolle.

┌─────────────────────────────────────────────────────────────────┐
│                        monitoring network                       │
│                                                                 │
│  ┌──────────────┐     scrape      ┌─────────────────────────┐  │
│  │  Prometheus  │◄────────────────│  cAdvisor   :8080       │  │
│  │   :9090      │◄────────────────│  pve-exporter :9221     │  │
│  │              │◄────────────────│  traefik    :8899       │  │
│  │              │◄────────────────│  prometheus :9090       │  │
│  └──────┬───────┘                 └─────────────────────────┘  │
│         │ query (PromQL)                                        │
│  ┌──────▼───────┐                 ┌─────────────────────────┐  │
│  │   Grafana    │                 │        Redis            │  │
│  │   :3000      │                 │  (cAdvisor session)     │  │
│  └──────────────┘                 └─────────────────────────┘  │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

         │ proxy network
    ┌────▼─────┐
    │ Traefik  │ → grafana.example.com (Authentik-geschützt)
    └──────────┘

Außerhalb des monitoring network:
┌─────────────────────────────────┐
│  Proxmox VE  192.168.100.21     │
│  pve-exporter liest PVE API     │
└─────────────────────────────────┘

Prometheus ist die Zentrale. Es scraped alle Datenquellen in regelmäßigen Intervallen, speichert die Zeitreihendaten in seiner eigenen TSDB und beantwortet PromQL-Abfragen von Grafana.

Grafana ist das Visualisierungslayer. Es stellt keine eigenen Metriken bereit und speichert keine Zeitreihendaten – es fragt Prometheus per PromQL ab und rendert Dashboards.

cAdvisor (Container Advisor) läuft auf dem Docker-Host und exportiert Ressourcenmetriken aller laufenden Container: CPU, RAM, Netzwerk, Disk-I/O – pro Container, in Echtzeit. Prometheus scraped cAdvisor alle 5 Sekunden.

pve-exporter übersetzt die Proxmox VE API in Prometheus-Metriken. Er läuft als Container im monitoring-Netzwerk und wird von Prometheus über einen Umweg gescraped – mehr dazu im Abschnitt zur prometheus.yml.

Redis wird von cAdvisor als Session-Store genutzt.


Vorbereitung

mkdir -p /opt/monitoring
cd /opt/monitoring

Drei Dateien werden neben der compose.yml benötigt:

/opt/monitoring/
├── compose.yml
├── prometheus.yml      # Scrape-Konfiguration
└── pve.yml             # Proxmox-Zugangsdaten

docker-compose.yml

Grafana

grafana:
  image: grafana/grafana:latest
  container_name: grafana
  environment:
    - GF_SECURITY_ADMIN_USER=admin
    - GF_SECURITY_ADMIN_PASSWORD=admin
  volumes:
    - grafana-data:/var/lib/grafana
  networks:
    - monitoring
    - proxy

Grafana hängt in zwei Netzwerken: monitoring für die Prometheus-Verbindung und proxy für Traefik. Das Admin-Passwort sollte nicht im Compose-File stehen – besser in einer .env-Datei.

Grafana ist der einzige Container im Stack der nach außen exponiert wird – über Traefik mit Authentik-Middleware. Prometheus, cAdvisor und pve-exporter sind ausschließlich intern erreichbar.

Prometheus

prometheus:
  image: prom/prometheus:latest
  container_name: prometheus
  volumes:
    - ./prometheus.yml:/etc/prometheus/prometheus.yml
    - prometheus-data:/prometheus
  networks:
    - monitoring

Die prometheus.yml wird als Bind-Mount eingebunden – Änderungen an der Scrape-Konfiguration sind ohne Image-Rebuild möglich. Das prometheus-data-Volume persistiert die TSDB. Standardmäßig hält Prometheus Daten 15 Tage vor.

cAdvisor

cadvisor:
  image: gcr.io/cadvisor/cadvisor:latest
  container_name: cadvisor
  cpus: 0.1
  command:
    - '-housekeeping_interval=10s'
    - '-docker_only=true'
    - '-store_container_labels=false'
  volumes:
    - /:/rootfs:ro
    - /var/run:/var/run:rw
    - /sys:/sys:ro
    - /var/lib/docker/:/var/lib/docker:ro
  networks:
    - monitoring

cAdvisor braucht direkten Zugriff auf den Host-Kernel um Container-Metriken zu lesen – daher die umfangreichen Volume-Mounts:

Mount Zweck
/:/rootfs:ro Filesystem-Statistiken
/var/run:/var/run:rw Docker-Socket für Container-Metadaten
/sys:/sys:ro Kernel-Subsysteme (cgroups, Netzwerk)
/var/lib/docker:/var/lib/docker:ro Docker-interne Metriken

-docker_only=true schränkt cAdvisor auf Docker-Container ein – ohne dieses Flag werden auch systemd-Services und andere cgroup-Prozesse erfasst, was Rauschen erzeugt. -store_container_labels=false verhindert dass alle Container-Labels als Prometheus-Labels landen – reduziert die Kardinalität der Zeitreihen erheblich.

cpus: 0.1 begrenzt cAdvisor auf 10% eines CPU-Kerns – cAdvisor kann ohne Limit überraschend ressourcenhungrig werden.

pve-exporter

pve-exporter:
  image: prompve/prometheus-pve-exporter:latest
  container_name: pve-exporter
  command: "--config.file=/etc/prometheus/pve.yml"
  volumes:
    - ./pve.yml:/etc/prometheus/pve.yml:ro
  networks:
    - monitoring

Der pve-exporter übersetzt Proxmox-API-Daten in Prometheus-Metriken. Er liest seine Zugangsdaten aus pve.yml – API-Token statt Passwort ist die empfohlene Authentifizierungsmethode.


prometheus.yml – Scrape-Konfiguration

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'traefik'
    static_configs:
      - targets: ['traefik:8899']

  - job_name: cadvisor
    scrape_interval: 5s
    static_configs:
      - targets:
        - cadvisor:8080

  - job_name: 'pve'
    static_configs:
      - targets:
        - 192.168.100.21
    metrics_path: /pve
    params:
      module: [default]
      cluster: ['1']
      node: ['1']
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: pve-exporter:9221

Scrape-Intervalle

cadvisor wird mit scrape_interval: 5s häufiger gescraped als der globale Standard von 15 Sekunden – Container-Metriken ändern sich schnell und 15 Sekunden wären für CPU-Spikes zu grob. Prometheus, Traefik und pve-exporter reichen mit 15 Sekunden aus.

Das pve-Relabeling

Der Proxmox-Scrape-Job ist das komplexeste Stück der Konfiguration und verdient eine Erklärung:

Prometheus will scrapen:  192.168.100.21  (der Proxmox-Host)
Aber der Exporter läuft:  pve-exporter:9221 (im monitoring-Netzwerk)

Der pve-exporter funktioniert als Proxy: Prometheus schickt eine Anfrage an pve-exporter:9221/pve?target=192.168.100.21, der Exporter holt die Daten von der Proxmox-API und gibt sie als Prometheus-Metriken zurück.

Das Relabeling bewerkstelligt genau diese Umleitung:

1. source_labels: [__address__]      → nimmt "192.168.100.21"
   target_label: __param_target      → setzt ?target=192.168.100.21

2. source_labels: [__param_target]   → nimmt "192.168.100.21"
   target_label: instance            → setzt instance-Label für Grafana

3. target_label: __address__         → überschreibt Zieladresse
   replacement: pve-exporter:9221    → Prometheus fragt jetzt den Exporter

Das Muster ist Standard für alle Prometheus-Exporter die als HTTP-Proxy fungieren (Blackbox Exporter, SNMP Exporter, PVE Exporter).

Traefik-Metrics

Traefik exponiert Prometheus-Metriken auf dem dedizierten metrics-EntryPoint (Port 8899). Da Traefik und Prometheus im selben monitoring-Netzwerk hängen, ist traefik:8899 direkt auflösbar – kein Port nach außen nötig.


pve.yml – Proxmox-Zugangsdaten

default:
  verify_ssl: false
  user: 'monitoring@pve'
  token_name: 'prometheus'
  token_value: '<token>'

verify_ssl: false ist nötig wenn Proxmox ein selbstsigniertes Zertifikat verwendet – üblich in Heimlabor-Umgebungen. In produktiven Umgebungen sollte ein gültiges Zertifikat und verify_ssl: true verwendet werden.

API-Token in Proxmox erstellen

Im Proxmox-Webinterface: Datacenter → Permissions → API Tokens → Add

Benötigte Berechtigungen für den monitoring-User:

Pfad Rolle Propagate
/ PVEAuditor

PVEAuditor erlaubt Lesezugriff auf alle Nodes, VMs und Container – ausreichend für Monitoring, keine Schreibrechte.


Start

docker compose up -d

# Prometheus Targets prüfen
# http://server-ip:9090/targets
# Alle Targets sollten "UP" sein

docker compose logs -f prometheus
docker compose logs -f pve-exporter

Grafana ist nach dem Start unter http://server-ip:3000 oder via Traefik erreichbar.

Prometheus als Datenquelle einrichten

In Grafana: Connections → Data Sources → Add → Prometheus

URL: http://prometheus:9090

Da Grafana und Prometheus im selben monitoring-Netzwerk sind, funktioniert der Container-Name direkt.

Empfohlene Dashboards

Fertige Dashboards lassen sich in Grafana über Dashboards → Import per ID laden:

Dashboard ID Quelle
Node Exporter Full 1860 grafana.com
cAdvisor Docker 14282 grafana.com
Proxmox VE 10347 grafana.com
Traefik 2/3 Official Dashboard 17346 grafana.com

Updates & Wartung

docker compose pull
docker compose up -d

# Prometheus Retention anpassen (Standard: 15 Tage)
# In compose.yml unter prometheus command:
command:
  - '--config.file=/etc/prometheus/prometheus.yml'
  - '--storage.tsdb.retention.time=30d'
  - '--storage.tsdb.retention.size=10GB'

Fazit

Der Stack folgt dem Unix-Prinzip: jedes Tool macht genau eine Sache. Prometheus sammelt und speichert, cAdvisor exportiert Container-Metriken, pve-exporter überbrückt die Proxmox-API, Grafana visualisiert. Die Kopplung ist lose – jede Komponente ist austauschbar, jede Konfiguration liegt als Datei vor. Das Relabeling-Pattern im pve-Job ist dabei das einzige nicht-offensichtliche Konzept – wer es einmal verstanden hat, kann jeden Proxy-Exporter im Prometheus-Ökosystem damit ansprechen.