Douze constructions

Une pile de surveillance qui surveille votre propre flotte

Prometheus, exportateurs et Alertmanager sur plusieurs sites, scrapés via un tunnel privé, avec des alertes qui se déclenchent avant qu'un disque ne se remplisse plutôt qu'après.

Ce que cela construit

Une petite instance qui récupère toutes les autres machines que vous possédez, via un tunnel privé, et vous envoie un courriel lorsque quelque chose est sur le point de casser. Métriques de nœud, sondes blackbox entre sites, règles d'alerte avec des seuils sensés, et une configuration Alertmanager qui regroupe les notifications au lieu de vous en envoyer quatre cents à trois heures du matin.

Il n'y a pas de tableau de bord dans cette construction. Les tableaux de bord sont agréables et ne sont pas de la surveillance ; un graphique que personne ne regarde n'a jamais réveillé personne. Ajoutez-en un plus tard si vous le voulez, par-dessus les mêmes données.

Avant de commencer

  • Un R-4 pour le moniteur. Cent nœuds à intervalles de quinze secondes représentent quelques centaines de milliers d'échantillons par minute, ce qu'il gère sans s'en apercevoir.
  • Placez-le ailleurs que votre parc. Tout moniteur partageant un bâtiment avec tout ce qu'il surveille reste admirablement silencieux précisément le jour où vous avez besoin qu'il crie. Si votre parc est européen, Toronto ou Singapour est l'endroit sensé pour cela.
  • Un tunnel vers chaque nœud surveillé, depuis le guide WireGuard. Les exportateurs exposent beaucoup de choses sur une machine et ne devraient se trouver nulle part près d'une interface publique.

1. Sur chaque nœud surveillé

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

Remplacez par l'adresse du tunnel de chaque nœud. Se lier au tunnel plutôt qu'à tout signifie que le pare-feu est une deuxième ligne de défense plutôt que la seule.

2. Sur le moniteur

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

Écrivez /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 découverte basée sur des fichiers plutôt qu'une liste statique vaut le répertoire supplémentaire. Ajouter un nœud devient un fichier, et le fichier peut être écrit par ce qui provisionne vos machines. /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 }

Ces étiquettes sont ce qui rend les alertes lisibles plus tard. Une alerte disant db in AMS-01 est exploitable ; une disant 10.7.0.12 vous envoie vers un tableur.

3. Des règles qui valent le coup

/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 est la règle qui justifie cette construction. Un seuil sur l'espace libre vous dit qu'un disque est plein ; une tendance de six heures extrapolée vers l'avant vous dit qu'il sera plein vers quatre heures cet après-midi, ce qui est un problème que vous pouvez encore résoudre calmement. Les alertes disque basées sur un pourcentage fixe sont soit bruyantes sur les petits volumes, soit inutiles sur les grands.

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 règle d'inhibition est la différence entre un message et quarante. Quand un nœud tombe, chaque avertissement concernant ce nœud est supprimé, parce que vous le savez déjà : le nœud est down.

Le regroupement par alertname et site signifie qu'un site entier perdant de l'électricité produit un seul courriel listant chaque machine, plutôt qu'un courriel par machine. Ce serveur de courrier est celui du guide courriel, et avoir votre chemin d'alerte qui dépend d'une infrastructure que vous surveillez aussi est un compromis connu ; un second récepteur pointant vers un webhook ailleurs est une assurance bon marché.

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

La rétention vaut la peine d'être définie délibérément. Quatre-vingt-dix jours de cent nœuds représentent quelques dizaines de gigaoctets :

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

Vérifiez-le

La syntaxe d'abord, parce qu'un fichier de règles avec une faute de frappe échoue silencieusement au chargement et vous le découvrez pendant l'incident :

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

Ensuite, confirmez que chaque cible est scrapée :

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

Chaque cible devrait rapporter up. Une rapportant down est soit une règle de pare-feu, soit un exportateur lié à la mauvaise adresse.

Maintenant le seul test qui prouve que toute la chaîne fonctionne, c'est de casser quelque chose exprès. Sur n'importe quel nœud surveillé :

systemctl stop prometheus-node-exporter

Trois minutes plus tard, l'alerte devrait être en attente, puis se déclencher. Regardez-la évoluer :

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

Environ une minute après le déclenchement, le courriel arrive. Si l'alerte se déclenche mais qu'aucun courriel n'apparaît, le problème est les identifiants smarthost, et journalctl -u prometheus-alertmanager le dira clairement. Redémarrez l'exportateur et confirmez que vous recevez aussi la notification de résolution, puisqu'un système d'alerte qui ne vous dit jamais que les choses s'améliorent vous entraîne à l'ignorer.

systemctl start prometheus-node-exporter

Ensuite

Ajoutez des sondes blackbox entre les sites, de chaque site vers chaque autre site, et vous obtenez une matrice de latence de votre propre parc qui est bien plus utile pendant un incident que n'importe quelle page de statut. La nôtre est à statut, et le looking glass répond à l'autre moitié de la question quand une route semble fausse.

Prêt quand vous l'êtes

Choisissez une ville. Choisissez une taille. Payez en crypto.

Aucun formulaire sur votre identité, pas d'attente d'approbation humaine, pas d'appel téléphonique pour vérifier quoi que ce soit. La facture est réglée et les identifiants arrivent dans votre boîte mail.