Blackbox Consul

Reisserischer Titel - ich weiß. Eigentlich will ich nur festhalten, was ich zum Thema "Prometheus Service Discovery mit Consul und Verwendung des Blackbox-Exporters" herausgefunden habe. Damit ich es leichter nachschlagen kann.

Um Metriken über Infrastruktur oder Applikationen zu sammeln, wird oft Prometheus verwendet. Wenn man jetzt Prometheus keine statische Liste von Zielen (Targets) geben kann, die er für Metriken abfragen soll, dann kann man mit Hilfe von "Service Discovery" Prometheus die Möglichkeit geben, diese Targets automatisch zu "entdecken". Prometheus unterstützt mehrere Varianten von "Service Discovery" - eine davon arbeitet mit Consul.

Dazu wird ein Consul Server (Cluster für Produktion - Single Instance für Tests) benötigt, bei dem sich Consul Clients automatisch anmelden.

Auf den Consul Clients wiederum sind - für die auf dem Client installierten Services - Service-Definitionen hinterlegt. Startet der Client, liest er die Service-Definitionen ein und registriert die Services so beim Consul Server.

Prometheus braucht dann nur noch den Consul Server nach den bei ihm registrierten Services zu fragen und erhält so seine Liste von Targets, bei denen er Metriken abholen soll.

Im Fall von Prometheus sind meist nicht die eigentlichen Services (z. B. MongoDB) sondern die zugehörigen Exporter (z. B. mongodb_exporter) interessant, weil sie auf dem Client die Metriken von der dort installierten Applikation erheben.

Weitere beliebte Exporter sind der node_exporter, der process_exporter und der blackbox_exporter.

Der blackbox_exporter tanzt ein wenig aus der Reihe, weil er quasi als Proxy fungiert und erst durch die Anfrage von Prometheus konfiguriert wird. Damit kann Prometheus quasi von der VM/Instanz aus, auf der der blackbox_exporter installiert ist, eine Aktion auslösen und die bei dieser Aktion gesammelten Metriken wieder abholen. Dazu unterstützt der blackbox_exporter verschiedene Module (sogenannte "probes" für http, tcp, dns, icmp, grpc und tls).

Die für den jeweiligen Client "erlaubten" probes werden in einer Konfigurationsdatei auf dem Client konfiguriert. Z. B. so:

root@probe-stage2-0:/etc/prometheus# cat blackbox.yml 
modules:
  tcp_connect:
    prober: tcp
  icmp:
    prober: icmp
  icmp_ipv4:
    prober: icmp
  icmp_ttl5:
    prober: icmp
    timeout: 5s
    icmp:
      ttl: 5
  dns_soa:
    prober: dns
    timeout: 5s
    dns: 
      query_name: "kubernetes.io"
      query_type: "SOA"

Mit dieser Konfiguration wird der blackbox_exporter dann z. B. als systemd-Service gestartet:

root@probe-stage2-0:~# systemctl cat blackbox-exporter
# /etc/systemd/system/blackbox-exporter.service
[Unit]
Description=Blackbox Exporter Service
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
Restart=always
User=root
Group=root
ExecStart=/usr/local/bin/blackbox_exporter --config.file=/etc/prometheus/blackbox.yml --web.listen-address=0.0.0.0:9115
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process

[Install]
WantedBy=multi-user.target

Die zugehörige Service-Definition für Consul, die ebenfalls auf dem Client hinterlegt ist, sieht so aus:

root@probe-stage2-0:~# cat /etc/consul/service_blackbox_exporter.json 
{
  "services": [
    {
       "address": "192.168.0.134",
       "name": "blackbox-exporter",
       "id": "blackbox-exporter",
       "port": 9115,
       "tags": [
         "monitoring"
       ],
       "enable_tag_override": false,
       "checks": [
         {
           "http": "http://127.0.9.1:9115",
           "interval": "10s",
         }
       ]
    },
    {
       "address": "192.168.0.134",
       "id": "icmp-default-gateway",
       "port": 9115,
       "name": "icmp",
       "tags": [
         "icmp:192.168.0.1", 
         "bb-icmp"
       ],
    },
    {
       "address": "192.168.0.134",
       "id": "icmp-resolver1",
       "port": 9115,
       "name": "icmp",
       "tags": [
         "icmp:10.14.25.55",
         "bb-icmp"
       ],
    },
    {
       "address": "192.168.0.134",
       "id": "icmp-resolver2",
       "port": 9115,
       "name": "icmp",
       "tags": [
         "icmp:10.15.25.55",
         "bb-icmp"
       ],
    },
    {
       "address": "192.168.0.134",
       "id": "dns-kubernetesio",
       "port": 9115,
       "name": "dns",
       "tags": [
         "dns:10.15.25.55"
         "bb-dns"
       ],
    }
  ] 
}

Natürlich "emittiert" der blackbox_exporter aus selbst Metriken. Die werden mit dem Service ganz oben erfasst. Dazu kommt noch ein Service-Check, den Consul durchführt, um den Dienst bei Ausfall direkt austragen zu können.

Die "address" ist dabei immer die IP-Adresse des Clients. Die in den Tags konfigurierte Adresse ist die, die getestet werden soll.

Die Herausforderung steckt jetzt in der Prometheus-Konfiguration auf dem Prometheus-Server:

debian@promgrafcon:~$ cat /etc/prometheus/prometheus.yaml 
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  scrape_timeout: 10s 

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

  - job_name: 'blackbox-exporter'
    consul_sd_configs:
      - server: '192.168.0.215:8500'
        datacenter: "probes-stage2"
        services: [blackbox-exporter]
    relabel_configs:
      - source_labels: [__meta_consul_tags]
        regex: .*,monitoring,.*
        action: keep
      - source_labels: [__meta_consul_service]
        target_label: job
  - job_name: 'blackbox-icmp'
    metrics_path: /probe
    params:
      module: [icmp_ipv4]
    consul_sd_configs:
      - server: '192.168.0.215:8500'
    relabel_configs:
      - source_labels: [__meta_consul_tags]
        regex: .*,bb-icmp,.*
        action: keep
      - source_labels: [__meta_consul_tags]
        regex: .*,icmp:([^,]+),.*
        replacement: '${1}'
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
  - job_name: 'blackbox-dns'
    metrics_path: /probe
    params:
      module: [dns_soa]
    consul_sd_configs:
      - server: '192.168.0.215:8500'
    relabel_configs:
      - source_labels: [__meta_consul_tags]
        regex: .*,bb-dns,.*
        action: keep
      - source_labels: [__meta_consul_tags]
        regex: .*,dns:([^,]+),.*
        replacement: '${1}'
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance

Im Prometheus Web-GUI sieht das dann so aus:

Die einzelnen Jobs haben mit Service Discovery und durch die relabel-Konfiguration die gewünschten Clients gefunden.

Auf dem entsprechenden Client kann man im syslog sehen, wie die einzelnen Probes ausgeführt werden.


Interessante Links, die mir geholfen haben:

Understanding and using the multi-target exporter pattern

Using Prometheus to Monitor Your VMs and Using Consul For Discovery

Prometheus: Discovering Services with Consul

Prometheus: Consul Service Discovery for blackbox and snmp exporter