Modul 15 — Senior úroveň: architektura a leadership
69. Návrh škálovatelné infrastruktury pro produkční systémy
Jak navrhnout infrastrukturu, která zvládne růst zátěže — horizontální škálování, load balancing, cachování, škálování databází a role kontejnerové orchestrace a cloudu.
Úvod a kontext
Dosavadní moduly probraly jednotlivé stavební bloky — servery,
databáze, kontejnery, Kubernetes, cloud. Tato lekce, první z bloku
"senior úroveň", je o tom, jak tyto bloky poskládat do jednoho
konzistentního návrhu infrastruktury, která zvládne růst z desítek
na statisíce uživatelů, aniž by se musela každý půlrok kompletně
přestavět. Jde o typickou zodpovědnost seniorního DevOps/SRE
inženýra nebo architekta.
Teorie
Vertikální vs. horizontální škálování
Vertikální škálování (scale up) znamená přidat výkonnějšímu
serveru více CPU/RAM/disku. Je jednoduché (žádná změna architektury
aplikace), ale má tvrdý strop — existuje maximální velikost stroje,
kterou lze koupit či pronajmout, a je to single point of failure
(padne-li ten jeden velký server, padne vše).
Horizontální škálování (scale out) znamená přidat další,
stejně velké instance aplikace a rozdělit mezi ně zátěž. Vyžaduje,
aby aplikace byla bezstavová (stateless) — každý požadavek musí
jít obsloužit kterýmkoliv instancí, bez závislosti na tom, co si
"pamatuje" konkrétní server (session data patří do sdíleného úložiště
typu Redis, ne do paměti procesu). Horizontální škálování je pružnější
a odolnější, ale vyžaduje více architektonické disciplíny předem.
Load balancing jako základní stavební kámen
Horizontální škálování potřebuje něco, co rozděluje příchozí
požadavky mezi instance — load balancer (viz Nginx jako reverzní
proxy, modul 5, nebo Kubernetes Service, modul 8). V cloudu tuto roli
běžně přebírá spravovaný load balancer (AWS ALB/NLB, viz modul 11),
který navíc umí automaticky vyřadit nezdravé instance na základě
health checků (modul 8).
Cachování
Cache snižuje zátěž na pomalejší vrstvy systému (typicky databázi)
tím, že často čtená data drží blíž a rychleji dostupná:
- Cache na úrovni aplikace/in-memory (Redis, Memcached) — pro
výsledky drahých dotazů nebo výpočtů. - CDN (Content Delivery Network) — cachuje statický obsah
(obrázky, JS, CSS) na serverech geograficky blízko uživateli, čímž
snižuje latenci a zátěž na origin server. - HTTP cache hlavičky — umožňují prohlížeči nebo proxy cachovat
odpověď bez dotazu na server vůbec.
Cachování přináší vlastní komplexitu — tzv. invalidace cache
("cache invalidation" je pověstně jeden ze dvou "opravdu těžkých
problémů v informatice"): když se podkladová data změní, je potřeba
zajistit, že cache neukazuje zastaralá data déle, než je přijatelné.
Škálování databáze
Databáze je nejčastěji nejtěžší částí architektury na škálování,
protože (na rozdíl od bezstavové aplikace) drží stav:
- Read repliky (viz modul 6) odlehčí čtecí zátěž tím, že se čtení
rozloží na více kopií dat, zatímco zápisy jdou stále na jeden
primární uzel. - Connection pooling (viz incident v modulu 14) zabrání tomu, aby
velké množství instancí aplikace vyčerpalo limit současných
připojení k databázi. - Sharding (dělení dat podle klíče, např. podle ID zákazníka, na
více nezávislých databázových instancí) řeší škálování zápisů, ale
je architektonicky nákladné — zavádí ho až tým, který skutečně
narazil na limit jedné instance, ne preventivně od začátku. - Cachování před databází (viz výše) je často nejlevnější první
krok, než se sáhne po replikaci nebo shardingu.
Role kontejnerů a orchestrace
Kontejnery a Kubernetes (moduly 7–8) usnadňují horizontální
škálování tím, že standardizují, jak se aplikace balí a spouští, a
HorizontalPodAutoscaler (modul 8) umí počet instancí (Podů)
automaticky přizpůsobovat aktuální zátěži bez ručního zásahu.
V cloudu (modul 11) navíc autoscaling skupiny umí přidávat i celé
nové výpočetní uzly, na kterých Pody běží, takže se škáluje jak
aplikace, tak podkladová infrastruktura.
Návrhový princip: škáluj podle skutečného úzkého hrdla
Časná chyba je předčasně optimalizovat všechno najednou. Seniorní
přístup je změřit (metriky z modulu 12), najít skutečné úzké hrdlo
(bottleneck) — často je to databáze, ne aplikační vrstva — a řešit
právě to, místo plošného "přidáme víc serverů všude". Škálovací
opatření mají cenu (peníze, komplexita, provozní zátěž), takže se
zavádí, až když je reálně potřeba, podloženo daty, ne intuicí.
Praktický příklad
Zjednodušený diagram typické škálovatelné produkční architektury
webové aplikace (popsáno textově, odshora dolů podle toku
požadavku):
Uživatel
│
▼
CDN (statický obsah: JS, CSS, obrázky)
│
▼
Load Balancer (AWS ALB / Nginx)
│
├──► App instance 1 (Kubernetes Pod)
├──► App instance 2 (Kubernetes Pod)
└──► App instance N (Kubernetes Pod, škáluje HPA podle CPU/latence)
│
├──► Redis cache (často čtená data, session store)
│
└──► PostgreSQL primární (zápisy)
│
├──► Read replika 1 (čtení reportů)
└──► Read replika 2 (čtení dashboardu)
Odpovídající zjednodušený HorizontalPodAutoscaler (viz modul 8),
který zajišťuje, že se počet App instancí přizpůsobuje zátěži:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: app
minReplicas: 3
maxReplicas: 30
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65
Shrnutí
Škálovatelná infrastruktura kombinuje horizontální škálování
bezstavových aplikačních instancí (podpořené load balancerem a
kontejnerovou orchestrací), cachování na více úrovních (in-memory,
CDN) a strategie pro škálování databáze (read repliky, connection
pooling, v krajním případě sharding). Klíčový návrhový princip je
škálovat podle skutečně změřeného úzkého hrdla, ne plošně a
preventivně — komplexita a náklady škálovacích opatření se mají
zavádět, až když jsou opodstatněné daty.
Kontrolní otázky
- Proč musí být aplikace bezstavová, aby šla efektivně horizontálně
škálovat, a kam se má přesunout stav (např. session), který by
jinak žil v paměti jednoho serveru? - Jaký je rozdíl mezi read replikami a shardingem jako strategiemi
škálování databáze a proč se sharding zavádí jako poslední
možnost? - Co znamená princip "škáluj podle skutečného úzkého hrdla" a proč
je bezpečnější než plošně přidávat kapacitu všude? - Mini cvičení: v diagramu výše navrhněte, kam byste přidali
dodatečnou cache vrstvu, kdyby metriky ukázaly, že hlavní úzké
hrdlo je opakované čtení stejných dat z read replik.
Lekce na sebe nejsou zamčené — libovolnou lekci můžete otevřít i označit jako hotovou v jakémkoliv pořadí.