fix(metrics): дисковые тревоги в абсолютных ГБ + алерт на скорость утечки #3542

Merged
lekss361 merged 1 commit from fix/disk-alerts-absolute-thresholds into main 2026-09-17 12:49:43 +00:00
Showing only changes of commit a8d3499bdc - Show all commits

View file

@ -63,40 +63,85 @@ groups:
- name: host
interval: 60s
rules:
# Диск. На Beget уже был случай, когда занято 79 % и никто не смотрел;
# порог 85 % даёт запас на реакцию, а не сообщает о свершившемся факте.
# Диск. Инцидент 16.09: кэш архивов Forgejo ел 2 ГБ/ч на диске 145 ГБ
# (host=infra). Проценты на дисках разного размера значат разное —
# host=apps держит /-раздел ~910 ГБ, те же 85 % там это ещё ~135 ГБ
# запаса, а на infra (145 ГБ) — почти ничего. Порог переведён в
# АБСОЛЮТНЫЕ ГБ свободного места: он одинаково осмыслен на любом диске,
# потому что напрямую отвечает на вопрос «сколько времени есть до нуля
# при текущей скорости утечки», а не «какая доля занята».
#
# `mountpoint="/"` — намеренное сужение с прежнего «все fstype кроме
# tmpfs/overlay»: /boot и /boot/efi по обоим хостам меньше 1 ГБ
# целиком, с порогом 30/15 ГБ они бы горели ПОСТОЯННО (проверено живыми
# метриками 16.09 — infra:/boot/efi 98 МБ, apps:/boot 553 МБ). Данные
# приложения и Postgres лежат на "/", туда и целится алерт.
- alert: DiskSpaceLow
expr: |
(1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}
/ node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) > 0.85
node_filesystem_avail_bytes{fstype!~"tmpfs|overlay", mountpoint="/"}
/ 1073741824 < 30
for: 15m
labels:
severity: warning
annotations:
summary: "Диск занят больше 85 %"
description: "{{ $labels.host }} {{ $labels.mountpoint }}: занято {{ $value | humanizePercentage }}."
summary: "Свободно на диске меньше 30 ГБ"
description: "{{ $labels.host }} {{ $labels.mountpoint }}: свободно {{ printf \"%.1f\" $value }} ГБ."
- alert: DiskSpaceCritical
expr: |
(1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}
/ node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) > 0.93
node_filesystem_avail_bytes{fstype!~"tmpfs|overlay", mountpoint="/"}
/ 1073741824 < 15
for: 5m
labels:
severity: critical
annotations:
summary: "Диск почти кончился"
description: "{{ $labels.host }} {{ $labels.mountpoint }}: занято {{ $value | humanizePercentage }}. Postgres при заполнении диска останавливается."
summary: "Свободно на диске меньше 15 ГБ"
description: "{{ $labels.host }} {{ $labels.mountpoint }}: свободно {{ printf \"%.1f\" $value }} ГБ. Postgres при заполнении диска останавливается."
# Прогноз важнее порога: он ловит утечку до того, как она упрётся в стену.
# Скорость, а не уровень. Ловит именно ту утечку, что была 16.09: пока
# DiskSpaceLow/Critical ещё не сработали (места вагон), но оно тает
# быстрее ~1 ГБ/ч устойчиво — это уже течь, а не органический рост.
# `deriv()` — линейная регрессия по 15-минутному окну (не мгновенная
# разница двух точек, ту дёргает шум). Знак минус спереди и деление
# переносят результат из "Б/с, отрицательное при убыли" в "ГБ/ч,
# положительное когда тает" — чтобы $value в тексте читался нормально
# (не "-2.1 ГБ/ч"). `for: 30m` поверх 15-минутного окна регрессии
# требует НЕПРЕРЫВНОЙ убыли около часа, чтобы не будить на разовый
# скачок (бэкап, ротация логов).
- alert: DiskSpaceDepletingFast
expr: |
-deriv(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay", mountpoint="/"}[15m])
* 3600 / 1073741824 > 1
for: 30m
labels:
severity: warning
annotations:
summary: "Диск пустеет быстрее ГБ в час"
description: "{{ $labels.host }} {{ $labels.mountpoint }}: свободное место убывает на {{ printf \"%.1f\" $value }} ГБ/час устойчиво последние ~30 минут — независимо от того, сколько места осталось сейчас."
# Прогноз важнее порога: он ловит утечку до того, как она упрётся в
# стену — но роль другая, чем у DiskSpaceDepletingFast выше. Тот ловит
# БЫСТРУЮ (>1 ГБ/ч) утечку рано, за счёт короткого 15-минутного окна.
# Этот ловит УМЕРЕННУЮ утечку (может быть медленнее 1 ГБ/ч), которую
# короткое окно не поймает, но которая всё равно приведёт к нулю в
# течение суток при текущем уровне занятости — окно 6h усредняет шум
# ценой более позднего срабатывания. На одной и той же быстрой утечке
# оба правила могут сработать (сначала это, следом то) — это
# ЗАДУМАННАЯ эскалация двумя разными сигналами (скорость сейчас →
# подтверждённый тренд на сутки), а не дублирующее письмо: тексты и
# время срабатывания разные. DiskSpaceLow/Critical выше добавляют
# третий, независимый от скорости сигнал — «места мало» само по себе,
# даже если утечки нет и ничего не тает быстро.
- alert: DiskWillFillIn24h
expr: |
predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}[6h], 24*3600) < 0
(0 - predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay", mountpoint="/"}[6h], 24*3600))
/ 1073741824 > 0
for: 30m
labels:
severity: warning
annotations:
summary: "По текущему темпу диск кончится за сутки"
description: "{{ $labels.host }} {{ $labels.mountpoint }}: экстраполяция по последним 6 часам."
description: "{{ $labels.host }} {{ $labels.mountpoint }}: по экстраполяции последних 6 часов через сутки не хватит ~{{ printf \"%.1f\" $value }} ГБ."
- alert: MemoryPressure
expr: |