Hier zeige ich euch, wie ihr in ein paar Minuten ein cooles Dashboard bekommt, welches euch diverse Sachen über euren Server anzeigt. Traefik dient uns hier als Reverse Proxy und stellt später den Dienst verschlüsselt per TLS bereit.
Datum | Änderungen |
---|---|
14.04.2020 | Erstellung dieser Anleitung. |
27.04.2020 | Traefik “secHeaders” hinzugefügt. Dashboard erweitert. |
03.01.2022 | Bilder erneuert. |
30.03.2022 | cadvisor Image angepasst. Danke an @Jonas @Jürgen |
15.12.2022 | Docker Compose v2, Traefik Labels angepasst, Kapitel 0 hinzugefügt |
29.05.2023 | Anpassung an neue Traefik Anleitung |
So kann später dann euer Dashboard aussehen:
Dazu werden wir gleich folgende Tools installieren
- Prometheus
- node-exporter
- cadvisor
- grafana
0. Grundvoraussetzung
- Docker & Docker Compose v2 (Debian / Ubuntu)
- TRAEFIK V2 + 3 – REVERSE-PROXY MIT CROWDSEC IM STACK EINRICHTEN
1. Ordner anlegen
Zuerst legen wir uns passende Ordner-Strukturen an.
mkdir -p /opt/containers/grafana/{grafana,prometheus}
Nun ändern wir noch die Berechtigungen.
chown 1000:1000 /opt/containers/grafana/grafana
2. Docker Compose anlegen
Hier legen wir die Docker Compose an.
nano /opt/containers/grafana/docker-compose.yml
Inhalt:
--- version: '3' services: mon_prometheus: image: prom/prometheus:latest container_name: mon_prometheus restart: unless-stopped volumes: - $PWD/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml depends_on: - mon_node-exporter - mon_cadvisor networks: - default mon_node-exporter: image: prom/node-exporter:latest container_name: mon_node-exporter restart: unless-stopped volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--path.rootfs=/rootfs' - '--collector.filesystem.ignored-mount-points="^(/rootfs|/host|)/(sys|proc|dev|host|etc)($$|/)"' - '--collector.filesystem.ignored-fs-types="^(sys|proc|auto|cgroup|devpts|ns|au|fuse\.lxc|mqueue)(fs|)$$"' networks: - default mon_cadvisor: image: gcr.io/cadvisor/cadvisor container_name: mon_cadvisor restart: unless-stopped volumes: - /:/rootfs:ro - /var/run:/var/run:rw - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro networks: - default mon_grafana: image: grafana/grafana:latest container_name: mon_grafana restart: unless-stopped volumes: - /opt/containers/grafana/grafana:/var/lib/grafana user: "1000" depends_on: - mon_prometheus labels: - "traefik.enable=true" - "traefik.http.routers.grafana.entrypoints=websecure" - "traefik.http.routers.grafana.rule=(Host(`grafana.euredomain.de`))" - "traefik.http.routers.grafana.tls=true" - "traefik.http.routers.grafana.tls.certresolver=http_resolver" - "traefik.http.routers.grafana.service=grafana" - "traefik.http.services.grafana.loadbalancer.server.port=3000" - "traefik.docker.network=proxy" - "traefik.http.routers.grafana.middlewares=default@file" networks: - proxy - default networks: proxy: external: true
Notwendige Anpassungen:
- eure URL eingeben bei Traefik (grafana.euredomain.de)
3. prometheus.yml anlegen
Nun legen wir noch eine Konfigurationsdatei für Prometheus an.
nano /opt/containers/grafana/prometheus/prometheus.yml
global: scrape_interval: 15s evaluation_interval: 15s rule_files: scrape_configs: - job_name: 'node-exporter' static_configs: - targets: ['mon_node-exporter:9100'] - job_name: 'cadvisor' static_configs: - targets: ['mon_cadvisor:8080']
4. Grafana starten
Wie gewohnt starten wir nun Grafana mittels folgendem Befehl:
docker compose -f /opt/containers/grafana/docker-compose.yml up -d
5. Grafana Konfigurieren
5.1 Einloggen
Nun geht ihr auf “grafana.euredomain.de” und solltet folgendes sehen:
Die Zugangsdaten lauten:
- Name: admin
- Passwort: admin
Wenn ihr euch einloggt, werdet ihr aufgefordert das Kennwort zu ändern.
Nun solltet ihr folgendes sehen.
5.2 Mit Prometheus Datenbank verbinden
Nun klickt ihr auf “Add data source”.
Hier wählt ihr “Prometheus” aus.
Hier gebt ihr nun unter “URL” folgendes ein:
http://mon_prometheus:9090
Nun scrollt ihr nach unten und klickt auf “Save & Test”. Wenn alles ok ist, dann sollte es bei euch so aussehen.
5.3 Dashboard hinzufügen
Ihr könnt euch nun ein Dashboard selbst zusammenbauen oder eins kostenlos von der Grafana Community beziehen.
Wenn ihr mein Dashboard haben wollt, so müsst ihr folgendes tun.
Klickt auf das “+” links oben und wählt “Import” aus.
Hier kopiert ihr nun folgenden Code in das Feld. Ihr könnt den Code komplett markieren und dann kopieren.
{ "annotations": { "list": [ { "builtIn": 1, "datasource": "-- Grafana --", "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "description": "", "editable": true, "gnetId": 893, "graphTooltip": 1, "id": 1, "iteration": 1588003866954, "links": [], "panels": [ { "cacheTimeout": null, "colorBackground": false, "colorValue": false, "colors": [ "rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)" ], "datasource": "Prometheus", "editable": true, "error": false, "format": "none", "gauge": { "maxValue": 100, "minValue": 0, "show": false, "thresholdLabels": false, "thresholdMarkers": true }, "gridPos": { "h": 4, "w": 4, "x": 0, "y": 0 }, "id": 31, "interval": null, "links": [], "mappingType": 1, "mappingTypes": [ { "name": "value to text", "value": 1 }, { "name": "range to text", "value": 2 } ], "maxDataPoints": 100, "nullPointMode": "connected", "nullText": null, "postfix": "", "postfixFontSize": "50%", "prefix": "", "prefixFontSize": "50%", "rangeMaps": [ { "from": "null", "text": "N/A", "to": "null" } ], "sparkline": { "fillColor": "rgba(31, 118, 189, 0.18)", "full": false, "lineColor": "rgb(31, 120, 193)", "show": false }, "tableColumn": "", "targets": [ { "expr": "count(rate(container_last_seen{name=~\".+\"}[$interval]))", "format": "time_series", "intervalFactor": 2, "refId": "A", "step": 1800 } ], "thresholds": "", "title": "Containers", "type": "singlestat", "valueFontSize": "120%", "valueMaps": [ { "op": "=", "text": "N/A", "value": "null" } ], "valueName": "current" }, { "cacheTimeout": null, "datasource": null, "gridPos": { "h": 7, "w": 9, "x": 4, "y": 0 }, "id": 35, "links": [], "options": { "fieldOptions": { "calcs": [ "last" ], "defaults": { "mappings": [], "max": 100, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "title": "" }, "overrides": [], "values": false }, "orientation": "auto", "showThresholdLabels": false, "showThresholdMarkers": false }, "pluginVersion": "6.7.2", "targets": [ { "expr": "100 - (avg by (cpu) (irate(node_cpu_seconds_total{mode=\"idle\"}[1m])) *100)", "hide": false, "interval": "", "legendFormat": "", "refId": "A" }, { "expr": "(irate(node_cpu_seconds_total{mode=\"idle\"}[1m])) ", "hide": true, "interval": "", "legendFormat": "", "refId": "B" } ], "timeFrom": null, "timeShift": null, "title": "CPU Auslastung", "type": "gauge" }, { "cacheTimeout": null, "datasource": "Prometheus", "gridPos": { "h": 6, "w": 4, "x": 13, "y": 0 }, "id": 25, "links": [], "options": { "fieldOptions": { "calcs": [ "lastNotNull" ], "defaults": { "decimals": 0, "mappings": [ { "id": 0, "op": "=", "text": "N/A", "type": 1, "value": "null" } ], "max": 100, "min": 0, "nullValueMode": "connected", "thresholds": { "mode": "absolute", "steps": [ { "color": "rgba(50, 172, 45, 0.97)", "value": null }, { "color": "rgba(237, 129, 40, 0.89)", "value": 70 }, { "color": "rgba(245, 54, 54, 0.9)", "value": 90 } ] }, "unit": "percent" }, "overrides": [], "values": false }, "orientation": "horizontal", "showThresholdLabels": false, "showThresholdMarkers": true }, "pluginVersion": "6.7.2", "targets": [ { "expr": "((node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes) * 100 ", "format": "time_series", "interval": "", "intervalFactor": 2, "legendFormat": "", "refId": "A", "step": 1800 } ], "timeFrom": null, "timeShift": null, "title": "RAM Auslastung", "type": "gauge" }, { "datasource": null, "gridPos": { "h": 6, "w": 7, "x": 17, "y": 0 }, "id": 39, "options": { "colorMode": "value", "fieldOptions": { "calcs": [ "mean" ], "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "decbytes" }, "overrides": [], "values": false }, "graphMode": "area", "justifyMode": "auto", "orientation": "auto" }, "pluginVersion": "6.7.2", "targets": [ { "expr": "node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes", "interval": "", "legendFormat": "", "refId": "A" } ], "timeFrom": null, "timeShift": null, "title": "RAM Verbrauch", "type": "stat" }, { "cacheTimeout": null, "colorBackground": false, "colorValue": false, "colors": [ "rgba(50, 172, 45, 0.97)", "rgba(237, 129, 40, 0.89)", "rgba(245, 54, 54, 0.9)" ], "datasource": "Prometheus", "decimals": 0, "editable": true, "error": false, "format": "decbytes", "gauge": { "maxValue": 500000000, "minValue": 0, "show": true, "thresholdLabels": false, "thresholdMarkers": true }, "gridPos": { "h": 4, "w": 4, "x": 0, "y": 4 }, "id": 30, "interval": null, "links": [], "mappingType": 1, "mappingTypes": [ { "name": "value to text", "value": 1 }, { "name": "range to text", "value": 2 } ], "maxDataPoints": 100, "nullPointMode": "connected", "nullText": null, "postfix": "", "postfixFontSize": "50%", "prefix": "", "prefixFontSize": "50%", "rangeMaps": [ { "from": "null", "text": "N/A", "to": "null" } ], "sparkline": { "fillColor": "rgba(31, 118, 189, 0.18)", "full": false, "lineColor": "rgb(31, 120, 193)", "show": false }, "tableColumn": "", "targets": [ { "expr": "(node_memory_SwapTotal_bytes{instance=~'mon_node-exporter:9100'} - node_memory_SwapFree_bytes{instance=~'mon_node-exporter:9100'})", "format": "time_series", "intervalFactor": 2, "legendFormat": "", "refId": "A", "step": 1800 } ], "thresholds": "400000000", "title": "Swap", "type": "singlestat", "valueFontSize": "80%", "valueMaps": [ { "op": "=", "text": "N/A", "value": "null" } ], "valueName": "current" }, { "cacheTimeout": null, "colorBackground": false, "colorValue": false, "colors": [ "rgba(50, 172, 45, 0.97)", "rgba(237, 129, 40, 0.89)", "rgba(245, 54, 54, 0.9)" ], "datasource": "Prometheus", "decimals": 1, "editable": true, "error": false, "format": "percentunit", "gauge": { "maxValue": 1, "minValue": 0, "show": true, "thresholdLabels": false, "thresholdMarkers": true }, "gridPos": { "h": 5, "w": 4, "x": 13, "y": 6 }, "id": 26, "interval": null, "links": [], "mappingType": 1, "mappingTypes": [ { "name": "value to text", "value": 1 }, { "name": "range to text", "value": 2 } ], "maxDataPoints": 100, "nullPointMode": "connected", "nullText": null, "postfix": "", "postfixFontSize": "50%", "prefix": "", "prefixFontSize": "50%", "rangeMaps": [ { "from": "null", "text": "N/A", "to": "null" } ], "sparkline": { "fillColor": "rgba(31, 118, 189, 0.18)", "full": false, "lineColor": "rgb(31, 120, 193)", "show": false }, "tableColumn": "", "targets": [ { "expr": "min((node_filesystem_size_bytes{fstype=~\"xfs|ext4\",instance=\"mon_node-exporter:9100\"} - node_filesystem_free_bytes{fstype=~\"xfs|ext4\",instance=\"mon_node-exporter:9100\"} )/ node_filesystem_size_bytes{fstype=~\"xfs|ext4\",instance=\"mon_node-exporter:9100\"})", "format": "time_series", "hide": false, "interval": "", "intervalFactor": 2, "legendFormat": "", "refId": "A", "step": 1800 } ], "thresholds": "0.75, 0.90", "title": "Festplatten Auslastung", "type": "singlestat", "valueFontSize": "80%", "valueMaps": [ { "op": "=", "text": "N/A", "value": "null" } ], "valueName": "current" }, { "datasource": "Prometheus", "gridPos": { "h": 5, "w": 7, "x": 17, "y": 6 }, "id": 13, "links": [], "options": { "colorMode": "value", "fieldOptions": { "calcs": [ "mean" ], "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "decbytes" }, "overrides": [], "values": false }, "graphMode": "area", "justifyMode": "auto", "orientation": "auto" }, "pluginVersion": "6.7.2", "targets": [ { "expr": "node_filesystem_size_bytes{fstype=\"ext4\"} - node_filesystem_free_bytes{fstype=\"ext4\"}", "format": "time_series", "hide": false, "interval": "", "intervalFactor": 2, "legendFormat": "{{device}}", "refId": "A", "step": 600 } ], "timeFrom": null, "timeShift": null, "title": "Festplatten Verbrauch", "type": "stat" }, { "aliasColors": { "IN on /sda": "#7EB26D", "OUT on /sda": "#890F02" }, "bars": false, "dashLength": 10, "dashes": false, "datasource": "Prometheus", "editable": true, "error": false, "fill": 1, "fillGradient": 0, "grid": {}, "gridPos": { "h": 9, "w": 9, "x": 4, "y": 7 }, "hiddenSeries": false, "id": 3, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": false, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null as zero", "options": { "dataLinks": [] }, "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "-sum(rate(node_disk_read_bytes_total[$interval])) by (device)", "format": "time_series", "hide": false, "intervalFactor": 2, "legendFormat": "OUT on /{{device}}", "metric": "node_disk_bytes_read", "refId": "A", "step": 600 }, { "expr": "sum(rate(node_disk_written_bytes_total[$interval])) by (device)", "format": "time_series", "intervalFactor": 2, "legendFormat": "IN on /{{device}}", "metric": "", "refId": "B", "step": 600 } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Disk I/O", "tooltip": { "msResolution": true, "shared": true, "sort": 0, "value_type": "cumulative" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": false, "values": [] }, "yaxes": [ { "format": "Bps", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": false } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": { "SENT": "#BF1B00" }, "bars": false, "dashLength": 10, "dashes": false, "datasource": "Prometheus", "editable": true, "error": false, "fill": 1, "fillGradient": 0, "grid": {}, "gridPos": { "h": 8, "w": 4, "x": 0, "y": 8 }, "hiddenSeries": false, "id": 19, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": false, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null as zero", "options": { "dataLinks": [] }, "percentage": false, "pointradius": 1, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "sum(rate(container_network_receive_bytes_total{id=\"/\"}[$interval])) by (id)", "intervalFactor": 2, "legendFormat": "RECEIVED", "refId": "A", "step": 600 }, { "expr": "- sum(rate(container_network_transmit_bytes_total{id=\"/\"}[$interval])) by (id)", "hide": false, "intervalFactor": 2, "legendFormat": "SENT", "refId": "B", "step": 600 } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Netzwerk Verkehr", "tooltip": { "msResolution": true, "shared": true, "sort": 0, "value_type": "cumulative" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": false, "values": [] }, "yaxes": [ { "format": "bytes", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": false } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "Prometheus", "editable": true, "error": false, "fill": 1, "fillGradient": 0, "grid": {}, "gridPos": { "h": 7, "w": 11, "x": 13, "y": 11 }, "hiddenSeries": false, "id": 9, "legend": { "alignAsTable": true, "avg": false, "current": false, "hideEmpty": false, "hideZero": false, "max": false, "min": false, "rightSide": true, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 2, "links": [], "nullPointMode": "null as zero", "options": { "dataLinks": [] }, "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "sum(rate(container_network_transmit_bytes_total{name=~\".+\"}[$interval])) by (name)", "intervalFactor": 2, "legendFormat": "{{name}}", "refId": "A", "step": 240 }, { "expr": "rate(container_network_transmit_bytes_total{id=\"/\"}[$interval])", "hide": true, "intervalFactor": 2, "legendFormat": "", "refId": "B", "step": 10 } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Sent Network Traffic per Container", "tooltip": { "msResolution": true, "shared": true, "sort": 0, "value_type": "cumulative" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "Bps", "label": "", "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": "", "logBase": 10, "max": 8, "min": 0, "show": false } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "cacheTimeout": null, "dashLength": 10, "dashes": false, "datasource": "Prometheus", "editable": true, "error": false, "fill": 5, "fillGradient": 0, "grid": {}, "gridPos": { "h": 7, "w": 13, "x": 0, "y": 16 }, "hiddenSeries": false, "id": 1, "legend": { "alignAsTable": true, "avg": false, "current": false, "max": false, "min": false, "rightSide": true, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null as zero", "options": { "dataLinks": [] }, "percentage": false, "pluginVersion": "6.7.2", "pointradius": 5, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "expr": "sum(rate(container_cpu_usage_seconds_total{name=~\".+\"}[$interval])) by (name) * 100", "hide": false, "interval": "", "intervalFactor": 2, "legendFormat": "{{name}}", "metric": "", "refId": "F", "step": 240 } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "CPU Usage per Container", "tooltip": { "msResolution": true, "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "percent", "label": "", "logBase": 1, "max": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": false } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "Prometheus", "editable": true, "error": false, "fill": 1, "fillGradient": 0, "grid": {}, "gridPos": { "h": 7, "w": 11, "x": 13, "y": 18 }, "hiddenSeries": false, "id": 8, "legend": { "alignAsTable": true, "avg": false, "current": false, "max": false, "min": false, "rightSide": true, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 2, "links": [], "nullPointMode": "null as zero", "options": { "dataLinks": [] }, "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "sum(rate(container_network_receive_bytes_total{name=~\".+\"}[$interval])) by (name)", "intervalFactor": 2, "legendFormat": "{{name}}", "refId": "A", "step": 240 }, { "expr": "- rate(container_network_transmit_bytes_total{name=~\".+\"}[$interval])", "hide": true, "intervalFactor": 2, "legendFormat": "{{name}}", "refId": "B", "step": 10 } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Received Network Traffic per Container", "tooltip": { "msResolution": true, "shared": true, "sort": 0, "value_type": "cumulative" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "Bps", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "Prometheus", "editable": true, "error": false, "fill": 3, "fillGradient": 0, "grid": {}, "gridPos": { "h": 7, "w": 13, "x": 0, "y": 23 }, "hiddenSeries": false, "id": 10, "legend": { "alignAsTable": true, "avg": false, "current": false, "max": false, "min": false, "rightSide": true, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 2, "links": [], "nullPointMode": "null as zero", "options": { "dataLinks": [] }, "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "expr": "sum(container_memory_rss{name=~\".+\"}) by (name)", "hide": false, "intervalFactor": 2, "legendFormat": "{{name}}", "refId": "A", "step": 240 }, { "expr": "container_memory_usage_bytes{name=~\".+\"}", "hide": true, "intervalFactor": 2, "legendFormat": "{{name}}", "refId": "B", "step": 240 } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Memory Usage per Container", "tooltip": { "msResolution": true, "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "bytes", "label": "", "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "columns": [ { "text": "Current", "value": "current" } ], "datasource": null, "editable": true, "error": false, "fontSize": "100%", "gridPos": { "h": 8, "w": 11, "x": 13, "y": 25 }, "id": 37, "links": [], "pageSize": null, "scroll": true, "showHeader": true, "sort": { "col": 1, "desc": true }, "styles": [ { "align": "auto", "colorMode": null, "colors": [ "rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)" ], "decimals": 2, "pattern": "/.*/", "thresholds": [ "10000000", " 25000000" ], "type": "number", "unit": "decbytes" } ], "targets": [ { "expr": "sum(container_spec_memory_limit_bytes{name=~\".+\"} - container_memory_usage_bytes{name=~\".+\"}) by (name) ", "hide": true, "intervalFactor": 2, "legendFormat": "{{name}}", "metric": "", "refId": "A", "step": 240 }, { "expr": "sum(container_spec_memory_limit_bytes{name=~\".+\"}) by (name) ", "hide": true, "intervalFactor": 2, "legendFormat": "{{name}}", "refId": "B", "step": 240 }, { "expr": "container_memory_usage_bytes{name=~\".+\"}", "hide": false, "intervalFactor": 2, "legendFormat": "{{name}}", "refId": "C", "step": 240 } ], "title": "Usage memory", "transform": "timeseries_aggregations", "type": "table" } ], "refresh": "5s", "schemaVersion": 22, "style": "dark", "tags": [], "templating": { "list": [ { "auto": true, "auto_count": 50, "auto_min": "50s", "current": { "selected": false, "text": "30s", "value": "30s" }, "hide": 0, "label": "interval", "name": "interval", "options": [ { "selected": false, "text": "auto", "value": "$__auto_interval_interval" }, { "selected": true, "text": "30s", "value": "30s" }, { "selected": false, "text": "1m", "value": "1m" }, { "selected": false, "text": "2m", "value": "2m" }, { "selected": false, "text": "3m", "value": "3m" }, { "selected": false, "text": "5m", "value": "5m" }, { "selected": false, "text": "7m", "value": "7m" }, { "selected": false, "text": "10m", "value": "10m" }, { "selected": false, "text": "30m", "value": "30m" }, { "selected": false, "text": "1h", "value": "1h" }, { "selected": false, "text": "6h", "value": "6h" }, { "selected": false, "text": "12h", "value": "12h" }, { "selected": false, "text": "1d", "value": "1d" }, { "selected": false, "text": "7d", "value": "7d" }, { "selected": false, "text": "14d", "value": "14d" }, { "selected": false, "text": "30d", "value": "30d" } ], "query": "30s,1m,2m,3m,5m,7m,10m,30m,1h,6h,12h,1d,7d,14d,30d", "refresh": 2, "skipUrlSync": false, "type": "interval" } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": { "refresh_intervals": [ "5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d" ], "time_options": [ "5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d" ] }, "timezone": "browser", "title": "Docker - System Dashboard", "uid": "0E0FhC7Wz", "variables": { "list": [] }, "version": 1 }
Danach klickt ihr auf “Load”.
Nun klickt ihr “Import”.
Jetzt solltet ihr folgendes sehen.
Hallo an alle,
ich habe mir die Traefik Metriks mit in Grafana eingebunden:
Dazu habe ich folgendes gemacht:
/opt/containers/traefik-crowdsec-stack/traefik/traefik.yml
metrics:
prometheus:
addRoutersLabels: true
addEntryPointsLabels: true
addServicesLabels: true
buckets: 0.100000, 0.300000, 1.200000, 5.000000
entryPoint: metrics
entryPoints:
metrics:
address: :8899
(Das wird auch im Traefik-Dashboard angezeigt)
/opt/containers/grafana/prometheus/prometheus.yml
scrape_configs:
– job_name: ‘traefik’
static_configs:
– targets: [‘traefik:8899’]
/opt/contaimers/grafana/docker-compose.yml
services:
mon_prometheus:
networks:
– default
– proxy
(damit der prometheus den traefik auch sehen kann)
Jetzt in Grafana das Board 17346 importieren.
Gibt noch einen kleinen Trick, sich ein Dashbord zu importieren:
Hier ein Dashboard raussuchen:
https://grafana.com/grafana/dashboards/
Dann sich die Nummer merken
Also bei diesem: https://grafana.com/grafana/dashboards/1860-node-exporter-full/ wäre es 1860.
Dann
Dashboards / New / Import / – in der Mitte die Nummer eingeben – Prometheus – Datasource auswählen / Import
hey hab folgendes Problem.
Erst läuft es und nach einer weile bekomme ich dieses Bild
If you’re seeing this Grafana has failed to load its application files
1. This could be caused by your reverse proxy settings.
2. If you host grafana under subpath make sure your grafana.ini root_url setting includes subpath. If not using a reverse proxy make sure to set serve_from_sub_path to true.
3. If you have a local dev build make sure you build frontend using: yarn start, or yarn build
4. Sometimes restarting grafana-server can help
5. Check if you are using a non-supported browser. For more information, refer to the list of supported browsers.
Unbedingt compose im grafana Ordner abschießen. Prometheus findet ansonsten seine config nicht.
Guten Abend
zuerst einmal muss ich mich bedanken für die super Anleitung! Hat fast auf anhieb funktioniert. Warum fast? Ja ich glaub, das liegt an cadvisor.
Da funktionieren wohl nicht alle Versionen.
Hab nach langer Suche folgendes herausbekommen:
die Zeilen in der Compose lauten:
mon_cadvisor:
container_name: cadvisor
image: gcr.io/cadvisor/cadvisor:latest
…
das funktioniert leider nicht. Der Dienst startet nicht
mit den Versionen 0.47.2 sowie 0.45.0 geht es.
mon_cadvisor:
container_name: cadvisor
image: gcr.io/cadvisor/cadvisor:v0.47.2 #v0.45.0 v0.47.2
…
Das hat 3 Stunden gedauert, bis ich das gefunden hab. Das muss ja nicht jeder machen
Guten Morgen, ich hatte ebenfalls das Problem, dass er Prometheus mit dem Hostname http://mon_prometheus:9090 nicht verbinden konnte, ich musste tatsächlich via docker ps die Container ID raussuchen, dann mit docker inspect die IP des Containers selbst herrausfinden und diese dann als URL eintragen. Dann lief es bei mir, vielleicht hilft es ja jemanden. ^-^
Hallo Zusammen
Danke für die wirklich gute Anleitung.
Allerdings stosse ich auf ein Problem mit dem Zertifikat für die Subdomain – es wird nicht generiert.
Laut der Anleitung wird in den Labels der entrypoint “websecure”, _.grafana.tls=true und _.grafana.certresolver=http_resolver verwendet – wie für den traefik proxy zur Generierung von Zertifikaten vorgesehen.
Ich habe mittels –force-recreate alle Dienste neugestartet und im traefik dashboard wird der Router und der Service für grafana auch fehlerfrei angelegt.
Kann mir jemand helfen und aufzeigen wie man das Problem am besten untersucht?
Viele Grüsse
Alex
Hi Christian,
bei mir kommt Prometheus einfach nicht hoch – habe nichts an der Config geändert.. keine Ahnung was da los ist. Any ideas?
Guten Abend (:
sag mal wie kann ich unter deiner anleitung auch weitere dashboards hinzufügen? zb wie ich den Datenverbrauch meines routers bekommen?
also wie kann ich einsehen, wie GB oder auch T ich pro tag/ pro monat verbrauche (:
am besten sogar evtl einsehen von allen geräten in meinem netzwerk?
das wäre super cool von dir (:
deine anleitung ist echt geil (:
danke dir dafür auf jedenfall
Hallo,
erstmal danke für die Anleitung.
Ich hatte am Anfang mit dem “”User: 1000″”
nach dem ich den auskommentiert hatte und allen Verzeichnissen wieder root:root verpasste hatte lief das.
hier mal der Link dazu: https://grafana.com/docs/grafana/latest/setup-grafana/installation/docker/#migrate-to-v51-or-later
Nun habe ich noch das Problem das mein Grafana Container einfach keine IP bekommt.
Ich habe den default durch backend ersetzt und auch auf default gelassen. (backend hatte ich natürlich vorher angelegt).
Egal wie ich es anstelle ich bekomme einfach für den Grafana Container keine IP Adresse.
Getestet habe ich folgendes:
service:
mon_grafana:
.
.
networks:
proxy:
ipv4_address: 172.18.0.5
backend:
ipv4_address: 172.19.0.5
oder eben mit automatischer vergabe
service:
mon_grafana:
.
.
networks:
– proxy
– backend
Die Netzwerke funktionieren, da die anderen Container ja im Backend IP Adressen bekommen und das Proxy Netz schon andere Container (Traefik,Portainer,Watchtower, ….. ) enthalten die alle neben einer IPv4 auch IPv6 bekommen ohne Probs ( ps IPv6 bekommt der Grafana Container auch keine )
Hier noch mal meine komplette Docker-Compose-File
version: ‘2.5’
services:
mon_prometheus:
image: prom/prometheus:latest
container_name: mon_prometheus
restart: unless-stopped
volumes:
– ../prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
depends_on:
– mon_node-exporter
– mon_cadvisor
networks:
– default
#backend:
#ipv4_address: 172.19.0.2
mon_node-exporter:
image: prom/node-exporter:latest
container_name: mon_node-exporter
restart: unless-stopped
volumes:
– /proc:/host/proc:ro
– /sys:/host/sys:ro
– /:/rootfs:ro
command:
– ‘–path.procfs=/host/proc’
– ‘–path.sysfs=/host/sys’
– ‘–path.rootfs=/rootfs’
– ‘–collector.filesystem.ignored-mount-points=”^(/rootfs|/host|)/(sys|proc|dev|host|etc)($$|/)”‘
– ‘–collector.filesystem.ignored-fs-types=”^(sys|proc|auto|cgroup|devpts|ns|au|fuse\.lxc|mqueue)(fs|)$$”‘
networks:
– default
#backend:
#ipv4_address: 172.19.0.3
mon_cadvisor:
image: gcr.io/cadvisor/cadvisor
container_name: mon_cadvisor
restart: unless-stopped
volumes:
– /:/rootfs:ro
– /var/run:/var/run:rw
– /sys:/sys:ro
– /var/lib/docker/:/var/lib/docker:ro
networks:
– default
#backend:
#ipv4_address: 172.19.0.4
mon_grafana:
image: grafana/grafana:latest
container_name: mon_grafana
restart: unless-stopped
volumes:
– /opt/containers/grafana/grafana:/var/lib/grafana
#user: “1000”
depends_on:
– mon_prometheus
labels:
– “traefik.enable=true”
– “traefik.http.routers.grafana.entrypoints=https”
– “traefik.http.routers.grafana.rule=(Host(
grafana.meinedomain.dev
))”– “traefik.http.routers.grafana.tls=true”
– “traefik.http.routers.grafana.tls.certresolver=http”
– “traefik.http.routers.grafana.service=grafana”
– “traefik.http.services.grafana.loadbalancer.server.port=3000”
– “traefik.docker.network=proxy”
– “traefik.http.routers.grafana.middlewares=default@file”
networks:
– proxy
#ipv4_address: 172.18.0.5
#ipv6_address: 2a03:4000:56:f4a:2::5
– default
#backend:
#ipv4_address: 172.19.0.5
networks:
proxy:
external: true
# backend:
# external: true
Die auskommentierten Zeilen habe ich mal drinne gelassen um dir zu zeigen was ich schon alles probiert habe.
Vielleicht hast du ja ne Lösung
System ist ein Debian 11 auf KVM Server (mit VMX Flag)
Zudem habe ich noch einen NDP Proxy laufen damit das IPv6 durchgereicht wird (die IPv6 Konfig meines Anbieters ist da nicht ganz sauber deswegen ist das notwendig)
Weis nicht ob es wichtig ist aber es läuft noch eine UFW mit Anpassungen für Docker drauf hier mal die Regeln die für Docker relevant sind:
[ 2] 172.20.0.2 27999/udp ALLOW FWD Anywhere # allow wireguard 27999/udp wireguard_default
[ 3] 172.18.0.2 80/tcp ALLOW FWD Anywhere # allow traefik 80/tcp proxy
[ 4] 172.18.0.2 443/tcp ALLOW FWD Anywhere # allow traefik 443/tcp proxy
Auch wenn Portainer hier nicht aufgeführt ist. Dank Traefik Freigabe funktioniert das alles
Ich bekomme folgenden Fehler, wenn ich ‘docker-compose up’ ausführe:
Attaching to mon_cadvisor, mon_grafana, mon_node-exporter, mon_prometheus
mon_grafana | GF_PATHS_DATA=’/var/lib/grafana’ is not writable.
mon_grafana | You may have issues with file permissions, more information here: http://docs.grafana.org/installation/docker/#migrate-to-v51-or-later
mon_grafana | mkdir: can’t create directory ‘/var/lib/grafana/plugins’: Permission denied
mon_grafana exited with code 1
Wie in den Docs empfohlen, versuchte ich es auch mit dem ‘user 104’, doch ebenfalls ohne Erfolg.
Hat jemand einen Tipp?
Ich glaube beim grafana service ist das “networks: – default” zu viel. Kommt ja unten noch mal und dann korrekt inkl. Proxy-Netzwerk. Zumindest hat Portainer vorher gemeckert.
Ich habe noch /etc/grafana als Volume bei grafana eingebunden, da ich dann die grafana.ini bearbeiten kann. War nötig, da ich OAuth2 von Google nutze und damit dann der Login möglich ist.
Ein Problem hab ich mit dem Dashboard. Bei mir funktioniert die “Memory Usage per Container” nicht. Irgendeine Idee?
Pefekte Anleitung, danke!
Es ist so unfassbar brauchbar. Immer wenn ich ein Tutorial suche lande ich hier 😀 und freue mich weil ich weiß dann funktioniert es 😀
Hi, leider sind bei mir ebenfalls viele Felder leer (N/A). Ich betreibe alle Container mit Portainer und bin immer als root unterwegs, vielleicht kommt sich das ja mit der UserID 1000 in die Quere…hat jemand eine Idee?
Hi, wollte eben bescheid geben, dass “google/cadvisor” als DEPRECATED markiert ist und neue images nur noch unter “gcr.io/cadvisor/cadvisor” kommen.
Deine Anleitung hat super funktioniert. Bis auf dass der cadvisor immer abgeschmiert ist und dann keine Metriken der Container kamen.
In einem Forum bin ich dann auf den Punkt gestoßen
image: gcr.io/cadvisor/cadvisor
nachdem ich das obige Image verwendet habe gings.
Vielleicht ist das ja ein Problem das andere auch haben
Hi Christian,
vielen Lieben dank für die ganzen guten Beschreibungen. Hut ab.
Ich habe bei mit Docker Rootless laufen kann es sein das Grafana/Prometheus root rechte benötigt.
Beste Grüße
Rainer
Hallo.
Ich bekomme leider nachdem ich unter URL folgendes eingetragen habe “http://mon_prometheus:9090” folgende Fehlermeldung: HTTP Error Bad Gateway. Ich hoffe mir kann da vielleicht jemand weiterhelfen.
Grüße Ted
Hallo Christian,
vielen Dank für die sehr gute Anleitung!
Gibt es eine Möglichkeit auf Grafana ein User zu anlegen, der ohne Anmeldedaten auf die Übersicht (Dashboard) kommt? Das wäre für mich interessant, vielleicht hast du eine Idee wie das funktioniert. Wäre cool, wenn du das mit uns teilst.
Vielen Grüße
Koray
Hallo,
Danke Christian für die Anleitung und danke Jonas für den Hinweis!
Leider bekomme ich bei diversen Tabellen die Meldung: ‘N/A’, ‘No Data’ oder ‘No data to show’.
Bin der oben stehenden Anleitung Step by Step gefolgt, da frag ich mich nun was habe ich falsch gemacht oder was ich noch ändern muss? Hat da jemand von euch ein Hinweis? Wäre cool, danke.
Grüsse
Gabriel
Hi Christian!
Nachdem ich deiner Anleitung gefolgt war, bekam ich auf meinem Dashboard immer wieder eine Fehlermeldung und viele Kacheln waren leer.
Ich habe nach einiger Zeit herausgefunden, dass in der JSON-File in Zeile 6 bei “datasource” “Prometheus” statt ” – Grafana – ” stehen muss, weil die Datasource die vorher erstellt wurde so heißt.
Vielleicht ein Hinweis, falls jemand das gleiche Problem hat 🙂
Liebe Grüße
Jonas
Hast du dir das Thema “Alerts” mal angeschaut? Macht eigentlich Sinn! Du kannst direkt in deiner Docker-Compose Datei den smtp Host definieren und in grafana “Alerts” einrichten. Würde mich interessieren ob es bei dir klappt.
Hallo wie kann ich mir den die Server “Uptime” ins Dashboard einbauen?
Hast du zufällig damit schon Kontakt gehabt?
Grüße