Dodici build

Uno stack di monitoraggio che osserva la propria flotta

Prometheus, exporter e Alertmanager su più siti, raccolti tramite un tunnel privato, con avvisi che scattano prima che un disco si riempia piuttosto che dopo.

Cosa si costruisce

Una piccola istanza che analizza ogni altra macchina che possiedi, attraverso un tunnel privato, e ti invia una mail quando qualcosa sta per rompersi. Metriche dei nodi, sonde blackbox tra i siti, regole di allerta con soglie sensate e una configurazione di Alertmanager che raggruppa le notifiche invece di inviartene quattrocento alle tre di notte.

Non c'è alcuna dashboard in questa build. Le dashboard sono piacevoli e non sono monitoraggio; un grafico che nessuno guarda non ha mai svegliato nessuno. Aggiungine una dopo se vuoi, sopra gli stessi dati.

Prima di iniziare

  • Un R-4 per il monitor. Cento nodi a intervalli di quindici secondi sono qualche centinaio di migliaia di campioni al minuto, che questo gestisce senza accorgersene.
  • Mettilo in un posto dove la tua flotta non è. Qualsiasi monitor che condivide un edificio con tutto ciò che osserva rimane ammirevolmente silenzioso proprio nel giorno in cui hai bisogno che gridi. Se il tuo parco macchine è europeo, Toronto o Singapore sono il posto sensato per lui.
  • Un tunnel verso ogni nodo monitorato, dalla guida WireGuard. Gli exporter espongono molte informazioni su una macchina e non dovrebbero stare vicino a un'interfaccia pubblica.

1. Su ogni nodo monitorato

apt update && apt install -y prometheus-node-exporter
mkdir -p /etc/systemd/system/prometheus-node-exporter.service.d
cat > /etc/systemd/system/prometheus-node-exporter.service.d/bind.conf <<EOF
[Service]
Environment=ARGS=--web.listen-address=10.7.0.11:9100 --collector.systemd --collector.processes
EOF
systemctl daemon-reload && systemctl restart prometheus-node-exporter
ss -ltn | grep 9100

Sostituisci con l'indirizzo del tunnel di ciascun nodo. Legare al tunnel anziché a tutto significa che il firewall è una seconda linea di difesa piuttosto che l'unica.

2. Sul monitor

apt install -y prometheus prometheus-alertmanager prometheus-blackbox-exporter

Scrivi /etc/prometheus/prometheus.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    fleet: main

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['127.0.0.1:9093']

rule_files:
  - /etc/prometheus/rules/*.yml

scrape_configs:
  - job_name: nodes
    file_sd_configs:
      - files: ['/etc/prometheus/targets/*.yml']

  - job_name: probe_https
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
          - https://app.example.com/health
          - https://cloud.example.com/status.php
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: 127.0.0.1:9115

La scoperta basata su file piuttosto che una lista statica vale la directory extra. Aggiungere un nodo diventa un file, e il file può essere scritto da qualunque cosa provveda alle tue macchine. /etc/prometheus/targets/ams.yml:

- targets: ['10.7.0.11:9100']
  labels: { site: AMS-01, role: web }
- targets: ['10.7.0.12:9100']
  labels: { site: AMS-01, role: db }

Quelle etichette sono ciò che rende leggibili le allerte in seguito. Un'allerta che dice db in AMS-01 è attuabile; una che dice 10.7.0.12 ti manda a un foglio di calcolo.

3. Regole che valgono la pena

/etc/prometheus/rules/fleet.yml:

groups:
  - name: fleet
    rules:
      - alert: NodeDown
        expr: up{job="nodes"} == 0
        for: 3m
        labels: { severity: page }
        annotations:
          summary: "{{ $labels.instance }} in {{ $labels.site }} stopped answering"

      - alert: DiskFillingUp
        expr: predict_linear(node_filesystem_avail_bytes{fstype=~"ext4|xfs|zfs|btrfs"}[6h], 4*3600) < 0
        for: 30m
        labels: { severity: page }
        annotations:
          summary: "{{ $labels.instance }} fills {{ $labels.mountpoint }} within four hours"

      - alert: MemoryPressure
        expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes < 0.10
        for: 15m
        labels: { severity: warn }

      - alert: IOWaitHigh
        expr: avg by (instance) (rate(node_cpu_seconds_total{mode="iowait"}[5m])) > 0.25
        for: 20m
        labels: { severity: warn }

      - alert: CertificateExpiring
        expr: probe_ssl_earliest_cert_expiry - time() < 10*86400
        labels: { severity: warn }

      - alert: ProbeFailing
        expr: probe_success == 0
        for: 5m
        labels: { severity: page }

predict_linear è la regola che rende questa build utile. Una soglia sullo spazio libero ti dice che un disco è pieno; un trend di sei ore estrapolato in avanti ti dice che sarà pieno intorno alle quattro di questo pomeriggio, che è un problema che puoi ancora risolvere con calma. Le allerte sui dischi basate su una percentuale fissa sono o rumorose su volumi piccoli o inutili su quelli grandi.

4. Alertmanager

route:
  receiver: mail
  group_by: [alertname, site]
  group_wait: 45s
  group_interval: 5m
  repeat_interval: 12h
  routes:
    - matchers: [severity="warn"]
      repeat_interval: 72h

inhibit_rules:
  - source_matchers: [alertname="NodeDown"]
    target_matchers: [severity="warn"]
    equal: [instance]

receivers:
  - name: mail
    email_configs:
      - to: [email protected]
        from: [email protected]
        smarthost: mail.example.com:587
        auth_username: [email protected]
        auth_password: "<the mailbox password>"

La regola di inibizione è la differenza tra un messaggio e quaranta. Quando un nodo va giù, ogni avviso su quel nodo viene soppresso, perché lo sai già: il nodo è giù.

Raggruppare per alertname e site significa che un intero sito che perde corrente produce una sola mail che elenca ogni macchina, piuttosto che una mail per macchina. Quel server di posta è quello della guida mail, e avere il tuo percorso di allerta che dipende da infrastruttura che monitori anche tu è un compromesso noto; un secondo ricevitore che punta a un webhook altrove è un'assicurazione economica.

systemctl enable --now prometheus prometheus-alertmanager prometheus-blackbox-exporter

La conservazione vale la pena impostarla deliberatamente. Novanta giorni di cento nodi sono qualche decina di gigabyte:

echo 'ARGS="--storage.tsdb.retention.time=90d --storage.tsdb.retention.size=40GB"' > /etc/default/prometheus
systemctl restart prometheus

Verifica

Prima la sintassi, perché un file di regole con un refuso fallisce silenziosamente al caricamento e lo scopri durante l'incidente:

promtool check config /etc/prometheus/prometheus.yml
promtool check rules /etc/prometheus/rules/fleet.yml

Poi conferma che ogni target viene analizzato:

curl -s http://127.0.0.1:9090/api/v1/targets | grep -o "\"health\":\"[a-z]*\"" | sort | uniq -c

Ogni target dovrebbe riportare up. Uno che riporta down è o una regola del firewall o un exporter legato all'indirizzo sbagliato.

Ora l'unico test che dimostra che l'intera catena funziona, che è rompere qualcosa di proposito. Su qualsiasi nodo monitorato:

systemctl stop prometheus-node-exporter

Tre minuti dopo l'allerta dovrebbe essere in sospeso, poi in attivazione. Guarda il suo avanzamento:

curl -s http://127.0.0.1:9090/api/v1/alerts | head -c 400
amtool --alertmanager.url=http://127.0.0.1:9093 alert query

Entro circa un minuto dall'attivazione, arriva la mail. Se l'allerta si attiva ma non arriva nessuna mail, il problema sono le credenziali dello smarthost, e journalctl -u prometheus-alertmanager lo dirà chiaramente. Riavvia l'exporter e conferma di ricevere anche la notifica di risoluzione, poiché un sistema di allerta che non ti dice mai che le cose sono migliorate ti addestra a ignorarlo.

systemctl start prometheus-node-exporter

Dopo

Aggiungi sonde blackbox tra i siti, da ogni sito a ogni altro sito, e ottieni una matrice di latenza del tuo stesso parco macchine che è molto più utile durante un incidente di qualsiasi pagina di stato. La nostra è su status, e il looking glass risponde all'altra metà della domanda quando una rotta sembra sbagliata.

Pronto quando lo sei

Scegli una città. Scegli una dimensione. Paga in criptovaluta.

Nessun modulo su chi sei, nessuna attesa per l'approvazione di una persona, nessuna chiamata per verificare nulla. La fattura viene saldata e le credenziali arrivano nella tua casella di posta.