Тривога
повідомлення, яке система шле, коли потрібна людина
Що це таке
Тривога — це автоматичний сигнал про те, що умова, за якою стежить система, трималася достатньо довго, щоб заради неї варто було відірвати людину від справ. В українських командах часто кажуть просто «алерт», а тривогу, через яку будять чергового серед ночі, англійською називають page.
За цим словом стоять два різні об’єкти, і Prometheus розводить їх настільки чітко, що різницю легко помітити. Правило тривоги в Prometheus породжує тривоги, по одній на кожен окремий набір міток, для якого вираз повертає результат. Далі вони надходять до окремої програми, Alertmanager, а та перетворює їх на сповіщення: лист, повідомлення в чаті, дзвінок через сервіс чергувань. Сам проєкт прямо пише, що правила тривог самі по собі ще не є повноцінною системою сповіщень. Розрізняти ці дві речі доводиться тому, що їхня кількість розходиться. П’ятдесят тривог можуть прийти одним листом, одна тривога може нагадувати про себе кожні кілька годин, а тривога, якій вимкнули звук, до людей не доходить, хоча й далі спрацьовує.
Життєвий цикл у тривоги короткий. Поки вираз нічого не повертає, тривога неактивна. Щойно він уперше
дає результат, тривога переходить у стан очікування (pending) і лишається в ньому стільки, скільки
вимагає параметр for у правилі. Якщо наприкінці цього проміжку умова все ще виконується, тривога
спрацьовує (firing) і йде далі на доставку. Коли умова перестає виконуватися, тривога завершується
(resolved). Новіший параметр keep_firing_for утримує тривогу в стані спрацювання ще деякий час
після того, як умова зникла; документація пояснює його як захист від мерехтіння та хибних
повідомлень про те, що все вже гаразд. Крім того, Prometheus записує стани очікування й спрацювання
як часовий ряд ALERTS, тож до самих тривог можна робити запити й показувати їх на графіках.
Правило, яке чекає двадцять хвилин, перш ніж спрацювати, і ще десять, перш ніж відпустити, має такий вигляд:
groups:
- name: exports
rules:
- alert: ExportQueueStalled
expr: exports_waiting > 0 and rate(exports_done_total[15m]) == 0
for: 20m
keep_firing_for: 10m
labels:
severity: page
team: billing
annotations:
summary: "{{ $value }} exports queued and none finishing"
Мітки й анотації схожі на вигляд, але виконують різну роботу. Мітки входять до того, що робить
тривогу саме цією тривогою, і Alertmanager читає їх, щоб вирішити, куди її надіслати: severity: page може потрапити на телефон, а severity: ticket — у чергу заявок. Анотації несуть слова,
потрібні людині, коли повідомлення вже надійшло: короткий підсумок, довший опис, посилання на
інструкцію з першими кроками. Анотації можна складати з шаблонів, що підставляють мітки тривоги та
значення, яке її викликало, і саме тому підсумок у прикладі вище здатен назвати число.
Тривога й інцидент — різні поняття. Тривога повідомляє, що умова справдилася, а чи є те, що відбувається, інцидентом, вирішує людина.
Чому це важливо
Тривога — єдина частина моніторингу, яка не чекає, поки на неї подивляться. Метрика лежить у сховищі, дашборд висить на екрані, журнал чекає на пошуковий запит, а тривога вривається в чийсь вечір. Тож кожне правило тривоги — це невелика постійна заявка на чиюсь увагу, і вона справедлива лише тоді, коли людина може щось із цим зробити. Настанови Prometheus щодо тривог радять не будити людей, коли робити нічого, і тримати систему тривог нескладною.
Друге — звичайна арифметика. Одна несправність зазвичай зачіпає багато правил водночас. Якщо через
розділення мережі половина екземплярів сервісу втрачає зв’язок із базою даних, кожен екземпляр може
надіслати власну тривогу, і документація Alertmanager саме на цьому прикладі показує, як сотні
тривог стають одним сповіщенням. Alertmanager збирає разом тривоги зі спільними мітками,
переліченими в group_by, чекає group_wait (типово 30 секунд), щоб перше повідомлення вмістило
всю групу, надсилає оновлення для групи не частіше ніж раз на group_interval (5 хвилин) і повторює
повідомлення про тривогу, що досі спрацьовує, через repeat_interval (4 години). Пригнічення йде ще
далі й приглушує одні тривоги, поки спрацьовує інша, тож тривога про недоступність усього кластера
може заглушити тривоги окремих сервісів у ньому. Silence, як це називає Alertmanager, вимикає звук
для тривог із певними мітками на визначений час, зазвичай на період планових робіт.
Третє — кінець історії. Більшість отримувачів надсилає повідомлення, коли тривога завершується, але
для поштового отримувача параметр send_resolved типово має значення false. Команда, яка отримує
тривоги поштою, може побачити, як проблема почалася, і так і не дізнатися, коли вона скінчилася.
Як це виглядає на практиці
Тривоги на власному хості компанії влаштовано навпаки. Машина має 464 МБ пам’яті й тримає сервер git-репозиторіїв, базу даних і вебсервер, а найімовірніше її погубить вичерпана пам’ять або переповнений диск, і обидва збої настають мовчки. Тривога, яка розраховує, що хост сам повідомить про свою відмову, тут марна, бо говорити довелося б саме тому хостові, який відмовляє. Тому таймер на хості пінгує зовнішній сервіс лише тоді, коли і пам’ять, і диск у нормі, раз на чверть години з невеликим випадковим зсувом, а зовнішній сервіс надсилає тривогу, коли пінги перестають надходити. Хоч би як зламався хост, зокрема через утрачену мережу чи завантаження, що зависло, усе закінчується тим самим пропущеним пінгом, і саме на це розрахована схема. Сторінка називає й межу такого рішення: перевірка доводить, що машина здорова, але про те, чи відкривається сайт, вона нічого не каже.
Та сама інверсія захищає завдання за розкладом. Зашифроване резервне копіювання на інший хост запускається таймером і пінгує свій перемикач лише тоді, коли запуск вдався, тож невдалий запуск лишає по собі прогалину в низці пінгів, і цю прогалину помічає щось поза машиною, а не рядок у журналі на ній самій.
Інвертовані тривоги мають власний спосіб зламатися, і він проявився, коли платформа мала вирости з одного хоста до двох. Якби обидва хости ділили один перемикач, це послабило б саме ту систему тривог, яку мали розширити: поки пінгує хоча б один хост, перевірка лишається зеленою для обох, навіть коли другий уже мертвий. Кожен перемикач став окремим значенням для свого хоста, а поля перемикача для наявного хоста свідомо залишили порожніми, тож конфігурація показує, що з’єднання передбачене, а значення ще треба вписати.
Де виникають проблеми
Виміряне значення потрапляє в мітку. Оскільки мітки визначають тривогу, мітка з поточним числом перетворює кожну зміну цього числа на нову тривогу й завершує попередню. Отримувач бачить потік пар «спрацювала — завершилася» через одну проблему. Залишайте мітки для ідентичності й маршрутизації, а числа виносьте в анотації.
Тривога мерехтить. Умова, що коливається біля порогу, спрацьовує, завершується й знову
спрацьовує кожні кілька хвилин, і кожне повідомлення про завершення каже читачеві неправду. Подовжте
for, щоб короткий сплеск минав раніше, ніж про нього хтось дізнається, і додайте
keep_firing_for, щоб коротке падіння нижче порогу не закривало тривогу.
Silence живе довше за свою причину. Хтось вимикає звук тривоги на час робіт із надто широкою умовою та щедрим часом завершення, і справжній збій наступного тижня надходить беззвучно. Обмежуйте silence так вузько, як дозволяє робота, ставте кінець близько до того часу, коли роботу мають завершити, і пишіть у полі коментаря, хто його створив і навіщо.
Широкий маршрут поглинає вужчі. Alertmanager обходить дерево маршрутизації по черзі і, якщо
маршрут не має continue: true, зупиняється на першому дочірньому маршруті, що підходить. Загальний
маршрут, поставлений над маршрутом окремої команди, забирає тривоги цієї команди з собою. Ставте
найвужчі маршрути першими й перевіряйте дерево на прикладах міток, перш ніж на нього покладатися.
Усе стає терміновим. Диск, заповнений на 70%, сертифікат, що спливає наступного місяця, і платіжний сервіс, який повертає помилки, дзвонять на той самий телефон, і незабаром на телефон перестають зважати. Будіть людей лише через умови, які вимагають дій негайно, решту надсилайте в чергу заявок чи щоденне зведення, а правило, яке місяцями спрацьовує без жодної реакції, видаляйте.
Що почитати далі
- Alerting overview — як правила тривог у Prometheus і Alertmanager ділять між собою роботу та з яких кроків складається їхнє налаштування.
- Alerting rules —
синтаксис правил, зокрема
for,keep_firing_for, мітки, анотації та шаблони. - Alertmanager — групування, пригнічення, silences і робота кількох екземплярів Alertmanager для високої доступності.
- Alertmanager configuration — дерево
маршрутизації, таймери групування, правила пригнічення й налаштування кожного отримувача, серед
них
send_resolved. - Alerting practices — власні поради проєкту про те, заради чого варто будити людей, а що має йти іншими каналами.