Docker Monitoring mit Prometheus
Diese Anleitung beschäftigt sich mit der meist verbreitetsten Methode ein Monitoring für Docker und natürlich auch den Host einzurichten. Warum man das braucht, ganz klar um zu sehen, wie es dem Host nach dem Deployment von euren Containern geht und zu sehen, wieviel Ressourcenhunger die einzelnen Container mit sich bringen. So sieht man auch ob ein Host ausgelastet ist, oder ob gar noch mehr Container auf ihm laufen können. Ein proaktives Alerting sorgt dafür, das man rechtzeitig informiert wird, sollte irgendeine Ressource ausgehen (RAM, CPU, Storage). Für dieses Monitoring wird als Basis Prometheus
verwendet, welches die Host Informationen durch den node-exporter
und die docker Informationen durch Googles cAdvisor
bekommt. Für hübsche Grafiken und ein Alerting auf diese sorgt dann grafana
. Wir bauen uns das Ganze hier via Docker-Compose Projekt zusammen und setzen in Grafana dann ein kleines Dashboard ein, das ich mir zusammengeklickt habe. Das Alerting geschieht dann via E-Mail. Auch hier nutze ich wieder den NGINX SSL Reverse Proxy für Docker Container um Grafana sicher nach außen freizugeben. Zusätzlich kann man seine Webseiten (sogar die SSL Zertifikate) mittel blackbox-exporter
überwachen und in Grafana einbinden.
Vorbereitung
Zuerst legen wir den Compose Projekt Ordner an und springen in Ihn hinein:
mkdir -p /opt/monitoring/data/prometheus
cd /opt/monitoring
Dann brauchen wir die prometheus Konfigurationsdatei, welche sich mit den beiden Daten Crawlern (node-exporter
und cAdvisor
) verbindet. einfach die Datei mit untenstehendem Inhalt anlegen:
/opt/monitoring/data/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
monitor: 'vs'
rule_files:
scrape_configs:
- job_name: 'nodeexporter'
static_configs:
- targets: ['nodeexporter:9100']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
Nun richten wir einen vHost für den NGINX SSL Reverse Proxy für Docker Container ein:
Ich nutze hierfür eine eigene Subdomain: monitoring.domain.tld
Also legen wir eine Konfigdatei hierzu an:
/opt/nginxproxy/data/nginx/conf/monitoring.domain.tld.conf
server { listen 80; listen [::]:80; server_name monitoring.domain.tld; return 301 https://$host$request_uri; } server { listen 443 ssl; listen [::]:443 ssl; server_name monitoring.domain.tld; ssl_certificate /etc/letsencrypt/live/monitoring.domain.tld/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/monitoring.domain.tld/privkey.pem; include /etc/nginx/conf.d/includes/site-defaults.conf; include /etc/nginx/conf.d/includes/cert_bot.conf; expires $expires; location / { proxy_pass http://127.0.0.1:8070/; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; client_max_body_size 0; #include /etc/nginx/conf.d/includes/proxy_cache.conf; } # security headers add_header X-Robots-Tag none; add_header Strict-Transport-Security "max-age=15768000;"; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; add_header X-Download-Options noopen; add_header X-Frame-Options "sameorigin"; add_header X-Permitted-Cross-Domain-Policies none; add_header Referrer-Policy strict-origin; }
Nun generieren wir das SSL Zertifikat.
cd /opt/nginxproxy
echo "monitoring.domain.tld" >> domains.txt
./generate-certs.sh
Danach sollte der NGINX mit der neuen vhost online sein.
Docker Compose Projekt
Nun legen wir die Konfigurationen für das Compose Projekt an. Im .env
File geben wir an, das der Interne Port 3000
nach außen an localhost
Port 8070
gebunden wird.
/opt/monitoring/.env
# Config File for Monitoring Application
# Port Configuration
INT_PORT=3000
BIND_TO=127.0.0.1:8070
# Timezone
TZ=Europe/Berlin
In unserer Compose Projekt Datei passiert folgendes:
- Wir starten den
node-exporter
, welcher die wichtigen Dateisysteme read only gemountet und konfiguriert bekommt. - Das selbe Spiel bei
cAdvisor
- Prometheus wird mit der vorhin angelegten Konfigurationsdatei anschließend gestartet
- Grafana bekommt noch ein persistentes Volume und die Environment Variablen für den SMTP Server
- Das Label dient dazu, das Watchtower automatisch aktualisiert
Also einfach die Datei mit dem folgenden Inhalt anlegen
/opt/monitoring/docker-compose.yml
version: '3.7'
services:
prometheus:
image: prom/prometheus:latest
depends_on:
- nodeexporter
- cadvisor
volumes:
- data_monitoring_prometheus:/prometheus
- ./data/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
restart: always
environment:
TZ: ${TZ}
labels:
com.centurylinklabs.watchtower.enable: "true"
networks:
backend-mo:
aliases:
- prometheus
nodeexporter:
image: prom/node-exporter:latest
restart: always
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|)$$"'
environment:
TZ: ${TZ}
labels:
com.centurylinklabs.watchtower.enable: "true"
networks:
backend-mo:
aliases:
- nodeexporter
cadvisor:
image: gcr.io/google-containers/cadvisor:latest
restart: always
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
environment:
TZ: ${TZ}
command:
- --housekeeping_interval=15s
- --global_housekeeping_interval=15s
labels:
com.centurylinklabs.watchtower.enable: "true"
networks:
backend-mo:
aliases:
- cadvisor
renderer:
image: grafana/grafana-image-renderer:latest
restart: always
ports:
- 8081
environment:
ENABLE_METRICS: 'true'
labels:
com.centurylinklabs.watchtower.enable: "true"
networks:
backend-mo:
aliases:
- renderer
grafana:
image: grafana/grafana:latest
depends_on:
- prometheus
ports:
- ${BIND_TO}:${INT_PORT}
restart: always
volumes:
- data_monitoring_grafana:/var/lib/grafana
user: "0" # USER ID des Docker Users anpassen
environment:
- TZ= ${TZ}
- GF_SMTP_ENABLED=true
- GF_SMTP_HOST=mx.yourdomain.tld:465
- GF_SMTP_USER=monitoring@yourdomain.tld
- GF_SMTP_PASSWORD=MAILLPASSWORD
- GF_SMTP_FROM_ADDRESS=monitoring@yourdomain.tld
- GF_RENDERING_SERVER_URL=http://renderer:8081/render
- GF_RENDERING_CALLBACK_URL=http://grafana:3000/
- GF_LOG_FILTERS=rendering:debug
labels:
com.centurylinklabs.watchtower.enable: "true"
networks:
frontend-mo:
backend-mo:
aliases:
- grafana
volumes:
data_monitoring_grafana:
data_monitoring_prometheus:
networks:
frontend-mo:
driver: bridge
driver_opts:
com.docker.network.bridge.name: br-monitoringfe
backend-mo:
driver: bridge
driver_opts:
com.docker.network.bridge.name: br-monitoringbe
Zu guter Letzt deployen wir unseren Monitoring Stack:
cd /opt/monitoring
docker-compose up -d
Konfiguration Grafana
Nach dem alles gestartet wurde sollte der Aufruf unserer URL, den Grafana Login zeigen:
- https://monitoring.domain.tld
Hier loggen wir uns mit dem Standard Benutzer und Passwort admin / admin
ein und werden direkt aufgefordert das Kennwort zu ändern. Machen und Merken ;-)
Der Nächste schritt ist es Prometheus
als Datenquelle einzurichten:
Save & Test
und fertig. Nun ist alles wie gewünscht konfiguriert. Ihr könnt nun ein eigenes Dashboard bauen oder, ein fertiges herunterladen. Zu empfehlen wäre hier auf jeden Fall folgendes für den Node-Exporter:
Einfach auf Dashboards - Manage gehen und bei Import die Dashboard Nummer eingeben. Es gibt unter https://grafana.com/grafana/dashboards eine Ganze Menge an Dashboards, auch für Docker. Ich habe allerdings ein eigenes zusammengeklickt.
Grafana Dashboard
Ich habe mir ein eigenes Grafana Dashboard für Docker und System mit Alerting auf RAM, CPU, LOAD und Festplatte gebaut. Dies stelle ich hier zur Verfügung. Es sieht dann in etwa so aus wie in den nachfolgenden Screenshots:
Für den Dashboard Import kann entweder die Datei heruntergeladen werden, oder Untenstehendes via copy and paste genutzt eingefügt werden.
Download: Datei:Dashboard-by-ala.json
Copy&Paste: Grafana Docker and System Monitoring Dashboard
Webseiten Monitoring
Möchte man zusätzlich noch seine Webseiten mit Prometheus und Grafana überwachen, braucht man noch zusätzlich den blackbox_exporter
. Auch diesen gibt es als Docker Image und muss nur in unser Compose Projekt eingefügt werden. Doch als erstes legen wir die Konfigurationsdatei hierfür an:
mkdir /opt/monitoring/data/blackbox/
/opt/monitoring/data/blackbox/blackbox.yml
modules:
http_2xx:
prober: http
http:
preferred_ip_protocol: "ipv4"
http_post_2xx:
prober: http
http:
method: POST
preferred_ip_protocol: "ipv4"
nun binden wir den blackbox-exporter
in unser bestehendes docker-compose.yml
... depends_on - blackbox hinzufügen
services:
prometheus:
image: prom/prometheus:latest
depends_on:
- nodeexporter
- cadvisor
- blackbox
... Nach dem node-exporter
blackbox:
image: prom/blackbox-exporter:latest
restart: always
volumes:
- ./data/blackbox/blackbox.yml:/etc/blackbox_exporter/config.yml
environment:
TZ: ${TZ}
labels:
com.centurylinklabs.watchtower.enable: "true"
networks:
backend-mo:
aliases:
- blackbox
... vor cAdvisor
Das war es schon. nun einfach wie immer das Projekt neu deployen:
docker-compose up -d
In Grafana selbst habe ich folgendes Dashboard benutzt was ohne große Anpassungen funktioniert:
Wenn nun alles passt, solltet ihr folgendes sehen:
Man kann dann noch Alerts einrichten, ganz wie man möchte.
Hohe CPU Last durch cAdvisor
Bei mir kam es durch cAdvisor zu einer sehr hohen CPU Last durch den Prozess. top
zeigte fast dauerhaft 10-20% CPU Auslastung an. Nachdem ich im docker-compose.yml
die beiden Parameter --housekeeping_interval=15s --global_housekeeping_interval=15s
übergeben habe ist die Last auf 1-3% gesunken. Es gibt noch mehr Parameter, die man übergeben kann. Das docker-compose.yml
sollte dann wie folgte aussehen:
...
cadvisor:
#image: google/cadvisor:latest
image: gcr.io/google-containers/cadvisor:latest
restart: always
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
environment:
TZ: ${TZ}
command:
- --housekeeping_interval=15s
- --global_housekeeping_interval=15s
#- --allow_dynamic_housekeeping=true
#- --disable_metrics=disk,tcp,udp
#- --docker_only
labels:
com.centurylinklabs.watchtower.enable: "true"
networks:
backend-mo:
aliases:
- cadvisor
...
Quellen
- https://teqqy.de/docker-monitoring-mit-prometheus-und-grafana/
- https://docs.docker.com/config/thirdparty/prometheus/
- https://prometheus.io/docs/guides/cadvisor/
- https://scoutapm.com/blog/prometheus-and-docker-monitoring-your-environment
- https://grafana.com/grafana/dashboards/893
- https://github.com/prometheus/blackbox_exporter/blob/master/README.md
- https://medium.com/the-telegraph-engineering/how-prometheus-and-the-blackbox-exporter-makes-monitoring-microservice-endpoints-easy-and-free-of-a986078912ee