201 lines
11 KiB
YAML
201 lines
11 KiB
YAML
groups:
|
||
- name: host
|
||
rules:
|
||
- alert: TargetDown
|
||
expr: up == 0
|
||
for: 2m
|
||
labels: {severity: critical}
|
||
annotations:
|
||
summary: "Таргет {{ $labels.job }} на {{ $labels.instance }} недоступен"
|
||
|
||
- alert: HostHighCPU
|
||
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
|
||
for: 10m
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "Высокий CPU на {{ $labels.instance }}: {{ printf \"%.0f\" $value }}%"
|
||
|
||
- alert: HostLowMemory
|
||
expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 < 10
|
||
for: 5m
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "Мало памяти на {{ $labels.instance }}: доступно {{ printf \"%.0f\" $value }}%"
|
||
|
||
- alert: HostDiskLow
|
||
expr: node_filesystem_avail_bytes{fstype!~"tmpfs|overlay|squashfs"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay|squashfs"} * 100 < 15
|
||
for: 5m
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "Кончается диск на {{ $labels.instance }} ({{ $labels.mountpoint }}): свободно {{ printf \"%.0f\" $value }}%"
|
||
|
||
- alert: HostDiskCritical
|
||
expr: node_filesystem_avail_bytes{fstype!~"tmpfs|overlay|squashfs"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay|squashfs"} * 100 < 5
|
||
for: 5m
|
||
labels: {severity: critical}
|
||
annotations:
|
||
summary: "КРИТИЧНО: диск почти полон на {{ $labels.instance }} ({{ $labels.mountpoint }}): свободно {{ printf \"%.0f\" $value }}%"
|
||
|
||
# Метрики от rpi приходят через pushgateway (SSH-пуш, см. servers/rpi.md).
|
||
# push_time_seconds — когда группа последний раз обновлялась.
|
||
# SMART отправляется каждые 15 минут. Итог backup_* — только после прогона;
|
||
# свежесть бэкапов проверяется BackupStale/BackupNeverReported по расписанию.
|
||
- name: rpi
|
||
rules:
|
||
- alert: PushMetricsStale
|
||
expr: time() - push_time_seconds{job="smart"} > 3 * 3600
|
||
for: 10m
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "{{ $labels.instance }}: метрики {{ $labels.job }} не приходят {{ $value | humanizeDuration }} — хост/пуш лежит"
|
||
|
||
- alert: SmartHealthFailed
|
||
expr: smart_health_passed == 0
|
||
labels: {severity: critical}
|
||
annotations:
|
||
summary: "{{ $labels.instance }}: SMART FAILED на диске {{ $labels.model }} ({{ $labels.serial }}) — менять диск"
|
||
|
||
- alert: SmartBadSectors
|
||
expr: smart_attribute_raw{id=~"5|197|198"} > 0
|
||
labels: {severity: critical}
|
||
annotations:
|
||
summary: "{{ $labels.instance }}: {{ $labels.name }} = {{ $value }} на {{ $labels.model }} ({{ $labels.serial }}) — диск начал сыпаться"
|
||
|
||
- alert: SmartBadSectorsGrowing
|
||
expr: increase(smart_attribute_raw{id=~"5|197|198"}[1d]) > 0
|
||
labels: {severity: critical}
|
||
annotations:
|
||
summary: "{{ $labels.instance }}: {{ $labels.name }} растёт на {{ $labels.model }} — срочно вторую копию"
|
||
|
||
- alert: SmartUdmaCrcErrors
|
||
expr: increase(smart_attribute_raw{id="199"}[1d]) > 0
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "{{ $labels.instance }}: CRC-ошибки на {{ $labels.model }} — кабель/USB/питание"
|
||
|
||
- alert: SmartSelftestFailed
|
||
expr: smart_selftest_last_passed == 0
|
||
labels: {severity: critical}
|
||
annotations:
|
||
summary: "{{ $labels.instance }}: самотест SMART провален на {{ $labels.model }} ({{ $labels.serial }})"
|
||
|
||
- alert: SmartTemperatureHigh
|
||
expr: smart_temperature_celsius > 55
|
||
for: 15m
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "{{ $labels.instance }}: диск {{ $labels.model }} греется: {{ $value }}°C"
|
||
|
||
- alert: BackupFailed
|
||
expr: backup_last_exit_code != 0
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "{{ $labels.instance }}: {{ $labels.job }} завершился с кодом {{ $value }} — см. journalctl на хосте"
|
||
|
||
# sync каждые 4ч → 12ч = три пропуска подряд; verify раз в неделю → 8 дней; бэкап серверов ежедневно → 26ч; копия на роутер ежедневно → 30ч (первичная ~13ч)
|
||
- alert: BackupStale
|
||
expr: |
|
||
(time() - backup_last_success_timestamp{job="backup_onedrive"} > 12 * 3600)
|
||
or (time() - backup_last_success_timestamp{job="backup_onedrive_verify"} > 8 * 86400)
|
||
or (time() - backup_last_success_timestamp{job="backup_servers"} > 26 * 3600)
|
||
or (time() - backup_last_success_timestamp{job="backup_router"} > 30 * 3600)
|
||
or (time() - backup_last_success_timestamp{job="backup_vault"} > 3 * 3600)
|
||
or (time() - backup_last_success_timestamp{job="backup_router_sample"} > 35 * 86400)
|
||
for: 10m
|
||
labels: {severity: critical}
|
||
annotations:
|
||
summary: "{{ $labels.instance }}: {{ $labels.job }} не было успешного прогона {{ $value | humanizeDuration }}"
|
||
|
||
# /mnt/backup (HDD 4 ТБ) и /mnt/router (1 ТБ диск в роутере) — заполнение
|
||
- alert: BackupDiskFull
|
||
expr: 1 - backup_disk_avail_bytes / backup_disk_size_bytes > 0.9
|
||
for: 15m
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "{{ $labels.instance }}: диск бэкапа {{ $labels.mountpoint }} заполнен на {{ $value | humanizePercentage }}"
|
||
|
||
- alert: RouterDiskMountDown
|
||
expr: router_mount_up == 0
|
||
for: 30m
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "{{ $labels.instance }}: диск в роутере (/mnt/router, SFTP) недоступен 30+ мин — вторая копия бэкапа не пишется"
|
||
|
||
# BackupStale видит только существующие серии: если задача ни разу не отчиталась
|
||
# (таймер сломан, первый прогон упал до хука) — серии нет, и он молчит. Ловим отсутствие.
|
||
- alert: BackupNeverReported
|
||
expr: |
|
||
absent(backup_last_success_timestamp{instance="rpi",job="backup_onedrive"})
|
||
for: 12h
|
||
labels: {severity: critical, instance: rpi, job: backup_onedrive}
|
||
annotations:
|
||
summary: "rpi: синхронизация OneDrive ни разу не отчиталась об успехе за 12+ ч — проверь onedrive-backup"
|
||
- alert: BackupNeverReported
|
||
expr: absent(backup_last_success_timestamp{instance="rpi",job="backup_servers"})
|
||
for: 26h
|
||
labels: {severity: critical, instance: rpi, job: backup_servers}
|
||
annotations:
|
||
summary: "rpi: бэкап серверов fr1/ru1 не отчитывался 26+ ч — проверь servers-backup"
|
||
- alert: BackupNeverReported
|
||
expr: absent(backup_last_success_timestamp{instance="rpi",job="backup_router"})
|
||
for: 30h
|
||
labels: {severity: critical, instance: rpi, job: backup_router}
|
||
annotations:
|
||
summary: "rpi: копия на диск роутера не отчитывалась 30+ ч — проверь router-backup"
|
||
- alert: BackupNeverReported
|
||
expr: absent(backup_last_success_timestamp{instance="rpi",job="backup_onedrive_verify"})
|
||
for: 8d
|
||
labels: {severity: warning, instance: rpi, job: backup_onedrive_verify}
|
||
annotations:
|
||
summary: "rpi: проверка целостности OneDrive не отчитывалась 8+ дней — проверь onedrive-verify"
|
||
- alert: PushMetricsStale
|
||
expr: absent(push_time_seconds{instance="rpi",job="smart"})
|
||
for: 1h
|
||
labels: {severity: warning, instance: rpi, job: smart}
|
||
annotations:
|
||
summary: "rpi: метрики SMART в pushgateway отсутствуют 1+ ч — малина/пуш лежат или pushgateway потерял данные"
|
||
- alert: BackupNeverReported
|
||
expr: absent(backup_last_success_timestamp{instance="rpi",job="backup_router_sample"})
|
||
for: 35d
|
||
labels: {severity: warning, instance: rpi, job: backup_router_sample}
|
||
annotations:
|
||
summary: "rpi: ежемесячная перечитка файлов с диска роутера не отчитывалась 35+ дней — проверь router-sample"
|
||
|
||
# Домашняя сеть: роутер Huawei HG8245X6 (ONT Cyta), сторож router-watch на rpi раз в 5 мин.
|
||
# По отдельным устройствам прошивка трафик не считает — только по интерфейсам (wan, lan*, wifi-*).
|
||
- name: home-network
|
||
rules:
|
||
- alert: RouterWatchStale
|
||
expr: time() - push_time_seconds{job="router"} > 20 * 60
|
||
for: 10m
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "rpi: сторож роутера не присылал данных {{ $value | humanizeDuration }} — router-watch или вход на роутер сломан"
|
||
|
||
# всплеск = скорость за 15 мин в 4+ раза выше средней за неделю И выше абсолютного порога
|
||
- alert: RouterDownloadSpike
|
||
expr: |
|
||
rate(router_iface_bytes_total{iface="wan",dir="rx"}[15m]) > 5e6
|
||
and rate(router_iface_bytes_total{iface="wan",dir="rx"}[15m])
|
||
> 4 * avg_over_time(rate(router_iface_bytes_total{iface="wan",dir="rx"}[1h])[7d:1h])
|
||
for: 30m
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "Дом: необычно большая загрузка из интернета — {{ $value | humanize1024 }}Б/с 30+ мин. Кто качает: `router traffic --live` (по портам/Wi-Fi). Сама малина качает OneDrive/бэкапы — сверь с их расписанием."
|
||
|
||
- alert: RouterUploadSpike
|
||
expr: |
|
||
rate(router_iface_bytes_total{iface="wan",dir="tx"}[15m]) > 1e6
|
||
and rate(router_iface_bytes_total{iface="wan",dir="tx"}[15m])
|
||
> 4 * avg_over_time(rate(router_iface_bytes_total{iface="wan",dir="tx"}[1h])[7d:1h])
|
||
for: 30m
|
||
labels: {severity: warning}
|
||
annotations:
|
||
summary: "Дом: необычно большая ОТДАЧА в интернет — {{ $value | humanize1024 }}Б/с 30+ мин (облачная синхронизация, торрент или что-то подозрительное). Кто: `router traffic --live`."
|
||
- alert: BackupNeverReported
|
||
expr: absent(backup_last_success_timestamp{instance="rpi",job="backup_vault"})
|
||
for: 3h
|
||
labels: {severity: warning, instance: rpi, job: backup_vault}
|
||
annotations:
|
||
summary: "rpi: архив Obsidian-vault в gitea не отчитывался 3+ ч — проверь vault-archive / obsidian-sync"
|