Blog
Veröffentlicht vor 2 Jahren
Im vorangegangenen Teil haben wir die Einrichtung von code-server abgeschlossen. Damit wäre die serverbasierte Entwicklungsumgebung schon voll einsatzfähig. Darüber hinaus ist es aber durchaus sinnvoll, sich die Leistungsdaten (z.B. CPU- Auslatung, RAM- Nutzung und Netzwerkdurchsatz ) des Servers regelmäßig anzuschauen. Da sieht man auf den ersten Blick, ob noch alles ordnungsgemäß läuft. Damit kann man auch abschätzen, ob der gewählte Server für den beabsichtigten Einsatzzweck ausreichend ist oder vielleicht sogar überdimensioniert ist.
Das Server- Monitoring, das wir einrichten werden, besteht im Wesentlichen aus drei Bestandteilen:
Prometheus ist eine sehr beliebte Anwendung im Bereich des Server- Monitorings, da es nicht nur eine Zeitreihendatenbank ist, sondern auch noch das regelmäßige Abfragen der Messwerte von vordefinierten Datenquellen, sogenannte "Exporter", ("Polling") übernimmt.
Da hierfür aber eine etwas aufwändigere Konfiguration notwendig ist, kommt wieder das inwzischen bekannte Schema zum Einsatz, bei dem wir das Basis- Image von Prometheus mit Dockerfile und Github Actions um die Konfigurationsdateien erweitern.
Zuerst erstellen wir also den neuen Ordner prometheus/config
im Stammverezeichnis des Repos und
dann die Datei prometheus-config.yml
im Pfad `prometheus/config/ mit dem folgenden Inhalt:
# ./prometheus/config/prometheus-config.yml
global:
scrape_interval: 15s # By default, scrape targets every 15 seconds.
scrape_configs:
# prometheus (optional)
# - job_name: 'prometheus'
# static_configs:
# - targets: ['localhost:9090']
# node_exporter
- job_name: 'node_exporter'
static_configs:
- targets: ['node_exporter:9100']
# cadvisor
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
Mit dieser Konfigurationsdatei wird zunächst ein globales Zeitintervall für das Abfragen der
Messwerte von 15 Sekunden definiert. Sollte bei bestimmten Messwerten ein anderes Zeitintervall
gewünscht werden, kann dieses mit der Direktive scrape_interval
auch bei den einzelnen
Datenquellen konfiguriert werden.
Unter scrape_configs
werden dann die Datenquellen ("Exporter") definiert, von denen Messwerte
abgefragt werden sollen. Diese sind in unserem Fall:
node_exporter
: Daten des Serverscadvisor
: Daten der einzelnen Docker- ContainerFür die Exporter müssen wir dann später noch die entsprechenden Docker- Container einrichten und starten.
Als nächstes brauchen wir noch ein Dockerfile für die Anweisungen, wie wir das Base Image von Prometheus mit der Konfigurationsdatei erweitern:
# ./prometheus/Dockerfile
# base image
FROM prom/prometheus:v2.33.1
# copy configuration file
RUN mkdir -p /etc/prometheus
COPY ./config/prometheus-config.yml /etc/prometheus/prometheus-config.yml
Hier wird einfach die Konfigurationsdatei, die wir weiter oben erstellt haben während des Build- Prozesses an die richtige Stelle im Container kopiert.
Außerdem brauchen wir noch eine Github Action die unser Docker Image für Prometheus erstellt und in der Github Container Registry bereitstellt. Diese Github Action ist nach demselben Schema aufgebaut, wie auch die Actions zum Erstellen der adneren Docker- Images:
# ./.github/workflows/docker-build-prometheus.yml
name: build custom image for prometheus
on:
push:
branches:
- 'master'
paths:
- 'prometheus/**'
jobs:
build-prometheus:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Set up Docker BuildX
uses: docker/setup-buildx-action@v1
- name: login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push the custom Prometheus Image
uses: docker/build-push-action@v2
with:
context: ./prometheus
push: true
tags: ghcr.io/<GITHUB_USERNAME>/prometheus:latest
Weiterhin ergänzen wir die docker-compose.yml
um die Direktiven zum Starten des Prometheus-
Containers:
# ./docker-compose.yml
networks:
# ...
monitoring:
driver: bridge
volumes:
# ...
prometheus-data:
driver: local
services:
# ...
##############
# Monitoring #
##############
prometheus:
image: ghcr.io/<GITHUB_USERNAME>/prometheus:latest
container_name: prometheus
networks:
- monitoring
expose:
- 9090
volumes:
- prometheus-data:/prometheus
restart: unless-stopped
labels:
- 'com.centurylinklabs.watchtower.enable=true'
command:
- '--config.file=/etc/prometheus/prometheus-config.yml'
Für die Kommunikation der Container des Monitorings fügen wir ein weiteres lokales Netzwerk mit dem
Namen monitoring
hinzu und erstellen ein weiteres Volume für die dauerhafte Speicherung der
Prometheus Datenbank.
Die Direktiven für den Prometheus- Container sind ja relativ selbsterklärend. Ein wichtiger Punkt
ist jedoch, dass wir unter der command
- Direktive den Pfad zur Konfigurationsdatei angeben, die
wir während des Build- Prozesses in das Image kopiert haben.
Wie oben schon erwähnt nutzen wir zwei Datenquellen für unser Monitoring. Die Konfiguration dieser
Datenquellen ist aber so einfach, dass wir lediglich unsere docker-compose.yml
um die folgenden
Zeilen erweiteren müssen:
# ./docker-compose.yml
services:
# ...
node_exporter:
image: quay.io/prometheus/node-exporter:latest
container_name: node_exporter
command:
- '--path.rootfs=/host'
pid: host
restart: unless-stopped
volumes:
- '/:/host:ro,rslave'
labels:
- 'com.centurylinklabs.watchtower.enable=true'
networks:
- monitoring
cadvisor:
image: google/cadvisor:latest
container_name: cadvisor
networks:
- monitoring
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
labels:
- 'com.centurylinklabs.watchtower.enable=true'
devices:
- /dev/kmsg
restart: unless-stopped
Beiden Containern müssen wir umfangreichen Zugriff auf das Host- System gewähren, damit die
gewünschten Daten auch ausgelesen werden können. Dazu werden jeweils mehrere Volumes definiert, für
die aber mit dem Zusatz :ro
nur Leserechte gewährt werden.
Auch die Definition des Containers für Grafana erfolgt ausschließlich in der docker-compose.yml
.
Wir fügen dort also noch folgende Zeilen ein:
# ./docker-compose.yml
volumes:
#...
grafana-data:
driver: local
services:
# ...
grafana:
image: grafana/grafana-oss:latest
container_name: grafana
networks:
- proxy
- monitoring
expose:
- 3000
volumes:
- grafana-data:/var/lib/grafana
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.grafana.rule=Host(`grafana.server.<MY-DOMAIN>`)"
- "traefik.http.routers.grafana.entrypoints=https"
- "traefik.http.routers.grafana.tls=true"
- "traefik.http.routers.grafana.tls.certresolver=letsencrypt"
- "traefik.http.routers.grafana.middlewares=authelia@docker"
- "traefik.docker.network=proxy"
- "com.centurylinklabs.watchtower.enable=true"
environment:
- "GF_AUTH_ANONYMOUS_ENABLED=true"
- "GF_AUTH_ORG_ROLE=Editor"
- "GF_AUTH_DISABLE_LOGIN_FORM=true"
- "GF_AUTH_ANONYMOUS_ORG_ROLE=Admin"
Da wir ja bereits mit Authelia eine Authentifizierung für Aufrufe des Grafana Dashboards eingerichtet haben, nutzen wir die Umgebungsvariablen, um das in Grafana eingebaute Authentifizierungssystem auszuschalten. Außerdem fügen wir den Grafana- Container neben dem Monitoring- Netzwerk auch noch zum Netzwerk Proxy hinzu, um Verbindungen aus dem Internet über den Traefik Reverse Proxy zu ermöglichen.
Nachdem wir unsere Änderungen am Repo committed und auf Github gepusht haben, müssen wir noch ein
bisschen warten, bis das neue Prometheus- Image erstellt wurde. Danach können wir uns per SSH auf
dem Server einloggen, den Ordner mit dem Repo aufrufen und mit dem folgenden Befehl
docker-compose down
alle laufenden Container stoppen.
Als nächsten holen wir uns die neueste Version mit git pull origin main
von Github und starten mit
docker-compose up -d
alle Container wieder (inklusive der neuen Monitoring- Container).
Nun können wir unsers Grafana- Instanz im Browser aufrufen (grafana.server.<MY-DOMAIN>
) und in der
GUI noch die Einrichtung abschließen sowie die gewünschten Dashboards konfigurieren.
Zunächst fügen wir Prometheus als Datenquelle für Grafana hinzu. Hierzu fahren wir mit der Maus auf
das Zahnrad in der linkeren unteren Ecke des Bildschirms und wählen im Menü "Data Sources" aus. Ein
Klick auf "Add Data Source" bringt uns zu einer Liste mit verschieden Datenquellen, von der wir
natürlich "Prometheus" auswählen. Die Einstellungen könnenfast alle auf der Voreinstellung
verbleiben. Nur bei URL tragen wir http://prometheus:9090
ein, um auf den Prometheus- Container
zugreifen zu können.
Nun könnten wir unsere Dashboards mit den Daten aus Prometheus selbst erstellen. Das ist aber eine Menge Arbeit, die sich zum Glück schon andere gemacht haben. Auf der Seite https://grafana.com/grafana/dashboards/ gibt es eine Vielzahl von fertigen Dashboards, die sich sehr einfach in Grafana einbinden lassen. Ich nutze die folgende beiden Dashboards:
Die Einbindung dieser beiden Dashboards erfolgt ganz einfach über die ID, die auf der Seite in der
Seitenleiste rechts angegeben ist. Für "Node Exporter Full" ist das 1860
und für "Cadvisor
Exporter" 14282
. In Grafana klicken wir auf der linken Seite auf das Icon für die Dashboards (vier
Quadrate), danach auf den Button "New" und wählen aus dem Menü "Import" aus. Im Feld "Import via
grafana.com" muss die ID des gewünschten Dashboards eingfügt und mit Klick auf "Load" bestätigt
werden. Nach einigen Augenblicken öffnet sich das Dashboard und die ersten Messwerte werden
angezeigt.
Da die Container für die Erfassung der Messwerte ja erst seit ein paar Minuten laufen, gibt es natürlich auch nur für diesen kurzen Bereich Messwerte und es könnte sein, dass mit dem standardmäßig eingestellten Zeitintervall von 24 Stunden für die Anzeige noch nichts zu erkennen ist. Über einen Button in der oberen rechten Ecke kann aber das Zeitintervall angepasst werden.
Das war jetzt zwar ne ganze Menge Arbeit, aber nun haben wir einen eigenen Server, mit dem wir die Webentwicklung vom Endgerät entkoppeln und in die Cloud verlegen können. Außerdem ist ein solcher Server auch ein toller Startpunkt, um weitere Dienste wie zum Beispiel einer Datenbank oder einer eigenen Nextcloud- Instanz hinzuzufügen. Den Server könnte man aber auch nutzen, um selbst entwickelte Apps und Webseiten zu hosten. Nach meiner Erfahrung ist der Server mit der beschriebenen Einrichtung noch keineswegs ausgelastet und bietet noch viel Raum für Erweiterungen.
Den gesamten Code und die Konfigurationsdateien, die in den vier Blogeinträgen dieser Serie beschrieben wurden, können auch in meinem Github Repository eingesehen und heruntergeladen werden.
Zum Abschluss möchte ich noch Danke sagen, dass du dir die Zeit zum Lesen dieser Serie genommen hast, und hoffe, dass du dabei auch die ein oder andere Sache gelernt hast.