Menu

Docker Monitoring mit cAdvisor, Influxdb und Grafana

26. November 2016 - Docker

Einleitung

Wenn man Docker in einer Produktivumgebung betreibt möchte man die Maschine und die Services auch im Monitoring haben. Der Docker Host selber kann natürlich in Nagios o.ä. eingebunden werden, genauso wie die einzelnen Services innerhalb der Container.

Interessant ist es aber auch einen Blick auf die Statistiken über den Ressourcen Verbrauch der einzelnen Container und des gesamten Docker Systems auf dem Host zu haben. Dafür hat google den cAdvisor entwickelt. Dieser besitzt auch ein kleines Web Interface, um die Daten der aktuellen Prozesse zu sehen.

Allerdings möchte man auch gerne eine Historie der Messdaten haben. Dafür bieten sich ‚Timeseries Databases‚ an, also Datenbanken, die darauf optimiert sind Eintäge bezogen auf den Zeitpunkt zu speichern. Bekannteste Vertreter sind hier Influxdb und Prometheus. Wobei Prometheus weiter auf das speichern von numerischen Werten optimiert ist und eine höhere Kompressionsrate zeigt. Influxdb kann dagegen auch nicht numerische Daten speichern.

Zur Visualisierung der Daten ist Grafana eigentlich das Werkzeug der Wahl. Die Promtheus Datenbank besitzt auch ein eigenes Visualisierungs-Tool PromDash, auf der Webseite wird aber auch die Verwendung von Grafana gegenüber PromDash empfohlen.

Aufgrund der (beschriebenen) besseren Implementation von numerischen Messdaten wäre eigentlich Prometheus die Datenbank der Wahl. Leider habe ich Prometheus noch nicht mit cAdvisor zusammen ans Laufen bekommen. Prometheus zieht sich Daten alle paar Sekunden vom cAdvisor und die Einrichtung scheint nicht ganz so trivial zu sein. Mangels Zeit habe ich hier nur wenig probieren können, zumal ich selber bereits eine laufende Installation mit Influxdb habe. Von daher wird auch hier die Implementation mit Influxdb beschrieben.

Da die verschiedenen Container miteinander interagieren müssen, werden diese mit Hilfe von Docker Compose erzeugt und es wird eine docker-compose.yml erstellt. Die docker-compose.yml findet sich im zugehörigen Projekt auf github:

https://github.com/StMoelter/blog-docker-monitoring

Die einzelnen Schritte sind in verschiedenen Branches des Git-Repositories aufgeteilt.

cAdvisor

Als Herzstück dient natürlich der cAdvisor, diesen wollen wir aufsetzen, starten und uns die Ausgabe im Web-Interface ansehen.

Das entsprechende docker-compose file findet sich im Branch cadvisor-basic:

https://github.com/StMoelter/blog-docker-monitoring/blob/cadvisor-basic/docker-compose.yml

Dort finden sich folgende Einträge:

version: '2'
services:
  cadvisor:
    container_name: cadvisor
    restart: unless-stopped
    image: google/cadvisor:latest
    volumes:
      - /var/run:/var/run:rw
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    ports:
      - 127.0.0.1:8080:8080

In dem Beispiel wird die Version des Docker Compose Syntax verwendet, deshalb die Angabe in der ersten Zeile, die Sektion ’services‘, die in Zeile 2 eingeleitet wird ist entsprechend dem Syntax der Version 2.

Zeile 3 definiert den Service ‚cadvisor‘ im Container mit dem Namen ‚cadvisor‘ (Zeile 4). Die Angabe: restart: unless-stopped ist ganz praktisch für das lokale testen, da der Service nach einem reboot des hosts wieder ausgeführt wird, allerdings nicht wenn der service händisch gestoppt wurde. Dadurch entstehen weniger ungewollte Nebeneffekte auf dem Docker Host, bei der Entwicklung. Für Produktiv Systeme würde man eher restart: always wählen.

Das Image für den Container kommt von der Docker Registry, definiert in Zeile 5.

Der Zugriff auf die Daten des Docker Hosts wird in der Sektion ‚volumes‘ getätigt. Innerhalb dieser Ordner die hier für den Container zugänglich gemacht werden, findet der cAdvisor im Container die benötigten Daten für die Auswertung.

Zeile 11 und 12 definieren die Weiterleitung des Ports 8080 im Container auf 8080 lokal auf dem Docker Host ( – Host:Container ). Ohne die Angabe 127.0.0.1 würde der Port auf 0.0.0.0:8080 des Hosts gebunden werden und wäre evtl. aus dem Internet erreichbar, was wir nicht wollen.

Wenn Docker innerhalb einer virtuellen Maschine läuft (wie z.B. öfters bei Mac Usern zu sehen) ist zu beachten, dass dann der Port lokal auf der virtuellen Maschine weitergeleitet wird. Hier kann man dann 127.0.0.1 mit der IP der virtuellen Maschine ersetzen.

Um den Docker Container zu starten geht man in der Kommendozeile in den Ordner mit der docker-compose.yml und gibt den Befehl:

docker-compose up -d

ein. Dies startet den cAdvisor im Container im Hintergrung (-d für daemonize)

Mit dem Browser auf http://127.0.0.1:8080 navigieren, es sollte sich ein folgendes Bild zeigen:

bildschirmfoto_2016-10-23_16-58-05

 

Influxdb

Die Einstellungen für die influxdb finden sich im Branch ‚influxdb‘.

Das entsprechende docker-compose.yml findet sich hier:

https://github.com/StMoelter/blog-docker-monitoring/blob/influxdb/docker-compose.yml

Mit folgenden Einträgen:

version: '2'
services:
  influxdb:
    container_name: influx
    restart: unless-stopped
    image: influxdb
    ports:
      - 127.0.0.1:8086:8086
      - 127.0.0.1:8083:8083

Im Vergleich zum cAdvisor fällt hier auf, dass der container_name: influx anstatt influxdb lautet, wie zu erwarten gewesen wäre. Das ist einfach nur meiner Test-Maschine geschuldet, da gibt es schon einen Container namens ‚influxdb‘, den ich jetzt nicht löschen wollte.

Es werden hier 2 Ports weitergeleitet. Diese werden beide für das Web-Interface benötigt, welches nach dem Start durch:

docker-compose up -d

unter 127.0.0.1:8083 erreichbar ist. Unter dem Port 8086 ist nun die API der Datenbank verfügbar. Das Web Interface macht nichts anderes als die API abzurufen und die Eingaben des Users an den Port 8086 zu senden. Das Webinterface, welches von Port 8083 ausgeliefert wird, ist eine kleine JavaScript Applikation im Browser, die mit dem Port 8086 des Server kommuniziert.

Für das weiter vorgehen soll jetzt eine Datenbank mit dem Namen cadvisor in der Influxdb angelegt werden. Alternativ erledigt ein:

curl -G http://localhost:8086/query --data-urlencode "q=CREATE DATABASE cadvisor"

Im Browser sollte das in etwa so aussehen:

bildschirmfoto_2016-10-23_17-31-43

cAdvisor Daten in Influxdb speichern

Die Daten für die Verbindung vom cAdvisor mit der Influxdb findet sich im Branch ‚cadvisor-influxdb‘, siehe:

https://github.com/StMoelter/blog-docker-monitoring/blob/cadvisor-influxdb/docker-compose.yml

Wir sehen hier, dass ein Netzwerk mit dem Namen app_net erstellt wurde und die Container bekommen Zugriff darauf. Dadurch ist eine Kommunikation zwischen den Servern gewährleistet, ohne dass das Netzwerk des Hosts allzusehr beeinflusst wird.

Interessant ist hier die Zeile 13, da werden zusätzliche Parameter für den Aufruf des cAdvisors definiert. Diese Parameter weisen den cAdvisor an die gesammelten Daten an die Influxdb zu übermitteln:

command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influx:8086

Gesamter Code:

version: '2'
services:
  cadvisor:
    container_name: cadvisor
    restart: unless-stopped
    image: google/cadvisor:latest
    volumes:
      - /var/run:/var/run:rw
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influx:8086
    ports:
      - 127.0.0.1:8080:8080
    networks:
      - app_net

  influxdb:
    container_name: influx
    restart: unless-stopped
    image: influxdb
    ports:
      - 127.0.0.1:8086:8086
      - 127.0.0.1:8083:8083
    networks:
      - app_net

networks:
  app_net:
    driver: bridge

Die Container wurden geändert, von daher sollten diese neu initialisiert werden.

Dazu werden zuerst alle beide Container gestoppt:

docker-compose stop

Beide Container löschen:

docker rm influx
docker rm cadvisor

Die Container werden neu gestartet und vorher natürlich initialisiert mit den neuen Daten:

docker-compose up -d

Einmal auf 127.0.0.1:8083 mit dem Browser schauen und evtl. die Datenbank cadvisor in der Influxdb anlegen.  (s.o.)

Gibt es die Datenbank, dann nach einer Minute (es dauert etwas, bis cadvisor die Daten sendet) mal einen Blick auf die Measurements werfen:

bildschirmfoto_2016-10-27_23-42-01

Jetzt wird die Influxdb mit Daten vom cAdvisor befüllt und wir können diese Auswerten. Damit das komfortabel ist, schauen wir uns mal Grafana dafür an.

Dashboard mit Grafana erstellen

Grafana als Docker Image starten.

Das Grafana Image nehmen wir auch vom Docker Hub, siehe hier:

https://hub.docker.com/r/grafana/grafana/

Integration in die docker-compose.yml ist zu finden im git Repo, Branch grafana:

https://github.com/StMoelter/blog-docker-monitoring/blob/grafana/docker-compose.yml

Definition in docker-compose.yml:

grafana:
  container_name: grafana
  restart: unless-stopped
  image: grafana/grafana
  ports:
    - 127.0.0.1:3000:3000
  environment:
    - GF_SERVER_ROOT_URL=http://localhost:3000
    - GF_SECURITY_ADMIN_PASSWORD=password
  networks:
    - app_net

Die Umgebungsvariablen bestimmen einmal die URL für Grafana und das admin password, hier password. Das initiale Login erfoglt also über ‚admin / password‘ im Browser Interface.

Beim Port 3000 auf localhost ist zu beachten, dass einige Rails Entwicklungsserver diesen auch benutzen. Wenn der Port auf dem Host schon im Gebrauch ist einfach die Angabe unter ‚-ports‘ auf 127.0.0.1:3001:3000 ändern und GF_SERVER_ROOT_URL=http://localhost:3001 setzen.

Der Container wird mit docker-compose up -d grafana gestartet.

Danach kann man mit dem Browser die url:

http://127.0.0.1:3000

ansteuern.

Grafana login

 

Nun kann man sich mit dem Usernamen ‚admin‘ und dem Passwort ‚password‘ anmelden.

Von der Seite der Docker Container ist nun alles getan. Im Weiteren werden wir uns mit der Einrichtung des Dashboards in Grafana beschäftigen.

Influxdb Datenbank als Datenquelle einrichten

Grafana kann mit mehreren Datrenquellen umgehen. Wir wollen hier die Datenbank ‚cadvisor‘ in der Influxdb in Grafana definieren

Nach dem Login klickt man auf das Grafana-Logo in der linken oberen Ecke. Es erscheint eine weitere Navigation, hier bitte ‚Data Sources‘ wählen.

bildschirmfoto_2016-11-05_13-52-29

 

Bei der Definition der Datenquelle geben wir unter ‚Name‘ den Namen der Datenquelle in Grafana an. Hier wählt man auch ‚cadvisor‘, darunter wird umter ‚Type‘ die Art des Datenspeichers gewählt. Das ist in diesem Falle ‚Influxdb‘.

Unter den http settings geben wir http://influx:8086 als ‚Url‘ an und ‚procy‘ als ‚Access‘. Es gibt als ‚Access‘ proxy und direct. bei direct werden die Datenbanken queries direkt vom Browser an die Datenbank abgesetzt. Bei ‚proxy‘ werden die Anfragen an Grafana gesendet und von hier zur Datenbank. In einer Produktiv-Umgebung will man nicht unbedingt die Datenbank im Internet öffnen sondern nur lokal zugängöich haben. Deshalb  ist ‚proxy‘ hier die Einstellung der Wahl, auch wenn es auf einer Entwicklungsumgebung mit ‚direct‘ auch funktionieren würde. Als ‚Url‘ wurde hier die Influxdb über den Docker-Hostnamen angegeben, damit das Grafana Backend den Server findet.

HttpAuth bleibt leer, wurde nicht definiert. Als ‚Database‘ wird auch cadvisor angegeben, ‚User‘ und ‚Password‘ für die Influxdb werden hier nicht benötigt und bleiben leer.

bildschirmfoto_2016-11-05_13-54-00

 

Nach Klick auf ‚Save & Test‘ sollte wir die grüne ‚Success‘ Meldung wie im Bild oben sehen. Damit ist die Datenquelle in Grafana definiert und man kann jetzt Auswertungen visualisieren.

Daten visualisieren

Dazu wird zuerst ein neues Dashboard erstellt. Man klicke wieder auf das Grafana Symbol in der Ecke oben links. In der erscheinenden Navigation dann ‚Dashboards‘, danach ‚+ New‘.

Man landet auf folgender Seite:

bildschirmfoto_2016-11-26_17-50-15

Unter dem Grafana Symbol in der oberen linken Ecke findet sich ein recht unauffälliger grüner Balken. Geht man mit der Maus darauf, so fährt dieser aus, nach Klick kann man nun aus einer Navigation auswählen.

‚Add Panel‘ -> ‚Graph‘ wird gebraucht.

Folgende Seite ist nun sichtbar:

bildschirmfoto_2016-11-26_17-57-55

Unter dem Bereich ‚Panel data source‘ wird ‚cadvisor‘ ausgewählt. Danach der Editor-Modus durch Klick auf das große, blaue ‚A‘ neben dem Datenbank Statement geändert:

Editior Modus für Datenbank Statement

Es soll nun ein Graph erzeugt werden, welcher die Speicherauslastung des Influxdb Containers zeigt. Dazu klickt man auf ’select measurement‘ im ‚FROM‘ Bereich des Statements, dann kann man ‚memory_usage‘ auswählen. Nun muss noch ein Container ausgewählt werden. Dazu auf das ‚+‘ neben ‚WHERE‘ klicken. Nach Klick in das neu erscheinende Feld rechts neben dem Plus-Zeichen kann man das Feld aussuchen nachdem gefiltert werden soll.  In diesem Falle ist es ‚container_name‘.

bildschirmfoto_2016-11-26_21-15-48

Der Gleichheitsoperator wird automatisch ausgewählt. Man klickt in das Feld daneben und wählt einen passenden Wert aus. Für dieses Beispiel ist das ‚influx‘ als Containername.

bildschirmfoto_2016-11-26_21-39-55

Der Eintrag ist recht weit unten zu finden, der cadvisor speichert au noch einige interne Daten unter anderen Containernamen.

Nun sollte ein Graph sichtbar werden. Der Graph braucht noch eine schöne Überschrift. Dazu klickt man im Tab auf ‚General‘. Dort kann man die Überschrift ändern.bildschirmfoto_2016-11-26_21-22-37

Die Y-Achse zeigt jetzt noch reine Zahlenwerte, welche ad hoc schwer zu interpretieren sind. Um dies zu ändern klickt man im Tab auf ‚Axes‘:

bildschirmfoto_2016-11-26_21-23-06

Dort kann man die rechte Y-Achse abschalten und für die linke die korrekte Einstallung wählen. Dazu auf den Wert von ‚Unit‘ klicken und wie im Bild oben auswählen.

Die Einstellungen für den Graph sind nun soweit fertig und werden mit einem Klick auf das ‚X‘ rechts neben der  Tab Navigation beendet.

Nun sollte das Dashboard noch gespeichert werden, um die Einstellung zu behalten.

bildschirmfoto_2016-11-26_21-24-48

Dies wird durch Klicken auf die keine Diskette in der Hauptnavigation ganz oben getätigt.

Viel Spaß beim Erstellen weiterer Visualisierungen mit Grafana.

Im Master-Branch findet sich noch eine json Datei zum Import in Grafana für 2 Graphen.