4.3. Umsetzung

4.3.1. Reverse-Proxy über Traefik

Docker Compose Definition

Wir verwenden wieder Traefik, um die GUIs von Prometheus und Grafana über die Domains prom.dva.mahart.ma und grafana.dva.mahart.ma per https zu erreichen. Wir haben bereits Erfahrung mit dem Reverse Proxy und können daher eine angepasste Docker Compose Definition aus dem letzten Versuch wiederverwenden.

networks:
grafana:
    external: true

services:
watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    restart: unless-stopped
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    command: --label-enable --interval=43200 --cleanup
    networks:
    - grafana

traefik:
    image: "traefik:v2.11"
    container_name: "traefik"
    command:
    #- "--log.level=DEBUG"
    #- "--api.insecure=true"
    - "--api.dashboard=true"
    - "--providers.docker=true"
    - "--providers.docker.exposedbydefault=false"
    - "--providers.docker.network=web"
    - "--entrypoints.web.address=:80"
    - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
    - "--entrypoints.websecure.address=:443"
    - "--entrypoints.websecure.http.middlewares=https_config@docker,www-redirect@docker"
    - "--entrypoints.websecure.http.tls.options=default"
    - "--entrypoints.websecure.http.tls.certresolver=myresolver"
    - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
    #- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
    - "--certificatesresolvers.myresolver.acme.email=mahartma@mahartma.com"
    - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"

    labels:
    traefik.enable: true

    # https redirect
    traefik.http.middlewares.https_config.redirectscheme.scheme: "https"
    traefik.http.middlewares.https_config.redirectscheme.permanent: true

    # www -> non-www
    traefik.http.middlewares.www-redirect.redirectregex.regex: "^https://www.(.*)"
    traefik.http.middlewares.www-redirect.redirectregex.replacement: "https://$${1}"
    traefik.http.middlewares.www-redirect.redirectregex.permanent: true

    # basic-auth
    # Note: when used in docker-compose.yml all dollar signs in the hash need to be doubled for escaping.
    # echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
    traefik.http.middlewares.dev-auth.basicauth.users: "dva:$$apr1$$gUBBy11O$$w.owgrn.62lbLkM2ON.1p0" # password: secure

    # dashboard
    traefik.http.routers.api.rule: Host(`traefik.dva.mahart.ma`)
    traefik.http.routers.api.service: api@internal
    traefik.http.routers.api.middlewares: dev-auth
    traefik.http.routers.api.entrypoints: websecure

    # auto updates via watchtower
    com.centurylinklabs.watchtower.enable: true

    ports:
    - "443:443"
    - "80:80"

    volumes:
    - "/var/lib/traefik/letsencrypt:/letsencrypt"
    - "/var/run/docker.sock:/var/run/docker.sock:ro"

    networks:
    - grafana
    - default

    restart: unless-stopped

Prometheus und Grafana Services werden im gleichen Netzwerk wie Traefik betrieben, um die Kommunikation zu gewährleisten.

Da die Prometheus GUI keine Authentifizierung hat, haben wir Basic-Auth eingerichtet. Auch die automatische Provisionierung von Zertifikaten über Let’s Encrypt kann für Services einfach aktiviert werden. Beides kann für die jeweiligen Services über Labels aktiviert werden. Das Traefik Dashboard ist über die Domain traefik.dva.mahart.ma erreichbar.

Watchtower ist ebenfalls für alle Services aktiviert, um automatische Updates zu gewährleisten.

Quellen:

4.3.2. Prometheus

Docker Compose Definition

Auch die Prometheus-Instanz wurde mithilfe von Docker Compose aufgesetzt.

services:
    prometheus:
        image: docker.io/prom/prometheus:latest
        container_name: prometheus
        user: root
        ports:
        - 9090:9090
        networks:
        - grafana
        command:
        "--config.file=/etc/prometheus/prometheus.yaml"
        volumes:
        - ./prometheus/prometheus.yaml:/etc/prometheus/prometheus.yaml:ro
        - ./prometheus/prometheus-data:/prometheus
        depends_on:
        - cadvisor
        - node_exporter
        restart: unless-stopped
        labels:
        - traefik.enable=true
        - "traefik.http.routers.prom.rule=Host(`prom.dva.mahart.ma`)"
        - "traefik.http.routers.prom.entrypoints=websecure"
        - "traefik.http.routers.prom.tls.certresolver=myresolver"
        - "traefik.http.routers.prom.service=prom-prom"
        - "traefik.http.services.prom-prom.loadbalancer.server.port=9090"
        - "traefik.http.routers.prom.middlewares=dev-auth" # enable basic auth
        - "com.centurylinklabs.watchtower.enable=true"

In dieser Service-Definition binden wir direkt das offzielle Image von prometheus ein. Port und Network werden definiert, um die kommunikation zwischen den Instanzen zu gewährleisten und die Weboberfläche zugänglich machen zu können.

Im command: referenzieren wir auf die zu verwendende config, welche wir unter volumes: als Read-Only in den Container mounten. Des Weiteren wird noch ein zusätzliches Verzeichnis in den Container gemounted um die Daten über den Lebenszyklus des Containers hinweg persistent zu halten. Abschließend werden wieder Traefik Labels gesetzt, um die Kommunikation über den Reverse Proxy, die automatische Zertifikatsverwaltung und Basic-Auth zu aktivieren.

Die grafische Oberfläche von Prometheus ist über die Domain prom.dva.mahart.ma erreichbar. Sie kann verwendet werden, um die Datenquellen und Jobs zu überwachen.

Quellen:

Prometheus Konfiguration

Die Prometheus-config wird ebenfalls im YAML-format definiert. Die Config wurde in der Docker-Compose Definition über einen Bind-Mount in den Container gemounted und wird beim Start des Containers eingelesen, um die Jobs entsprechend zu starten. Versionsverwaltung und Backup der Config sind daher sehr wichtig.

global:
  scrape_interval: 15s

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

Nebst den globalen Settings wie z.B. das scrape_intervall, können hier die worker-jobs definiert werden. Mit den Jobs konfigurieren wir, welche Services an welcher Adresse und in welchem Intervall gescraped werden sollen.

Wir haben hier zu Beginn nur einen Job, welcher den Prometheus-Server selbst überwacht. Im späteren Verlauf können hier weitere Jobs hinzugefügt werden, in unserem Beispiel der cadvisor und der node_exporter.

Quellen:

Exporter

Wir haben zwei Exporter hinzugefügt, um Metriken über die Systemressourcen des Host-Systems und die darauf laufenden Docker-Container zu sammeln. Die Prometheus-Instanz schreibt seine eigenen Metriken auch in die Datenbank, braucht dafür also keinen eigenen Exporter.

Node Exporter

Node Exporter ist ein Exporter für die Metriken des Betriebssystems. Er sammelt Metriken wie CPU-Auslastung, Speicher, Festplattenplatz und Netzwerkstatistiken. Die Metriken werden dann von Prometheus gescraped und können später in Grafana visualisiert werden. Der Node-Exporter wird unter der Apache 2.0 Lizenz bei Prometheus entwickelt und ist in Golang geschrieben.

Das Deployment des Node-Exporters erfolgt über folgende Docker-Compose Definition:

node_exporter:
    image: quay.io/prometheus/node-exporter:latest
    container_name: node_exporter
    command:
    - '--path.rootfs=/host'
    network_mode: host
    pid: host
    restart: unless-stopped
    volumes:
    - '/:/host:ro,rslave'
    labels:
    - "com.centurylinklabs.watchtower.enable=true"

Der Prometheus-Config wird eine weitere scrape_config hinzugefügt, um die Metriken des Node-Exporters zu sammeln:

# job for node_exporter
- job_name: 'node_exporter'
  static_configs:
    - targets: ['node_exporter:9100']

Quellen:

cAdvisor

CAdvisor ist ein Container-Advisor, der Metriken über die Containerleistung und die aktuell laufenden Container sammelt. Das Tool wird unter der Apache 2.0 Lizenz bei Google entwickelt, ebenfalls in Golang.

Auch der cAdvisor wird über Docker-Compose deployt:

cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    ports:
    - 8080:8080
    volumes:
    - /:/rootfs:ro
    - /var/run:/var/run:rw
    - /sys:/sys:ro
    - /var/lib/docker/:/var/lib/docker:ro
    depends_on:
    - redis
    networks:
    - grafana
    restart: unless-stopped
    labels:
    - "com.centurylinklabs.watchtower.enable=true"

redis:
    image: redis:latest
    container_name: redis
    ports:
    - 6379:6379
    networks:
    - grafana
    restart: unless-stopped
    labels:
    - "com.centurylinklabs.watchtower.enable=true"

Der cAdvisor stützt sich auf die Docker API, um Metriken über die Containerleistung zu sammeln. Die Metriken werden dann von Prometheus gescraped und können in Grafana visualisiert werden.

Der Prometheus-Config wird eine weitere scrape_config hinzugefügt, um die Metriken des cAdvisors zu sammeln:

# job for cadvisor
- job_name: 'cadvisor'
  static_configs:
    - targets: ['cadvisor:8080']

Quellen:

4.3.3. Grafana

Docker Compose Definition

Wir verwenden das offizielle Grafana Docker Image, um unsere Grafana Instanz über Docker Compose zu betreiben. Die Konfiguration erfolgt über Umgebungsvariablen.

networks:
grafana:
    external: true

services:
grafana:
    image: grafana/grafana-enterprise
    container_name: grafana
    restart: unless-stopped
    environment:
        - GRAFANA_VERSION=latest
        - GF_INSTALL_IMAGE_RENDERER_PLUGIN=true
        - GF_SERVER_ROOT_URL=https://grafana.dva.mahart.ma
        - GF_INSTALL_PLUGINS=grafana-clock-panel
        - GF_USERS_ALLOW_SIGN_UP=true
    networks:
        - grafana
    ports:
        - '127.0.0.1:3000:3000'
    volumes:
        - grafana-data:/var/lib/grafana
    labels:
        - traefik.enable=true
        - "traefik.http.routers.grafana.rule=Host(`grafana.dva.mahart.ma`)"
        - "traefik.http.routers.grafana.entrypoints=websecure"
        - "traefik.http.routers.grafana.tls.certresolver=myresolver"
        - "traefik.http.routers.grafana.service=grafana-grafana"
        - "traefik.http.services.grafana-grafana.loadbalancer.server.port=3000"
        - "traefik.http.routers.grafana.middlewares=dev-auth" # enable basic auth
        - "com.centurylinklabs.watchtower.enable=true"

volumes:
grafana-data: {}

Unsere Grafana Instanz nimmt Anfragen auf dem lokalen Port 3000 im externen Netzwerk grafana entgegen. Traefik wurde über die Labels konfiguriert, um die Kommunikation über den Reverse Proxy zu ermöglichen. Die Labels setzen die Domain auf grafana.dva.mahart.ma und aktivieren Basic-Auth. Die automatische Zertifikatsverwaltung über Let’s Encrypt ist ebenfalls aktiviert.

Ein Volume namens grafana-data wird über einen Bind-Mount angebunden, um Daten über den Lebenszyklus des Containers hinweg persistent zu halten.

Die grafische Oberfläche von Grafana ist über die Domain grafana.dva.mahart.ma erreichbar. Sie kann verwendet werden, um Dashboards zu erstellen und zu verwalten, Datenquellen zu konfigurieren und Benutzer zu verwalten.

Quellen:

Prometheus als Datenquelle hinzufügen

Das Hinzufügen von Datenquellen ist ein simpler Schritt, der in der Weboberfläche von Grafana durchgeführt werden kann. Wir haben Prometheus als Datenquelle hinzugefügt, um die Daten aus Prometheus in Grafana zu visualisieren. Beim Anlegen der Datenquelle müssen wir die URL von Prometheus angeben, die in unserem Fall http://localhost:9090 ist.

Beim Anlegen von Dashboards können wir dann die Datenquelle auswählen, um die Daten aus Prometheus zu visualisieren.

Quellen:

Dashboards anlegen

Dashboards können in Grafana über die Weboberfläche erstellt und angepasst werden. Es gibt auch die Möglichkeit, Dashboards als JSON-Dateien zu exportieren und zu importieren. Über den Grafana Marketplace können vorgefertigte Dashboards heruntergeladen und importiert werden bzw. über die ID des Dashboards direkt importiert werden. Hier ist natürlich zu beachten, dass die Datenquellen korrekt konfiguriert sind, um die Daten aus Prometheus zu visualisieren.

Node-Exporter Dashboard

Wir verwenden ein vorgefertigtes Dashboard für den Node-Exporter, um einen Überblick über die Systemressourcen zu erhalten. Das Dashboard wurde über die ID 1860 importiert. Das Dashboard stützt sich auf die Daten aus Prometheus, die von der Node-Exporter-Instanz gescraped werden.

Quellen:

Docker Dashboard

Wir verwenden ein vorgefertigtes Dashboard für Docker, um einen Überblick über die Container und Hosts zu erhalten. Das Dashboard wurde über die ID 10619 importiert. Das Dashboard stützt sich auf die Daten aus Prometheus, die von der cAdvisor-Instanz gescraped werden.

Quellen:

Google OAuth Konfiguration

Schritt 1: Erstellung eines Google OAuth-Client-IDs

  1. Die Google API-Konsole wird unter https://console.developers.google.com/apis/credentials aufgerufen.

  2. Credentials erstellen wird ausgewählt, dann OAuth-Client-ID aus dem Dropdown-Menü.

  3. Folgende Informationen werden eingegeben:
    • Anwendungstyp: Webanwendung

    • Name: Grafana

    • Autorisierte JavaScript-Ursprünge: https://grafana.dva.mahart.ma

    • Autorisierte Weiterleitungs-URLs: https://grafana.dva.mahart.ma/login/google

Schritt 2: Hinzufügen von Umgebungsvariablen in Docker Compose

environment:
  - GF_AUTH_GOOGLE_ENABLED=true
  - GF_AUTH_GOOGLE_ALLOW_SIGN_UP=true
  - GF_AUTH_GOOGLE_AUTO_LOGIN=false
  - GF_AUTH_GOOGLE_CLIENT_ID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  - GF_AUTH_GOOGLE_CLIENT_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  - GF_AUTH_GOOGLE_AUTH_URL=https://accounts.google.com/o/oauth2/v2/auth
  - GF_AUTH_GOOGLE_TOKEN_URL=https://oauth2.googleapis.com/token
  - GF_AUTH_GOOGLE_API_URL=https://openidconnect.googleapis.com/v1/userinfo
  - GF_AUTH_GOOGLE_HOSTED_DOMAIN=dva.mahart.ma
  - GF_AUTH_GOOGLE_USE_PKCE=true
  - GF_AUTH_GOOGLE_SCOPES=openid email profile
  • GF_AUTH_GOOGLE_ENABLED: Aktiviert die Google Authentifizierung.

  • GF_AUTH_GOOGLE_ALLOW_SIGN_UP: Ermöglicht neuen Benutzern die Anmeldung via Google, wenn sie noch keinen Account haben.

  • GF_AUTH_GOOGLE_AUTO_LOGIN: Steuert, ob Benutzer automatisch eingeloggt werden, nachdem sie sich authentifiziert haben.

  • GF_AUTH_GOOGLE_CLIENT_ID und GF_AUTH_GOOGLE_CLIENT_SECRET: Diese Schlüssel identifizieren Ihre Grafana-Instanz sicher gegenüber Google und sind essentiell für die Authentifizierung.

  • GF_AUTH_GOOGLE_AUTH_URL, GF_AUTH_GOOGLE_TOKEN_URL, GF_AUTH_GOOGLE_API_URL: URLs, die für den Authentifizierungsprozess mit Google verwendet werden.

  • GF_AUTH_GOOGLE_HOSTED_DOMAIN: Beschränkt die Anmeldung auf Nutzer aus einer spezifischen Google Domain.

  • GF_AUTH_GOOGLE_USE_PKCE: Verbessert die Sicherheit während des Authentifizierungsprozesses durch Verwendung des PKCE-Verfahrens (Proof Key for Code Exchange).

  • GF_AUTH_GOOGLE_SCOPES: Definiert die Bereiche, auf die Grafana Zugriff haben wird, wenn es mit Google kommuniziert (z.B. Profilinformationen des Benutzers).

Vorteile der Google OAuth-Authentifizierung

  • Sicherheit: Die Authentifizierung erfolgt über Google, was bedeutet, dass die Sicherheit der Anmeldedaten in den Händen von Google liegt.

  • Benutzerfreundlichkeit: Benutzer können sich mit ihren Google-Anmeldeinformationen anmelden, was den Anmeldevorgang vereinfacht.

  • Verwaltung: Administratoren können die Anmeldung über Google steuern, z.B. durch Beschränkung auf bestimmte Domains.

  • Single Sign-On (SSO): Benutzer können sich bei mehreren Diensten anmelden, die Google OAuth verwenden, ohne sich jedes Mal erneut anmelden zu müssen.

  • Skalierbarkeit und Flexibilität: Google OAuth skaliert nahtlos mit der Anzahl der Nutzer und unterstützt komplexe Berechtigungsszenarien, die sich leicht an die wachsenden Bedürfnisse einer Organisation anpassen lassen.