Зазвичай про проблему дізнаються від клієнта: «сайт не відкривається». Потім з’ясовується, що диск на сервері бази заповнився ще вчора, реплікація відстала на годину, а лог із помилкою лежав на третій машині, куди ніхто не заходив. Дані про все це були. Просто їх ніхто не збирав в одне місце.

Буває й навпаки: моніторинг є, але це п’ять різних панелей із п’ятьма паролями, а Telegram-чат зі сповіщеннями давно на беззвучному, бо туди сиплеться по сотні повідомлень на день. Такий моніторинг лише створює враження, що все під контролем.

Ми ставимо компактний стек, який відповідає на три питання: що відбувається всередині серверів, що пишуть сервіси в логи і чи бачать вас користувачі ззовні. Один вхід, один логін, алерти тільки про те, що справді вимагає реакції.

Що ми робимо

  • Prometheus збирає метрики з усього, що у вас працює. На кожен сервер, VM і LXC ставимо node_exporter: диски, пам’ять, навантаження, мережа, стан systemd.
  • pve-exporter дивиться на Proxmox з боку гіпервізора: статус і споживання всіх VM та контейнерів, включно з вимкненими. Ходить через API з токеном тільки на читання.
  • Бази даних: експортери для PostgreSQL і MariaDB, плюс вбудовані метрики Patroni, etcd, HAProxy і ProxySQL. Видно, хто зараз primary, на скільки відстають репліки, скільки вузлів у Galera синхронізовано.
  • Alertmanager групує алерти й розсилає їх у Telegram, на пошту або в робочий чат.
  • Loki з агентом Promtail або Alloy збирає логи з усіх машин. Шукаєте в тій самій Grafana, поруч із графіками.
  • Uptime Kuma перевіряє сайти, API і порти ззовні, стежить за терміном TLS-сертифікатів і дає публічну status page для ваших клієнтів.
  • Grafana показує все це на дашбордах, зібраних під вашу інфраструктуру.
  • Traefik стоїть попереду як reverse proxy і сам отримує сертифікати Let’s Encrypt.
  • Authentik дає один логін для Grafana, Uptime Kuma і внутрішніх панелей, з 2FA. Сервіси без власної автентифікації закриваємо через forwardAuth у Traefik.

Розгортаємо на docker compose або в окремих LXC. Конфіги, правила алертів і дашборди лежать у git, тож стек можна відтворити з нуля.

Як зробити, щоб моніторинг читали

Головний ризик тут не технічний. Якщо алерт приходить, а реагувати не треба, людина за тиждень перестає їх відкривати. Тому кожне правило ми перевіряємо одним питанням: що треба зробити, коли воно спрацює? Якщо відповіді немає, це не алерт, а графік на дашборді.

На практиці це означає кілька речей. Алерт має умову for:, щоб короткий сплеск не будив нікого вночі. Заповнення диска рахуємо за трендом, а не за порогом «90%». Сервіси, яких уже немає, прибираємо з перевірок, інакше вони дають вічний червоний статус і привчають його ігнорувати. Приблизно так виглядає правило:

groups:
  - name: infra
    rules:
      - alert: DiskWillFillIn24h
        expr: predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}[6h], 24*3600) < 0
        for: 30m
        labels: {severity: warning}
        annotations:
          summary: "{{ $labels.host }}: {{ $labels.mountpoint }} заповниться за добу"
      - alert: GaleraNodeLost
        expr: mysql_global_status_wsrep_cluster_size < 3
        for: 2m
        labels: {severity: critical}

Дашборди робимо під конкретні питання, а не «все про все». Для щоденного погляду — один екран: гіпервізор, сховища, яка віртуалка чи контейнер їсть найбільше ресурсів, у кого закінчується місце, хто без бекапу. Для кластерів баз — інша логіка: роль вузла чи стан Galera показуємо смугою на часовій шкалі. Так failover видно одразу: смуга просто переїжджає на інший вузол. Великі дашборди генеруємо скриптом і після кожної правки перевіряємо, що жодна панель не порожня.

Є кілька нюансів, про які варто знати заздалегідь. node_exporter у LXC частково бачить метрики хоста, бо ядро спільне, тому реальне споживання контейнера беремо з pve-exporter. У Prometheus підписуємо машини іменами, а не IP, інакше в Grafana доведеться пам’ятати адреси.

Компроміси і коли це не підходить

Loki — не Elasticsearch. Він індексує лише мітки (хост, сервіс, рівень), а текст переглядає під час запиту. Тому він легкий і дешевий у зберіганні, але повнотекстовий пошук по місяцях логів буде повільним. Якщо вам потрібна аналітика по логах або вимоги аудиту з довгим зберіганням, краще підійде ELK або OpenSearch, і це вже інший масштаб заліза.

Моніторинг має жити окремо від того, що він моніторить. Якщо Prometheus стоїть на тому ж сервері, що й продакшн, то при падінні сервера ви не отримаєте навіть алерту про це. Мінімум — окрема VM або LXC. Uptime Kuma краще винести взагалі в іншу локацію чи до іншого провайдера: це ваш погляд очима користувача. Окремо налаштовуємо «сторожовий» алерт, який має приходити завжди: якщо він замовк, зламався сам ланцюжок сповіщень.

Authentik стає точкою входу. Якщо він ляже, у панелі не зайти. Тому робимо бекап його бази перед кожним оновленням, а після оновлення перевіряємо не лише «чи відкривається сторінка», а й куди веде редірект входу. Аварійний доступ до серверів лишається окремим і від SSO не залежить.

Для одного маленького VPS увесь стек надлишковий: там вистачить Uptime Kuma і пари алертів. Сенс він має від кількох серверів або там, де є бази з реплікацією.

Що ви отримуєте

  • Робочий стек Prometheus, Alertmanager, Grafana, Loki й Uptime Kuma за Traefik з HTTPS.
  • Один логін з 2FA для всіх панелей, облікові записи для вашої команди.
  • Метрики всіх серверів, VM/LXC і баз даних, включно з реплікацією, Patroni чи Galera.
  • Дашборди під вашу інфраструктуру, а не імпортовані «на все».
  • Алерти в Telegram, на пошту чи в чат, з описом, що означає кожен і що робити.
  • Status page для ваших клієнтів, якщо вона потрібна.
  • Увесь стек у git: конфіги, правила, дашборди, плюс документацію, як додати новий сервер чи перевірку.

Якщо у вас уже є кілька серверів і ви дізнаєтесь про проблеми від клієнтів, напишіть нам. Розкажіть, що у вас працює і де, а ми запропонуємо, як це спостерігати з одного місця.