Hoppa till innehållet

Larm

ett meddelande från ett system när något kräver en människa

Vad det är

Ett larm är en automatisk signal om att ett villkor som någon bevakar har gällt så länge att det är värt att avbryta en människa för det. På engelska heter det alert eller alarm, och ett larm som är allvarligt nog att väcka den som har jour kallas ofta en page.

Ordet täcker två olika saker, och Prometheus håller isär dem på ett sätt som gör skillnaden lätt att se. En larmregel (alerting rule) i Prometheus skapar larm: ett för varje unik uppsättning etiketter som uttrycket ger ett resultat för. Larmen går vidare till ett separat program, Alertmanager, som gör om dem till aviseringar: ett mejl, ett chattmeddelande, ett anrop till en jourtjänst. Projektet skriver rakt ut att larmregler ensamma inte är ett komplett system för aviseringar. Uppdelningen spelar roll eftersom antalen går isär. Femtio larm kan komma fram som ett enda meddelande, ett larm kan ge en påminnelse med några timmars mellanrum, och ett larm som har tystats når ingen alls fast det fortfarande är utlöst.

Livscykeln är kort. Så länge uttrycket inte returnerar något är larmet inaktivt (inactive). När det för första gången ger ett resultat blir larmet väntande (pending), och det förblir väntande så länge regelns for-klausul kräver. Gäller villkoret fortfarande när väntan är över utlöses larmet (firing) och lämnas vidare för leverans. När villkoret upphör att gälla återgår larmet (resolved). En nyare klausul, keep_firing_for, håller ett utlöst larm öppet en stund efter att villkoret har släppt, och dokumentationen beskriver den som ett skydd mot fladder och falska återgångar. Prometheus sparar dessutom tillstånden väntande och utlöst som en tidsserie med namnet ALERTS, så att själva larmen går att söka i och rita grafer över.

En regel som väntar tjugo minuter innan den utlöses, och tio minuter till innan den släpper, ser ut så här:

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"

Etiketter (labels) och annoteringar (annotations) ser likadana ut men gör olika jobb. Etiketterna är en del av det som gör ett larm till just det larmet och inget annat, och Alertmanager läser dem för att avgöra vart det ska: severity: page kan nå en telefon medan severity: ticket hamnar i en kö för ärenden. Annoteringarna bär orden som en människa behöver när meddelandet väl har kommit fram: en sammanfattning på en rad, en längre beskrivning, en länk till runbooken som säger vad som ska göras först. Annoteringar kan byggas med mallar av larmets etiketter och värdet som utlöste det, och det är så sammanfattningen ovan kan citera en siffra.

Larm och incident är olika ord av ett skäl. Ett larm rapporterar att ett villkor gällde. Att avgöra om villkoret utgör en incident är en människas beslut.

Varför det spelar roll

Larmet är den enda delen av övervakningen som inte väntar på att någon ska titta. Systemmätvärden ligger i lagring, en dashboard väntar på en skärm, en logg väntar på en sökning, och ett larm tränger sig in i någons kväll. Det gör varje larmregel till ett litet stående anspråk på en människas uppmärksamhet, och anspråket är skäligt bara om människan kan göra något åt saken. Prometheus egna råd om larm uttrycker det som att undvika att väcka någon när det inte finns något att göra, och att hålla larmen enkla.

Det andra skälet är ren aritmetik. En enda orsak utlöser oftast många regler på en gång. När en nätverkspartition skär av hälften av en tjänsts instanser från deras databas kan varje instans utlösa ett eget larm, och dokumentationen för Alertmanager använder just det fallet för att visa hur hundratals larm blir en enda avisering. Alertmanager samlar larm som delar etiketterna i group_by och väntar group_wait (30 sekunder som standard), så att det första meddelandet rymmer hela omgången. Därefter skickar den uppdateringar för gruppen högst en gång per group_interval (5 minuter) och upprepar ett meddelande som fortfarande gäller efter repeat_interval (4 timmar). Undertryckning (inhibition) går ett steg längre och håller tillbaka vissa larm medan ett annat är utlöst, så att ett larm om att ett helt kluster är onåbart kan tysta larmen från varje tjänst därinne. En silence stänger av larm som matchar en uppsättning etiketter under en bestämd tid, oftast under planerat underhåll.

Det tredje skälet gäller slutet på historien. De flesta mottagare skickar ett meddelande om återgång när larmet släpper, men e-postmottagarens inställning send_resolved är som standard false. Ett team som larmar via e-post kan alltså se problemet annonseras och aldrig se det ta slut.

Så ser det ut i praktiken

Larmen på företagets egen värd är byggda åt andra hållet. En värd med 464 MB minne kör en forge, en databas och en webbserver, och den dör troligast av att minnet eller disken tar slut, två fel som inte varnar i förväg. Ett larm som förutsätter att värden säger ifrån medan den går sönder är oanvändbart där, eftersom det är den trasiga värden som skulle behöva säga något. I stället pingar en timer på värden en extern tjänst bara medan både minne och disk är friska, var femtonde minut med slumpmässig förskjutning, och den externa tjänsten larmar när pingarna upphör. Det är ett dödmansgrepp: tystnaden är larmet. Varje sätt som värden kan gå sönder på, ett tappat nätverk och en start som stannar halvvägs inräknade, slutar i samma uteblivna ping, och det är precis vad konstruktionen är till för. Sidan anger också dess gräns: kontrollen bevisar att maskinen är frisk och säger ingenting om huruvida webbplatsen svarar.

Samma omvändning vaktar schemalagt arbete. Den krypterade säkerhetskopieringen till lagring utanför värden körs på en timer och pingar sitt dödmansgrepp bara när en körning lyckas, så en misslyckad körning ger tystnad. Tystnaden är det som blir ett larm, och det upptäcks av något utanför maskinen i stället för att skrivas till en logg på den.

Omvända larm har ett eget felläge, och det visade sig när plattformen skulle växa från en värd till två. Att låta båda värdarna dela ett grepp hade försvagat larmen som det var tänkt att utvidga: så länge någon av värdarna fortsätter att pinga förblir kontrollen grön medan den andra är död. Greppen delades upp med en post per värd, och den befintliga värdens poster lämnades tomma med avsikt, så att konfigurationen säger att kopplingen finns och att värdet återstår att fylla i.

Var det går fel

Ett uppmätt värde hamnar i en etikett. Eftersom etiketterna identifierar ett larm gör en etikett som bär det aktuella talet varje ändring av talet till ett nytt larm, och det förra återgår. Mottagaren ser en ström av par, utlöst och återgått, för ett och samma problem. Använd etiketter för identitet och routning, och lägg siffror i annoteringar.

Larmet fladdrar. Ett villkor som pendlar kring sitt tröskelvärde utlöses, återgår och utlöses igen med några minuters mellanrum, och varje meddelande om återgång säger något falskt till den som läser. Förläng for så att en tillfällig topp hinner försvinna innan någon hör om den, och använd keep_firing_for så att en kort dipp under tröskeln inte avslutar larmet.

En silence lever längre än sitt skäl. Någon tystar ett larm inför underhåll med en bred matchning och en generös sluttid, och nästa veckas verkliga fel kommer fram tystat. Matcha silences så snävt som arbetet tillåter, ge dem en sluttid nära den tidpunkt då arbetet borde vara klart, och skriv vem som satte dem och varför i kommentarsfältet som Alertmanager erbjuder.

En bred rutt sväljer de specifika. Alertmanager går igenom routningsträdet i ordning och stannar vid det första barnet som matchar, om inte en rutt sätter continue: true. En samlingsrutt som ligger ovanför ett teams egen rutt tar med sig teamets larm. Lägg de snävaste rutterna först och testa trädet med exempeletiketter innan ni förlitar er på det.

Allt är bråttom. Disk på 70 %, ett certifikat som går ut nästa månad och en betaltjänst som returnerar fel går alla till samma telefon, och snart börjar telefonen ignoreras. Larma bara för villkor som en människa måste agera på nu, skicka resten till en kö för ärenden eller en daglig sammanfattning, och radera en regel som har utlösts i månader utan att någon har agerat på den.

Läs mer

  • Alerting overview — hur larmregler i Prometheus och Alertmanager delar på arbetet, och stegen för att sätta upp båda.
  • Alerting rules — syntaxen för regler, med for, keep_firing_for, etiketter, annoteringar och mallar.
  • Alertmanager — gruppering, undertryckning, silences och hur fler än en Alertmanager körs för hög tillgänglighet.
  • Alertmanager configuration — routningsträdet, grupperingens timers, regler för undertryckning och varje mottagares inställningar, bl.a. send_resolved.
  • Alerting practices — projektets egna råd om vad som är värt att väcka någon för och vad som hör hemma någon annanstans.

Ordlista