Двенадцать сборок

Мониторинговый стек для наблюдения за собственным парком

Prometheus, экспортеры и Alertmanager на нескольких площадках, опрашиваемые по частному туннелю, с алертами, которые срабатывают до заполнения диска, а не после.

Что это даёт

Один небольшой инстанс, который опрашивает все остальные ваши машины по приватному туннелю и отправляет вам почту, когда что-то вот-вот сломается. Метрики узлов, blackbox-проверки между площадками, правила алертов с разумными порогами и конфигурация Alertmanager, которая группирует уведомления, а не шлёт их вам четыреста штук в три часа ночи.

В этой сборке нет дашборда. Дашборды приятны, но это не мониторинг; график, на который никто не смотрит, никогда никого не разбудил. Добавите позже, если захотите, поверх тех же данных.

Перед началом

  • R-4 для монитора. Сто узлов с интервалом в пятнадцать секунд — это несколько сотен тысяч сэмплов в минуту, с чем эта машина справляется без проблем.
  • Разместите его не там, где находится ваш парк машин. Любой монитор, живущий в одном здании со всем, за чем он следит, хранит впечатляющее молчание именно в тот день, когда вам нужно, чтобы он кричал. Если ваша инфраструктура в Европе, разумное место для него — Торонто или Сингапур.
  • Туннель до каждого отслеживаемого узла, по руководству по WireGuard. Экспортёры раскрывают много информации о машине, и им не место рядом с публичным интерфейсом.

1. На каждом отслеживаемом узле

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

Подставьте собственный туннельный адрес каждого узла. Привязка к туннелю, а не ко всему подряд, означает, что файрвол — это вторая линия обороны, а не единственная.

2. На мониторе

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

Запишите /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

Обнаружение на основе файлов, а не статический список, стоит дополнительной директории. Добавление узла сводится к одному файлу, и этот файл может быть создан тем, что разворачивает ваши машины. /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 }

Именно эти метки позже делают алерты читабельными. Алерт db in AMS-01 — это то, на что можно среагировать; а 10.7.0.12 отправляет вас к электронной таблице.

3. Правила, которые стоит иметь

/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 — это правило, которое оправдывает эту сборку. Порог по свободному месту сообщает вам, что диск полон; а экстраполяция тренда за шесть часов говорит вам, что он заполнится примерно к четырём часам дня — это проблема, которую вы можете спокойно решить. Алерты по диску на основе фиксированного процента либо шумят на маленьких томах, либо бесполезны на больших.

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>"

Правило inhibit — это разница между одним сообщением и сорока. Когда узел падает, все предупреждения об этом узле подавляются, потому что вы уже знаете: узел упал.

Группировка по alertname и site означает, что при отключении всей площадки вы получаете одно письмо со списком всех машин, а не по одному письму на машину. Этот почтовый сервер — тот, что из руководства по почте, и зависимость пути алертинга от инфраструктуры, которую вы тоже мониторите, — известный компромисс; второй получатель на webhook где-то ещё — дешёвая страховка.

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

Хранение стоит настроить осознанно. Девяносто дней для сотни узлов — это несколько десятков гигабайт:

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

Проверка

Сначала синтаксис, потому что файл правил с опечаткой молча не загрузится, и вы узнаете об этом во время инцидента:

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

Затем убедитесь, что все цели опрашиваются:

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

Каждая цель должна сообщать up. Если какая-то сообщает down, значит либо правило файрвола, либо экспортёр привязан не к тому адресу.

Теперь единственный тест, который доказывает, что вся цепочка работает, — это намеренно что-то сломать. На любом отслеживаемом узле:

systemctl stop prometheus-node-exporter

Через три минуты алерт должен быть в состоянии pending, затем firing. Следите за этим переходом:

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

В течение примерно минуты после срабатывания приходит почта. Если алерт сработал, а письма нет, проблема в учётных данных smarthost'а, и journalctl -u prometheus-alertmanager прямо об этом скажет. Запустите экспортёр снова и убедитесь, что вы также получили уведомление о разрешении, потому что система алертинга, которая никогда не сообщает об улучшении, приучает игнорировать её.

systemctl start prometheus-node-exporter

После

Добавьте blackbox-проверки между площадками, с каждой площадки на каждую другую, и вы получите матрицу задержек вашей собственной инфраструктуры, которая гораздо полезнее во время инцидента, чем любая страница статуса. Наша — на статусе, а looking glass отвечает на вторую половину вопроса, когда маршрут выглядит неверным.

Готовы, когда вы готовы

Выберите город. Выберите размер. Оплатите монетой.

Никаких форм о том, кто вы, никакого ожидания одобрения человеком, никаких звонков для проверки. Счёт оплачен — и учётные данные приходят на почту.