fix(alerts): a missing series must not silence the backup alerts
Verification on CFGMON showed RestoreDrillStale could never fire: restore-drill has no last_schedule_time series until its first scheduled run (a manually triggered job does not set it), and an expression over a missing series yields nothing. BackupNotRunning shares the flaw — deleting a CronJob removes the very series the alert reads, so it goes quiet instead of firing. Fall back to kube_cronjob_created, but aggregate with max by(namespace, cronjob): 'or' matches including __name__, so a bare fallback would return BOTH series and the never-updating created timestamp would fire permanently once the window elapsed. Add BackupCronJobMissing so a vanished CronJob is itself the alert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -104,8 +104,14 @@ groups:
|
|||||||
|
|
||||||
# Der CronJob plant gar nicht mehr (ausgesetzt, geloescht, Cluster-Problem).
|
# Der CronJob plant gar nicht mehr (ausgesetzt, geloescht, Cluster-Problem).
|
||||||
# 26h Toleranz fuer die taeglichen Laeufe um 03:00/03:15/03:30.
|
# 26h Toleranz fuer die taeglichen Laeufe um 03:00/03:15/03:30.
|
||||||
|
# Fallback auf die Anlagezeit: ein frisch (neu) angelegter CronJob hat noch
|
||||||
|
# keine last_schedule_time-Serie - ein Ausdruck ueber eine fehlende Serie
|
||||||
|
# liefert nichts, der Alarm koennte also nie feuern. max by(...) fasst beide
|
||||||
|
# Metriken zu EINER Serie je CronJob zusammen; ohne das wuerde die nie
|
||||||
|
# aktualisierte created-Serie nach Ablauf der Frist dauerhaft falsch feuern
|
||||||
|
# ('or' matcht inkl. __name__, ergibt also eine Vereinigung beider Serien).
|
||||||
- alert: BackupNotRunning
|
- alert: BackupNotRunning
|
||||||
expr: time() - kube_cronjob_status_last_schedule_time{cronjob=~"(synapse|authentik|wikijs)-backup"} > 93600
|
expr: time() - max by (namespace, cronjob) (kube_cronjob_status_last_schedule_time{cronjob=~"(synapse|authentik|wikijs)-backup"} or kube_cronjob_created{cronjob=~"(synapse|authentik|wikijs)-backup"}) > 93600
|
||||||
labels:
|
labels:
|
||||||
severity: critical
|
severity: critical
|
||||||
annotations:
|
annotations:
|
||||||
@@ -114,9 +120,30 @@ groups:
|
|||||||
# Die monatliche Restore-Probe laeuft nicht mehr. Eine Sicherung, die nie
|
# Die monatliche Restore-Probe laeuft nicht mehr. Eine Sicherung, die nie
|
||||||
# zurueckgespielt wurde, ist eine Vermutung — deshalb ist auch das Ausbleiben
|
# zurueckgespielt wurde, ist eine Vermutung — deshalb ist auch das Ausbleiben
|
||||||
# der PRUEFUNG ein Alarm, nicht nur ihr Fehlschlag. 40 Tage = Monatsrhythmus + Puffer.
|
# der PRUEFUNG ein Alarm, nicht nur ihr Fehlschlag. 40 Tage = Monatsrhythmus + Puffer.
|
||||||
|
# Bis zum ersten REGULAEREN Lauf gibt es keine last_schedule_time-Serie (ein
|
||||||
|
# manuell ausgeloester Job setzt sie nicht) - ohne Fallback waere dieser
|
||||||
|
# Alarm bis dahin blind. Gleiche max-by-Konstruktion wie oben.
|
||||||
- alert: RestoreDrillStale
|
- alert: RestoreDrillStale
|
||||||
expr: time() - kube_cronjob_status_last_schedule_time{cronjob="restore-drill"} > 3456000
|
expr: time() - max by (namespace, cronjob) (kube_cronjob_status_last_schedule_time{cronjob="restore-drill"} or kube_cronjob_created{cronjob="restore-drill"}) > 3456000
|
||||||
labels:
|
labels:
|
||||||
severity: warning
|
severity: warning
|
||||||
annotations:
|
annotations:
|
||||||
summary: "Restore-Probe seit ueber 40 Tagen nicht gelaufen — Wiederherstellbarkeit ist wieder unbewiesen (Verfahren: notfallhandbuch)"
|
summary: "Restore-Probe seit ueber 40 Tagen nicht gelaufen — Wiederherstellbarkeit ist wieder unbewiesen (Verfahren: notfallhandbuch)"
|
||||||
|
|
||||||
|
# Ein Backup-CronJob existiert gar nicht mehr (geloescht, Kustomization
|
||||||
|
# entfernt, Namespace weg). Bei den Alarmen oben verschwindet dann die
|
||||||
|
# Serie - und eine verschwundene Serie ist in Prometheus kein Alarm,
|
||||||
|
# sondern Stille. Genau das war der Fehler, den dieses Regelwerk
|
||||||
|
# verhindern soll, also ist das Fehlen selbst der Alarm.
|
||||||
|
# for: 30m puffert kurze Luecken der Metrik-Pipeline ab.
|
||||||
|
- alert: BackupCronJobMissing
|
||||||
|
expr: >-
|
||||||
|
absent(kube_cronjob_info{namespace="matrix", cronjob="synapse-backup"})
|
||||||
|
or absent(kube_cronjob_info{namespace="matrix", cronjob="wikijs-backup"})
|
||||||
|
or absent(kube_cronjob_info{namespace="authentik", cronjob="authentik-backup"})
|
||||||
|
or absent(kube_cronjob_info{namespace="matrix", cronjob="restore-drill"})
|
||||||
|
for: 30m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
summary: "Ein Backup-/Probe-CronJob fehlt im Cluster — Sicherung oder Wiederherstellungs-Nachweis laeuft nicht mehr"
|
||||||
|
|||||||
Reference in New Issue
Block a user