# Driftsättning

## Vad det är

Driftsättning är den följd av steg som tar en testad version av en applikation ut ur byggsystemet
och sätter den i tjänst. De byggda filerna eller containeravbildningen placeras på de maskiner eller
den plattform som ska köra dem, får konfigurationen för just den miljön och startas, och sedan
flyttas verkliga anrop över till den nya versionen. Ordet står både för handlingen och för
resultatet, så ett team talar om en driftsättning som fastnade i databassteget och om de
driftsättningar som just nu körs i varje miljö. Det som driftsätts kan vara en webbplats, ett API,
ett schemalagt jobb, en ändring i en databas eller den backend som en mobilapp pratar med. I tal
säger många svenska utvecklare deploy och deploya; i skrift är driftsättning det vanliga ordet.

Att driftsätta och att släppa en release hålls ofta isär. Driftsättningen placerar den nya koden
där den kan köras; releasen avgör vem som får se den. En funktion som döljs bakom en
funktionsflagga kan driftsättas på måndagen och släppas till kunderna på torsdagen, utan att någon
rör servrarna igen. Att hålla isär de två låter ett team leverera kod i små, täta steg, medan
besluten om när något ska nå kunderna ligger kvar hos dem som äger produkten.

Många driftsättningar levererar i dag en containeravbildning. Open Container Initiative, som
bildades inom Linux Foundation i juni 2015, publicerar tre specifikationer kring den: hur en
avbildning är uppbyggd, hur en containerkörmiljö kör den när den har packats upp, och hur register
lagrar och delar ut avbildningar. En avbildning identifieras av sin digest, en hash av innehållet,
så samma digest betyder alltid samma byte. En tagg som `1.4.2` är en läsbar pekare till en
avbildning, och den som pushar igen under samma tagg pekar om den till något nytt.

[The Twelve-Factor App](https://12factor.net/), en ofta citerad metod för att bygga webbtjänster,
delar upp vägen från kod till körande tjänst i tre steg som hålls strikt åtskilda. Byggsteget gör
om en commit till ett körbart paket. Releasesteget kombinerar paketet med konfigurationen för en
viss miljö. Körsteget startar processer från en vald release. Varje release får en unik
identifierare och ändras aldrig när den väl finns; varje ändring ger en ny release. Det är det
som gör en återgång, att rulla tillbaka, till en fråga om att välja en tidigare release.

Hur bytet sker beror på vad tjänsten tål. En driftsättning av typen recreate stoppar den gamla
versionen, startar sedan den nya och accepterar ett glapp däremellan. En rullande driftsättning
byter ut instanser några i taget, så att båda versionerna betjänar trafik en stund; det är
standardbeteendet för ett Deployment i Kubernetes. En blå-grön driftsättning kör den nya versionen
bredvid den gamla och flyttar all trafik på en gång, med den gamla redo att ta tillbaka den. En
canary skickar först en liten andel av trafiken till den nya versionen och breddar andelen så länge
felfrekvensen och latensen håller sig friska.

## Varför det spelar roll

Driftsättningen är den punkt där en ändring börjar hjälpa någon, och också den punkt där ett
misstag börjar nå användare. Team som driftsätter sällan samlar gärna många ändringar i varje
release, så varje driftsättning bär större risk och, när den går sönder, fler kandidater till
orsaken. Små, täta driftsättningar håller varje steg lätt att förstå och lätt att backa.

En driftsättning som görs för hand är precis så konsekvent som personen som gör den. Steg hoppas
över, görs i en annan ordning eller görs lite annorlunda av en kollega som täcker upp under en
semester. En CI/CD-pipeline utför samma steg varje gång och lämnar efter sig en uppgift om vilken
commit, vilken artefakt och vilken miljö det gällde, med en tidsstämpel. Den uppgiften är där
granskningen efter en incident börjar, och ofta det snabbaste sättet att svara på vad som ändrades.

Den starkaste vanan är att bygga en gång och föra resultatet vidare. Artefakten som testades i
staging ska byte för byte vara den som når produktion, och bara konfigurationen ska skilja sig;
miljön levererar den konfigurationen när artefakten kommer fram. Registrera digesten vid bygget och
driftsätt efter digest, så går löftet att kontrollera:

```sh
podman build -t registry.example.com/web:1.4.2 .
podman push --digestfile web.digest registry.example.com/web:1.4.2
kubectl -n staging set image deployment/web \
  web=registry.example.com/web@$(cat web.digest)
# after staging checks pass, the same digest goes to production
kubectl -n production set image deployment/web \
  web=registry.example.com/web@$(cat web.digest)
```

Att rulla tillbaka vilar på samma disciplin. När releaser är oföränderliga och har en identitet
innebär en återgång att peka på den föregående, vilket tar sekunder. När varje miljö bygger om från
källkoden innebär en återgång att bygga om en gammal commit och hoppas att dess beroenden
fortfarande löses upp på samma sätt.

## Så ser det ut i praktiken

Tre projekt på webbplatsen visar driftsättning som en väg som utformas en gång och sedan följs.

[Driftsättningarna av en plattform till Azure ägdes från början till slut](/sv/portfolio/owned-end-to-end-deployments-of-the-platform-71/),
och varje ändring följde samma fasta väg från utveckling via staging till produktion, utan att
någon pushade direkt till en skarp miljö. CI/CD-pipelinen bygger avbildningarna och levererar dem,
medan mallar i Bicep håller målinfrastrukturen likadan i varje miljö, så att varje steg vidare
landar på matchande infrastruktur. Inställningar som skiljer sig mellan miljöerna hålls åtskilda
från hemligheterna, vilket låter ett enda bygge färdas genom varje steg och plocka upp rätt
inställningar där det hamnar, utan att byggas om på vägen. Sidan beskriver hur ändringar når varje
miljö längs den fastställda vägen utan manuella ad hoc-driftsättningar, och hur releasen blev ett
kontrollerat steg som går till på samma sätt varje gång.

Ett tidigare uppdrag visar vad den konsekvensen är värd i timmar.
[Automatiserade pipelines för bygge, test och driftsättning sparade ungefär 4 000 timmar](/sv/portfolio/streamlined-ci-cd-processes-saving-4-000-hours-42/)
genom att standardisera vägen från en ändring till produktion och ta bort manuella steg som
varierade med vem som utförde dem. Sidan beskriver hur releaserna blev både snabbare och mer
tillförlitliga.

På företagets egen plattform hålls driftsättning åtskild från provisionering.
[En containermiljö byggd på Podman och Quadlet](/sv/portfolio/deployed-a-container-plane-on-podman-and-quadlet-122/)
låter root förbereda driftsättningsvägen en gång. Därefter driftsätter en oprivilegierad användare
på nytt genom att köra ett enda fast skript via en snävt avgränsad regel som tillåter just det
kommandot utan argument. Skriptet bygger avbildningen och startar om tjänsten, så en rutinmässig
release kräver varken ett root-skal eller godtyckliga kommandon.

## Var det går fel

De flesta problem med en driftsättning kommer av en skillnad mellan det som kontrollerades och det
som faktiskt ändrades.

**Produktionen kör något som staging aldrig såg.** När varje miljö bygger sin egen kopia löses
intervall för beroenden upp till nyare versioner, en basavbildning flyttar sig mellan två byggen
eller en byggflagga skiljer sig, och artefakten som klarade testerna är en annan än den som
betjänar kunderna. Bygg en gång, registrera digesten, för vidare just den digesten, och håll allt
som är specifikt för en miljö i konfigurationen snarare än i artefakten.

**En tagg flyttar sig, och en återgång landar på fel version.** En driftsättning som anger
`latest`, eller som återanvänder en versionstagg efter ett nytt bygge, beror på vad taggen pekar på
den dag den körs. Dokumentationen för Kubernetes avråder från `:latest` i produktion, eftersom det
då blir svårare att avgöra vilken version som körs och svårare att rulla tillbaka på rätt sätt.
Använd en versionstagg som aldrig återanvänds, och lås fast digesten där plattformen tillåter det.

**Pipelinen rapporterar framgång innan den nya versionen fungerar.** Många kommandon för
driftsättning returnerar så snart plattformen har tagit emot begäran, medan de nya instanserna
fortfarande startar och kanske kraschar en minut senare. Ett steg som väntar tills den nya
versionen rapporterar att den är redo, och sedan skickar några verkliga anrop och granskar svaren,
gör ett tyst fel till ett rött bygge medan den föregående releasen fortfarande finns nära till
hands.

**Ny kod och den gamla tabellstrukturen möts mitt i en utrullning.** Under en rullande
driftsättning eller en canary betjänar gamla och nya versioner trafik sida vid sida mot en och
samma databas. En databasmigrering som byter namn på eller tar bort en kolumn får de gamla
instanser som fortfarande körs att gå sönder, och gör det riskabelt att rulla tillbaka, eftersom den
gamla koden räknar med det som togs bort. Dela upp sådana ändringar över flera driftsättningar:
lägg först till den nya strukturen, leverera kod som fungerar med båda, och ta bort den gamla
strukturen först när ingen körande version behöver den.

## Läs mer

- [Build, release, run](https://12factor.net/build-release-run) — argumenten i The Twelve-Factor
  App för tre separata steg och för releaser som aldrig ändras när de väl har skapats.
- [Open Container Initiative](https://opencontainers.org/) — projektet inom Linux Foundation bakom
  specifikationerna för avbildningar, körmiljöer och distribution som de flesta driftsättningar av
  containrar vilar på.
- [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/main/spec.md)
  — manifest, lager, konfiguration och de digests av innehållet som identifierar en avbildning.
- [Kubernetes Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
  — rullande uppdateringar, strategin recreate, tidsgränsen för framsteg och återgångar.
- [Kubernetes images](https://kubernetes.io/docs/concepts/containers/images/) — taggar, digests,
  policyer för hämtning och varför `:latest` gör det svårare att rulla tillbaka.

<https://engineer.company/sv/glossary/deployment/>
