Infra & DevOps

Docker, k8s, CI/CD, deploy strategie, migrace.

Co se naučíš: Dostaneš aplikaci do provozu opakovatelně: kontejnery, CI/CD, strategie nasazení a migrace bez výpadku.

11 min čtení + cvičeníNavazuje na:🛡️ Reliability / SRE

Napsat kód je jen půlka práce, ještě se musí dostat z tvého počítače tam, kde poběží pro reálné uživatele, a to spolehlivě a bez výpadku. Tahle kapitola je o tom: jak appku zabalit, nasadit, sledovat a v případě průšvihu vrátit zpátky. Dobrý backend engineer tohle umí, ne jen psát funkce.


Pár pojmů na úvod

  • Produkce (production) = ostré prostředí, kde tvou appku používají skuteční uživatelé. Opak je vývojové prostředí na tvém počítači.
  • Deploy (nasazení) = dostat novou verzi kódu do produkce.
  • Rollout = postupné vypouštění nové verze.
  • Rollback = vrácení zpátky na předchozí (fungující) verzi, když se nová pokazí.
  • Výpadek (downtime) = doba, kdy služba nefunguje.

Kontejnery (Docker)

Problém, který řeší: „na mém počítači to jede, na serveru ne", kvůli jiné verzi knihoven, runtime apod. Kontejner zabalí tvoji appku i s celým jejím prostředím (knihovny, runtime) do jednoho balíčku, který běží stejně všude.

  • Image = neměnná šablona toho balíčku. Container = běžící instance vytvořená z image.
  • Kontejner vs virtuální stroj (VM): kontejner sdílí jádro (kernel) hostitelského systému, takže je lehký (megabajty, start v sekundách). VM virtualizuje celý operační systém, je těžší, ale izolovanější. Pro nasazování běžných služeb se používají kontejnery.
  • Dobré návyky: malé image, oddělit fázi sestavení od běhu (multi-stage build), neběžet jako root, a nikdy nedávat tajné údaje (secrets) přímo do image. A pozor: tag latest není neměnný (kdykoli se pod ním může objevit jiný obsah) → nasazuj podle konkrétního tagu/digestu.

Orchestrace (Kubernetes)

Když máš mnoho kontejnerů na mnoha strojích, potřebuješ něco, co je řídí, spouští, restartuje, rozkládá zátěž. Tomu se říká orchestrace a nejznámější nástroj je Kubernetes (zkráceně k8s). Jako junior ho nemusíš umět ovládat, ale měl bys chápat, co dělá:

  • Spouští a hlídá kontejnery, udržuje zadaný počet běžících kopií (replik).
  • Self-healing (samoléčení): když kontejner spadne, restartuje ho; když umře celý stroj, přeplánuje kontejnery jinam (využívá liveness/readiness z Observability).
  • Autoscaling: podle zátěže sám přidává nebo ubírá kopie.

Kubernetes je mocný, ale složitý. Pro menší projekty existují jednodušší nástroje (PaaS jako Railway, Render, Coolify), které tohle zařídí za tebe, víc v Tech Choices.


CI/CD, automatizace cesty do produkce

  • CI (Continuous Integration): při každém nahrání kódu se automaticky spustí sestavení a kontroly (lint, typová kontrola, testy). Chyba se chytí dřív, než se dostane do hlavní větve.
  • CD (Continuous Delivery/Deployment): po úspěšném CI se kód automaticky nasadí.
  • Celé to tvoří pipeline (potrubí): commit → sestavení → testy → (staging) → nasazení.

(Staging je předprodukční prostředí co nejvíc podobné produkci, kde se věci vyzkouší nanečisto.)


Deploy strategie, jak nasadit bez výpadku

Když nasazuješ novou verzi, nechceš, aby uživatelé viděli chybovou stránku. Možnosti:

StrategieJak fungujeZa co se platí
RecreateVypni starou verzi, pusť novouNejjednodušší, ale je výpadek
RollingVyměňuj instance po dávkáchBez výpadku; chvíli běží dvě verze naráz
Blue-GreenDvě prostředí, přepneš provoz narázOkamžitý rollback; ale dvojnásobek zdrojů
CanaryPusť nejdřív na malé % uživatelů, sleduj, pak na zbytekNejbezpečnější; ale složitější

Pozor: u rolling a canary běží během nasazení stará i nová verze naráz, takže změny API a databáze musí být zpětně kompatibilní (viz dál).

⚠️ A pozor na past blue-green: „okamžitý rollback" platí pro kód, ale obě prostředí typicky sdílejí jednu databázi, takže jakmile nová verze provede nevratnou migraci, rollback je iluze (databáze zpátky nejde, viz expand-contract níže). I u blue-green proto musí být DB změny zpětně kompatibilní.

Aby „bez výpadku" platilo, musí instance umět graceful shutdown. Při rolling deploy dostane stará instance signál k ukončení (SIGTERM). Nesmí spadnout uprostřed rozdělané práce, má:

  1. přestat hlásit readiness (load balancer ji přestane posílat nové requesty),
  2. dokončit rozpracované requesty (drain) v rámci časového limitu,
  3. teprve pak skončit.

Bez tohohle ti rolling deploy utne requesty, které zrovna běžely (a u dlouhých spojení jako WebSockets je drain o to důležitější, viz Realtime). Když instance do limitu neskončí, orchestrátor ji tvrdě zabije (SIGKILL).


Databázové migrace, kde se to nejčastěji rozbije

Migrace je řízená změna struktury databáze (přidat sloupec, tabulku…). Protože při nasazení běží chvíli stará i nová verze kódu nad stejnou databází, musí být migrace zpětně kompatibilní, jinak stará verze kódu na nové databázi spadne.

Bezpečný postup se jmenuje expand-contract: nejdřív jen přidej nové (sloupec), nasaď kód, který umí obojí, převeď data, přepni čtení na nové, a teprve nakonec smaž staré. Nikdy „přejmenuj sloupec" v jednom kroku během běžícího provozu.

⚠️ Pozor na zamykání tabulky, i zdánlivě nevinná migrace umí na velké tabulce položit provoz. V Postgresu může ADD COLUMN s defaultem nebo CREATE INDEX (bez CONCURRENTLY) zamknout zápisy na celou dobu běhu migrace → uživatelé vidí výpadek. Proto stavěj indexy přes CREATE INDEX CONCURRENTLY a nové sloupce přidávej jako nullable bez defaultu, a hodnoty doplň až dodatečně (backfill po dávkách).


Infrastructure as Code (IaC)

Místo ručního naklikávání serverů ve webové konzoli se infrastruktura popíše kódem (nástroji jako Terraform). Výhody: dá se verzovat, projít revizí a kdykoli přesně zopakovat. Souvisí s immutable infrastructure: běžící servery neupravuješ, ale nahradíš je novými z definice, takže se vyhneš „config driftu" (server, který někdo ručně osahal a teď funguje jen tam a nikdo neví proč).


Prostředí a konfigurace

  • Mívají se tři prostředí: dev (vývoj) → staging (zkušební) → production (ostré).
  • Konfigurace (adresy, klíče) patří do proměnných prostředí, ne do kódu. Tajné údaje přes secret manager.
  • Napříč prostředími nasazuj stejný balíček, liší se jen konfigurací.

Feature flags, autoscaling a disaster recovery

  • Feature flags (přepínače funkcí). Někdy chceš novou funkci nasadit do produkce, ale zapnout ji až později (nebo jen pro pár uživatelů). Feature flag je vypínač v konfiguraci, kterým funkci zapneš/vypneš bez nového nasazení. Oddělíš tím deploy (kód je venku) od release (funkce je vidět) a když je s ní problém, vypneš ji za vteřinu místo zdlouhavého rollbacku.
  • Autoscaling (automatické škálování). Místo abys počet instancí nastavoval ručně, systém ho sám přidává a ubírá podle zátěže (např. podle vytížení CPU). V noci míň, ve špičce víc. Šetří peníze i nervy, ale potřebuje, aby služba byla stateless (Performance).
  • Disaster recovery (zotavení po katastrofě). Plán, co když vypadne celé datacentrum nebo se smažou data. Dvě čísla, kterými se to měří: RPO (Recovery Point Objective, kolik dat smíš v nejhorším ztratit, určuje frekvenci záloh) a RTO (Recovery Time Objective, jak dlouho smí trvat, než zase běžíš). A pravidlo z Databází: obnovu pravidelně zkoušej.

Failure modes, kde se to kazí

  • Nekompatibilní migrace během nasazení → stará verze kódu spadne na novém schématu databáze.
  • Žádný plán na rollback → nasazení se pokazí a nemáš cestu zpět (proto blue-green/canary).
  • Config drift → ručně osahané servery, které nejde zopakovat („funguje jen na jednom").
  • Secrets v image nebo v gitu → únik tajných údajů.

🛠️ Cvičení

  1. Napiš Dockerfile. Pro jednoduchou appku udělej build oddělený od běhu (multi-stage), běh jako ne-root a .dockerignore. Vysvětli, proč do image nepatří secrets.
  2. Vyber deploy strategii. Pro rychlou opravu kritické chyby vs velký rizikový release vyber recreate / rolling / blue-green / canary a zdůvodni.
  3. Expand-contract migrace. Přejmenuj sloupec name na full_name bez výpadku, když během nasazení běží stará i nová verze kódu naráz. Napiš jednotlivé kroky.
  4. Rozbij rollout. Proč „rolling nasazení + migrace, co rovnou smaže starý sloupec" položí starou verzi kódu? Oprav to.
  5. CI pipeline. Navrhni kroky od commitu po produkci (sestavení, lint, testy, staging, nasazení) a urči, co má zastavit nasazení.
Náčrt řešení: rozbal, až si cvičení zkusíš sám
  1. Napiš Dockerfile, multi-stage build: jedna fáze sestaví, druhá (běhová) si vezme jen výsledek; přidej USER mimo root a .dockerignore, ať do image neletí node_modules/.git/.env. Secrets do image nepatří, protože image je neměnná šablona, kterou si kdokoli s přístupem stáhne a vrstvy přečte, tajné údaje předávej až za běhu přes proměnné prostředí / secret manager.
  2. Vyber deploy strategii, rychlou opravu kritické chyby nasaď nejrychlejší bezpečnou cestou (rolling, případně blue-green pro okamžitý rollback); velký rizikový release pусť přes canary (malé % uživatelů, sleduj metriky, pak zbytek). Pozor: u rolling i canary běží stará a nová verze naráz, takže API i DB změny musí být zpětně kompatibilní.
  3. Expand-contract migrace, kroky: přidej nový sloupec full_name, nasaď kód, který zapisuje do obou a čte z full_name s fallbackem na name, převeď stará data, přepni čtení čistě na full_name, a teprve po odejití staré verze smaž name. Pozor: nikdy ne „přejmenovat v jednom kroku" za běhu, stará verze kódu by spadla na chybějícím sloupci.
  4. Rozbij rollout, během rolling deploye běží i stará verze, která starý sloupec ještě čte; migrace, co ho rovnou smaže, jí ho podtrhne a ta padá. Oprava: rozděl to na expand-contract, smazání sloupce dej až do samostatné pozdější migrace, kdy už žádná stará verze neběží. Pozor: stejná past platí i u blue-green, kvůli sdílené databázi.
  5. CI pipeline, kroky: commit → build → lint → typová kontrola → testy → (staging) → nasazení do produkce. Nasazení má zastavit cokoli, co selže, padající test, typová chyba, chyba lintu, neúspěšný build. Pozor: smyslem je rychlá zpětná vazba a pořád funkční hlavní větev, ne „protlačit to dál".

🧠 Otázky & odpovědi

Jaký problém řeší kontejnery a čím se liší od virtuálního stroje?

Kontejner zabalí appku i s jejím prostředím (knihovny, runtime), takže běží stejně na tvém počítači i v produkci, konec „u mě to jede". Oproti virtuálnímu stroji sdílí jádro hostitele, takže je lehký (megabajty, start v sekundách), zatímco VM virtualizuje celý operační systém (těžší, ale izolovanější). Pro nasazování služeb jsou kontejnery výchozí volba.

Porovnej rolling, blue-green a canary nasazení.

Rolling vyměňuje instance po dávkách, bez výpadku, ale chvíli běží dvě verze naráz. Blue-green drží dvě prostředí a přepne provoz naráz, okamžitý rollback, ale potřebuje dvojnásobek zdrojů. Canary pustí novou verzi nejdřív na malé procento uživatelů, sleduje, jestli je vše OK, a pak ji rozšíří, nejbezpečnější, ale složitější. (Recreate = vypni staré, pusť nové; nejjednodušší, ale s výpadkem.)

Proč musí být databázová migrace zpětně kompatibilní?

Při rolling/canary nasazení běží během rolloutu stará i nová verze kódu naráz nad stejnou databází. Když migrace rovnou smaže nebo přejmenuje sloupec, stará verze spadne, protože ho čeká. Proto expand-contract: nejdřív přidej, nasaď kód umějící obojí, převeď data, přepni čtení a teprve pak smaž staré. Nikdy ne „přejmenovat v jednom kroku".

Co je Infrastructure as Code a immutable infrastructure?

Infrastructure as Code = infrastruktura popsaná kódem (např. Terraform), takže ji lze verzovat, projít revizí a přesně zopakovat, žádné ruční naklikávání. Immutable infrastructure = běžící servery neupravuješ, místo toho je nahradíš novými z definice. Tím se vyhneš config driftu (server, co funguje „jen na jednom místě" a nikdo neví proč).

K čemu je CI a co má zastavit nasazení?

CI (Continuous Integration) při každém nahrání kódu automaticky sestaví projekt a pustí kontroly, lint, typovou kontrolu, testy, takže se chyba chytí dřív, než se dostane do hlavní větve. Nasazení má zastavit cokoli, co selže: padající test, typová chyba, chyba lintu. Smysl je rychlá zpětná vazba a udržet hlavní větev pořád funkční.

K čemu jsou feature flags a co oddělují?

Feature flag je vypínač v konfiguraci, kterým funkci zapneš nebo vypneš bez nového nasazení. Tím oddělíš deploy (kód je nasazený v produkci) od release (funkce je opravdu vidět uživatelům): kód můžeš nasadit dřív a zapnout ho až později, jen pro část uživatelů, a když je s ním problém, vypneš ho za vteřinu místo zdlouhavého rollbacku.

Co znamenají RPO a RTO u disaster recovery?

Jsou to dvě čísla, kterými měříš plán zotavení po katastrofě. RPO (Recovery Point Objective) = kolik dat smíš v nejhorším ztratit, určuje, jak často musíš zálohovat. RTO (Recovery Time Objective) = jak dlouho smí trvat, než zase běžíš. Menší čísla = lepší ochrana, ale dražší. A platí: záloha, kterou nikdy nezkusíš obnovit, ti v krizi nepomůže.