25.09.2020
Alerting für Alerting - Was, wenn eine Metrik verschwindet und keiner bekommt es mit?
Dieser Artikel beschreibt eine mögliche Lösung für dieses Problem.
[
{
"attrs": [],
"content": "Prometheus bietet uns viele M\u00f6glichkeiten unsere Systeme zu \u00fcberwachen. Das Alerting hilft uns festzustellen, wenn diese Systeme in ihrer Funktionalit\u00e4t eingeschr\u00e4nkt sind.\n\nSobald viele verschiedene Exporter im Einsatz sind, hat man schnell eine gro\u00dfe Menge verschiedener Metriken - einige davon werden im Alerting genutzt - und verliert leicht den \u00dcberblick.\nAktuell haben wir 38 Alerts, die sich \u00fcber ca. 17 Bereiche unserer Infrastruktur erstrecken:\n```\n$ ls roles/prometheus/files/rules/alert*.yml | wc -l\n17\n$ grep 'expr:' roles/prometheus/files/rules/alert*.yml | wc -l\n38\n```\n\nJede dieser Dateien enth\u00e4lt Yaml, mit dem das Alerting konfiguriert wird. Darin enthalten sind eine oder mehrere Alerting-Gruppen mit jeweils einer oder mehreren Alerting-Regeln:\n```yaml\ngroups:\n - name: KubeStateMetrics\n rules:\n - alert: pod_frequently_restarting\n expr: increase(kube_pod_container_status_restarts_total{namespace!~\"example\"}[1h]) > 5\n labels:\n severity: warning\n annotations:\n description: Pod {{$labels.namespace}}/{{$labels.pod}} was restarted {{$value}} times within the last hour\n summary: Pod is restarting frequently\n```\n\nSind Metriken aus verschiedenen Gr\u00fcnden nicht mehr verf\u00fcgbar, kann es passieren, dass das Alerting unbemerkt verd\u00e4chtig ruhig wird.\nDiese Gr\u00fcnde m\u00fcssen nichts mit einer Fehlfunktion des Systems zu tun haben. \u00c4nderungen an der eigenen Config oder umbenannte Metriken in neuen Versionen eines Exporters k\u00f6nnen Gr\u00fcnde daf\u00fcr sein, dass Metriken nicht mehr verf\u00fcgbar sind.\n\n## Meta Alerting\nUnsere L\u00f6sung f\u00fcr dieses Problems ist es, f\u00fcr jede im Alerting benutzte Metrik einen weiteren Alert zu konfigurieren, der uns \u00fcber eine nicht verf\u00fcgbare Metrik informiert.\nDie PromQL (Prometheus Query Language) bietet eine Funktion, die pr\u00fcft, ob eine Metrik nicht verf\u00fcgbar ist: (link: https://prometheus.io/docs/prometheus/latest/querying/functions/#absent text: `absent` target:blank).\n\nDa wir gro\u00dfe Fans davon sind Dinge zu automatisieren, liegt das auch hier nahe.\nUnsere Idee: F\u00fcr jede im Alerting verwendete Metrik einen weiteren `absent`-Alert zu generieren: Aus einem Alert mit einem Ausdruck wie\n```\nincrease(kube_pod_container_status_restarts_total[1h]) > 5\n```\nsoll\n```\nabsent(kube_pod_container_status_restarts_total)\n```\nwerden.\n\nAls ersten Schritt ben\u00f6tigen wir also eine Liste aller im Alerting verwendeten Metriken.\nEin einfaches `grep` oder Regex-Matching mit z.B. Python ist nicht ausreichend, um Metriknamen zu extrahieren. Zum Einen m\u00fcssen Yaml Syntax und mehrzeilige PromQL Ausdr\u00fccke ber\u00fccksichtigt werden, zum Anderen m\u00fcssen wir z.B. zwischen dem Namen einer Metrik und dem einer Funktion unterscheiden.\nAlso haben wir uns auf die Suche nach einer Bibliothek gemacht, die f\u00fcr uns die PromQL Ausdr\u00fccke unserer Alerts, wie das obige Beispiel, parst.\n\nDie erste funktionierende Bibliothek in einer Sprache, die wir ausreichend gut sprechen, die wir gefunden haben ist das (link: https://crates.io/crates/promql text: `promql` Crate in Rust target:blank). Diese Bibliothek parst PromQL in einen AST (Abstract Syntax Tree), der mit Rust `enum`s abgebildet wird. So erhalten wir aus jeder PromQL Expression alle Informationen die wir ben\u00f6tigen.\n\nDas Ergebnis ist in unserem GitLab.com Account zu finden: (link: https://gitlab.com/neuland-bfi/prometheus-meta-alerting target:blank)\nIn den (link: https://gitlab.com/neuland-bfi/prometheus-meta-alerting/-/releases text: Releases target:blank) stehen precompiled binaries zum Download bereit und k\u00f6nnen z.B. in CI Pipelines benutzt werden.\n\n## Benutzung und Konfiguration\nDas Tool erwartet eine oder mehrere Dateien mit Prometheus Alerts und eine Zieldatei als Command Line Argumente:\n```shell\nprometheus-meta-alerting roles/prometheus/files/rules/*.yml roles/prometheus/files/rules/meta-alerts.yml\n```\n\nDie erzeugten Meta Alerts werden bei erneutem Generieren ignoriert. So ist es kein Problem die generierten Alerts mit anderen Alerts zusammen zu speichern und dem Tool als Input zu geben.\n\nAus dem obigen Beispiel wird der folgende Meta Alert generiert:\n```yaml\ngroups:\n - name: AlertingMetaAlerts\n rules:\n - alert: metric_absent_kube_pod_container_status_restarts_total\n expr: absent(kube_pod_container_status_restarts_total) == 1\n for: 10m\n labels:\n severity: warning\n service: alerting\n annotations:\n description: \"The metric `kube_pod_container_status_restarts_total` is `absent`! Go check the relevant exporter for updates\"\n title: \"Metric used in alert is `absent`!\"\n```\n\nNat\u00fcrlich kann das Tool auch konfiguriert werden, um beispielsweise eigene Annotationen und Labels an die erzeugten Alerts anzuh\u00e4ngen. So kann der eigentliche Alert im Alerting Mattermost-Channel formatiert werden.\nMit einem `ignore_meta_alerting` Label kann ein Alert explizit aus dem Meta Alerting ausgeschlossen werden. Dies ist n\u00fctzlich, wenn ein Alert bereits `absent` verwendet.\n\nMehr zum Thema Konfiguration ist in der Readme des Projekts dokumentiert.\n\n## Deployment\nIn unserem Monitoring/Alerting Setup integrieren wir das `prometheus-meta-alering`, indem unsere CI in einem Vorbereitungsschritt die Meta Alerts erzeugt. Sp\u00e4tere CI Schritte verwenden diese dann, um sie mit allen anderen Alerts zusammen zu deployen.",
"id": "_qdybtn3s4",
"type": "kirbytext"
}
]