# Nedetid

## Hvad det er

Nedetid er den tid, hvor en tjeneste er ude af drift for dem, der er afhængige
af den. Man taler også om udfald eller nedbrud; det modsatte er oppetid, og den
andel af tiden, en tjeneste er oppe, er dens tilgængelighed, som regel opgivet
i procent over en måned eller et år.

Det rene tilfælde er totalt: siden loader slet ikke, API'et afviser
forbindelser, databasen er nede. Det almindelige tilfælde er mere rodet. En
betaling, der løber ud i timeout, mens kataloget virker, en login-side, der
loader, men afviser hver eneste adgangskode, et API, der svarer på én ud af tre
forespørgsler: hver af dem er nedetid for den, der skal bruge netop den vej,
selv om et health check rettet mod forsiden melder grønt. En brugbar definition
tæller, hvad brugerne kan gøre, og ikke om en proces kører.

Der findes to slags nedetid. Uplanlagt nedetid er det udfald, ingen valgte: en
disk, et dårligt deploy, et udløbet certifikat, en afhængighed, der gik ned
først. Planlagt nedetid vælges på forhånd, som regel i et servicevindue, for at
opgradere, migrere eller flytte noget, der skal stå stille, mens det ændres.
Planlagt nedetid er lettere at leve med, fordi brugerne kan varsles, men den
tæller stadig imod tilgængeligheden, medmindre aftalen udtrykkeligt undtager
den.

HTTP har et ordforråd til selve øjeblikket. RFC 9110 definerer 5xx-klassen af
statuskoder til en server, der ved, at den har fejlet, eller som ikke kan udføre
det, der blev bedt om. Tre af dem betyder hver sit under et udfald. 502 Bad
Gateway siger, at en proxy fik et ugyldigt svar fra serveren bag den. 504
Gateway Timeout siger, at proxyen ventede for længe på et. Og 503 Service
Unavailable er den, man sender med vilje: specifikationen knytter den til
midlertidig overbelastning eller planlagt vedligeholdelse og lader serveren
sige, hvornår man skal komme igen:

```http
HTTP/1.1 503 Service Unavailable
Retry-After: 120
```

Det fortæller browsere, API-klienter og søgemaskinernes crawlere, at tilstanden
er midlertidig, og foreslår at vente to minutter. Det er et helt andet budskab
end en fejlside serveret med en succeskode.

## Hvorfor det betyder noget

Mål for tilgængelighed skrives i nitaller, og nitallerne kan regnes om til tid.
Over et år på 365 dage, altså 8.760 timer, giver hvert mål plads til så meget
nedetid:

- 99 %: 87,6 timer om året, cirka tre et halvt døgn;
- 99,9 %: 8,76 timer om året eller 43,2 minutter på en måned med 30 dage;
- 99,95 %: 4,38 timer om året eller 21,6 minutter på en måned med 30 dage;
- 99,99 %: 52,56 minutter om året;
- 99,999 %: omkring 5,26 minutter om året.

Hvert ekstra nital deler rammen med ti, og prisen for at nå det stiger brat. Ved
99,9 % kan en person nå at blive vækket, logge ind, finde fejlen og rette den
inden for månedens budget. Ved 99,99 % giver hele året under en time, hvilket
måske rækker til én hændelse, så genopretningen må ske automatisk. Ved
99,999 % skal selv en rutinemæssig genstart ske, uden at brugerne mærker det.

Afhængigheder ganges med hinanden. En forespørgsel, der kræver en load balancer,
en applikation og en database, der hver er oppe 99,9 % af tiden og fejler
uafhængigt af hinanden, bliver kun besvaret, når alle tre er oppe: 0,999³, eller
omkring 99,7 %, cirka 26 timers nedetid om året i stedet for 8,76. En tjeneste
kan ikke være mere tilgængelig end kæden af ting, den har brug for, medmindre
den fjerner led fra kæden eller dublerer dem.

Planlægningen begynder i forretningen. NIST's vejledning i beredskabsplanlægning
for amerikanske føderale systemer, SP 800-34, navngiver tre tal, der bør være på
plads, før noget går i stykker. Maximum tolerable downtime (MTD) er det samlede
udfald, systemets ejer vil acceptere. Recovery time objective (RTO) er, hvor
længe et system kan være nede, før konsekvenserne bliver uacceptable, og den
skal være kortere end MTD. Recovery point objective (RPO) er, hvor langt
tilbage i tiden data må gendannes fra den seneste backup, så den måler, hvor
meget datatab man kan tåle, og ikke hvor længe man er offline. Når de tre tal er
skrevet ned, bliver en backupplan og et failoverdesign svar på et spørgsmål i
stedet for gæt.

## Sådan ser det ud i praksis

På en
[IPTV- og OTT-streamingplatform med kunder i Kina, USA og Tyskland](/da/portfolio/provided-round-the-clock-24-7-infrastructure-support-82/)
var hver time nogens bedste sendetid, så en stille time til vedligeholdelse
fandtes simpelthen ikke. Supporten kørte døgnet rundt for omkring tusind servere
plus en god portion systemer, kunderne selv ejede. En stor del af arbejdet var at
opdage noget, der begyndte at skride, før det blev til et udfald, for på en
direkte stream er nedetid nogens fjernsyn, der bare stopper. Platformen forblev
kontinuerligt tilgængelig for sit globale publikum.

I en mellemstor virksomhed
[kørte ti PostgreSQL- og SQL Server-databaseservere med 99,9 % oppetid](/da/portfolio/designed-deployed-and-maintained-10-postgresql-and-ms-13/),
hvilket efter regnestykket ovenfor er en ramme på 8,76 timer om året for hver.
Bag tallet lå automatiserede backups med `pg_dump` og SQL Server Agent-jobs med
opbevaringsregler og offsite-lagring, overvågning i Prometheus og Grafana og
dokumenterede procedurer for disaster recovery, herunder point-in-time-gendannelse
og failover.

Og på en flåde af
[tredive Ubuntu-servere, hvis opsætning var vokset mere ved tilfældighed end plan](/da/portfolio/managed-30-ubuntu-linux-vps-instances-implementing-disaster-20/),
blev disaster recovery-delen bygget om med backups og gendannelsesprocedurer,
der faktisk blev testet. Netværkskonfigurationen blev én hærdet baseline på
tværs af alle instanser. Nedetidsrisikoen faldt, med genopretningsveje, der var
afprøvet, før nogen fik brug for dem.

## Hvor det går galt

**Overvågningen sidder inde i udfaldet.** Et health check, der kører på samme
server eller i samme datacenter, bliver ved med at melde grønt, mens brugerne
møder et udløbet TLS-certifikat, en forkert DNS-post eller en load balancer, der
peger ud i luften. Mål udefra, fra mere end ét sted, ad den vej en rigtig bruger
tager, og alarmér på det, den måling ser.

**Fejlsiden siger 200.** Et framework, der viser en venlig fejlside med en
succeskode, skjuler udfaldet for overvågningen, for klienter, der ellers ville
prøve igen, og for crawlere, som kan indeksere fejlsiden i stedet for den
rigtige. Fejl skal have en fejlstatus, og planlagt vedligeholdelse skal svare
503 med en Retry-After-header.

**Backuppen blev aldrig gendannet.** En backup beviser kun, at bytes blev
kopieret. Indtil en gendannelse er kørt, timet og tjekket mod data, er
genopretningstiden et gæt, og den er ofte langt længere end RTO'en på papiret.
Gendan efter en fast plan, i et separat miljø, og skriv ned, hvor lang tid det
tog. Det samme gælder failover: en standby, der aldrig har overtaget, er et håb,
og en failover, der er øvet i ro og mag, er den, der virker under pres.

**Udrulninger skaber de udfald, de skulle forhindre.** Et deploy, der stopper
den gamle version, før den nye er klar, efterlader et hul ved hver udgivelse.
En skemaændring, der omskriver en stor tabel under en eksklusiv lås, blokerer
alle forespørgsler mod den, indtil den er færdig. Rul nye instanser ud bag et
readiness-tjek, før de gamle stopper, del skemaændringer op i et expand-trin og
et senere contract-trin, så gammel og ny kode begge virker imens, og sæt på
Kubernetes et PodDisruptionBudget, så en node-drain ikke kan tage alle
replikaer ned på én gang.

## Læs mere

- [RFC 9110: HTTP Semantics, section 15.6](https://www.rfc-editor.org/rfc/rfc9110#section-15.6)
  — 5xx-statuskoderne, herunder 503 og dens Retry-After-hint.
- [NIST SP 800-34 Rev. 1: Contingency Planning Guide for Federal Information Systems](https://csrc.nist.gov/pubs/sp/800/34/r1/upd1/final)
  — hvor maximum tolerable downtime, RTO og RPO er defineret.
- [PostgreSQL: High Availability, Load Balancing, and Replication](https://www.postgresql.org/docs/current/high-availability.html)
  — standbyservere og failover, sådan som databasens egen manual beskriver dem.
- [PostgreSQL: Continuous Archiving and Point-in-Time Recovery](https://www.postgresql.org/docs/current/continuous-archiving.html)
  — den basebackup og det WAL-arkiv, en point-in-time-gendannelse bygger på.
- [Kubernetes: Disruptions](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/)
  — frivillige afbrydelser og de PodDisruptionBudgets, der begrænser dem.

<https://engineer.company/da/glossary/downtime/>
