Obvykle je vždy potřeba zajistit vyhrazený pool zdrojů pro nějakou aplikaci, aby mohla správně a stabilně fungovat. Ale co když na stejných kapacitách běží více aplikací? Jak zajistit, aby každá z nich měla minimálně potřebné zdroje? Jakým způsobem lze omezit spotřebu zdrojů? Jak efektivně rozdělit zátěž mezi uzly? Jak zajistit, aby mechanismus horizontálního škálování fungoval v případě, že dojde k růstu zátěže na aplikacích?

Nejdříve je třeba se zamyslet nad tím, jaké základní typy zdrojů existují v systému — tím jsou samozřejmě procesorový čas a operační paměť. V manifestech k8s se tyto typy zdrojů měří v následujících jednotkách:
- CPU — v jádrech
- RAM — v bytech
Pro každý zdroj existuje možnost definovat dva typy požadavků — requests a limits. Requests — popisuje minimální požadavky na volné zdroje uzlu pro spuštění kontejneru (a podu jako celku), zatímco limits stanovuje pevné omezení zdrojů, které jsou kontejneru k dispozici.
Je důležité chápat, že v manifestu není nutné výslovně definovat oba typy, přičemž chování bude následující:
- Pokud je výslovně zadáno pouze limits pro zdroj, requests pro tento zdroj automaticky přijme hodnotu rovnou limits (z toho se lze přesvědčit pomocí popisu entity). Tedy práce kontejneru bude fakticky omezena na stejné množství zdrojů, které požaduje pro svůj start.
- Pokud je pro zdroj výslovně zadáno pouze requests, žádná omezení nahoře na tento zdroj nejsou nastavena — tedy kontejner je omezen pouze zdroji samotného uzlu.
Existuje také možnost nastavit správu zdrojů nejen na úrovni konkrétního kontejneru, ale i na úrovni namespace pomocí následujících entit:
- LimitRange — popisuje politiku omezení na úrovni kontejneru/podu v ns a je potřebná k tomu, aby popsala výchozí omezení na kontejner/pod, a také bránila vytváření zjevně ‚tlustých‘ kontejnerů/podů (nebo naopak), omezovala jejich množství a určovala možný rozdíl hodnot v limits a requests.
- ResourceQuotas — popisují politiku omezení v celém prostoru názvů a obvykle se používají k rozdělení zdrojů mezi prostředími (užitečné, když nejsou prostředí přísně oddělena na úrovni uzlů)
Následují příklady manifestů, kde jsou nastavena omezení na zdroje:
Na úrovni konkrétního kontejneru:
containers: - name: app-nginx image: nginx resources: requests: memory: 1Gi limits: cpu: 200mTedy v tomto případě pro spuštění kontejneru s nginx bude zapotřebí minimálně dostupných 1G RAM a 0.2 CPU na uzlu, přičemž maximálně kontejner může spotřebovat 0.2 CPU a veškerou dostupnou RAM na uzlu.
Na úrovni celého prostoru názvů:
apiVersion: v1 kind: ResourceQuota metadata: name: nxs-test spec: hard: requests.cpu: 300m requests.memory: 1Gi limits.cpu: 700m limits.memory: 2GiTedy součet všech požadavků kontejnerů v defaultním prostoru názvů nesmí překročit 300m pro CPU a 1G pro RAM, a součet všech limitů — 700m pro CPU a 2G pro RAM.
Defaultní omezení pro kontejnery v prostoru názvů:
apiVersion: v1 kind: LimitRange metadata: name: nxs-limit-per-container spec: limits: - type: Container defaultRequest: cpu: 100m memory: 1Gi default: cpu: 1 memory: 2Gi min: cpu: 50m memory: 500Mi max: cpu: 2 memory: 4GiTedy v defaultním prostoru názvů pro všechny kontejnery bude ve výchozím nastavení nastavena žádost na 100m pro CPU a 1G pro RAM, limit — 1 CPU a 2G. Přičemž také je stanoveno omezení na možné hodnoty v žádosti/limitu pro CPU (50m < x < 2) a RAM (500M < x < 4G).
Omezení na úrovni podů prostoru názvů:
apiVersion: v1 kind: LimitRange metadata: name: nxs-limit-pod spec: limits: - type: Pod max: cpu: 4 memory: 1GiTedy pro každý pod v defaultním prostoru názvů bude stanoveno omezení na 4 vCPU a 1G.
Nyní bych rád vyprávěl, jaké výhody nám může přinést nastavení těchto omezení.
Mechanismus vyvažování zatížení mezi uzly
Jak je známo, za rozdělení podů mezi uzly odpovídá komponenta k8s, jako je scheduler, který funguje podle určitého algoritmu. Tento algoritmus při výběru optimálního uzlu pro spuštění prochází dvěma fázemi:
- Filtrace
- Hodnocení
Tedy podle popsané politiky jsou nejprve vybírány uzly, na kterých je možné spustit pod na základě sady predicates (včetně kontroly, zda má uzel dostatek zdrojů pro spuštění podu — PodFitsResources), a poté pro každý z těchto uzlů, podle priorities Body se přidělují body (čím více volných zdrojů má uzel, tím více bodů je mu přiděleno — LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) a pod se spouští na uzlu s největším počtem bodů (pokud tomuto požadavku vyhovuje více uzlů, náhodně se vybere jeden z nich).
Je však třeba si uvědomit, že scheduler při hodnocení dostupných zdrojů uzlu vychází z údajů uložených v etcd — tedy z celkového počtu requested/limit každého podu spuštěného na tomto uzlu, nikoli z aktuální spotřeby zdrojů. Tuto informaci lze získat výstupem příkazu kubectl describe node $NODE, například:
# kubectl describe nodes nxs-k8s-s1
..
Non-terminated Pods: (9 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
ingress-nginx nginx-ingress-controller-754b85bf44-qkt2t 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d
kube-system kube-flannel-26bl4 150m (0%) 300m (1%) 64M (0%) 500M (1%) 233d
kube-system kube-proxy-exporter-cb629 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d
kube-system kube-proxy-x9fsc 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d
kube-system nginx-proxy-k8s-worker-s1 25m (0%) 300m (1%) 32M (0%) 512M (1%) 233d
nxs-monitoring alertmanager-main-1 100m (0%) 100m (0%) 425Mi (1%) 25Mi (0%) 233d
nxs-logging filebeat-lmsmp 100m (0%) 0 (0%) 100Mi (0%) 200Mi (0%) 233d
nxs-monitoring node-exporter-v4gdq 112m (0%) 122m (0%) 200Mi (0%) 220Mi (0%) 233d
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 487m (3%) 822m (5%)
memory 15856217600 (2%) 749976320 (3%)
ephemeral-storage 0 (0%) 0 (0%)Zde vidíme všechny pody spuštěné na konkrétním uzlu, stejně jako zdroje, které každý pod vyžaduje. A takto vypadají logy scheduleru při spuštění podu cronjob-cron-events-1573793820-xt6q9 (tato informace se v logu scheduleru objeví při nastavení 10. úrovně logování v argumentech příkazu pro spuštění —v=10):
log
I1115 07:57:21.637791 1 scheduling_queue.go:908] Chystáme se naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9
I1115 07:57:21.637804 1 scheduler.go:453] Pokoušíme se naplánovat pod: nxs-stage/cronjob-cron-events-1573793820-xt6q9
I1115 07:57:21.638285 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s5 je povoleno, uzel běží pouze s 16 z 110 Podů.
I1115 07:57:21.638300 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s6 je povoleno, uzel běží pouze s 20 z 110 Podů.
I1115 07:57:21.638322 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s3 je povoleno, uzel běží pouze s 20 z 110 Podů.
I1115 07:57:21.638322 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s4 je povoleno, uzel běží pouze s 17 z 110 Podů.
I1115 07:57:21.638334 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s10 je povoleno, uzel běží pouze s 16 z 110 Podů.
I1115 07:57:21.638365 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s12 je povoleno, uzel běží pouze s 9 z 110 Podů.
I1115 07:57:21.638334 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s11 je povoleno, uzel běží pouze s 11 z 110 Podů.
I1115 07:57:21.638385 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s1 je povoleno, uzel běží pouze s 19 z 110 Podů.
I1115 07:57:21.638402 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s2 je povoleno, uzel běží pouze s 21 z 110 Podů.
I1115 07:57:21.638383 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s9 je povoleno, uzel běží pouze s 16 z 110 Podů.
I1115 07:57:21.638335 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s8 je povoleno, uzel běží pouze s 18 z 110 Podů.
I1115 07:57:21.638408 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s13 je povoleno, uzel běží pouze s 8 z 110 Podů.
I1115 07:57:21.638478 1 predicates.go:1369] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s10 je povoleno, stávající podmínky pro anti-afinitu jsou splněny.
I1115 07:57:21.638505 1 predicates.go:1369] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s8 je povoleno, stávající podmínky pro anti-afinitu jsou splněny.
I1115 07:57:21.638577 1 predicates.go:1369] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s9 je povoleno, stávající podmínky pro anti-afinitu jsou splněny.
I1115 07:57:21.638583 1 predicates.go:829] Naplánovat pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 na uzlu nxs-k8s-s7 je povoleno, uzel běží pouze s 25 z 110 Podů.
I1115 07:57:21.638932 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: Vyvážená alokace zdrojů, kapacita 39900 milicore 66620178432 bajtů paměti, celková žádost 2343 milicore 9640186880 bajtů paměti, skóre 9
I1115 07:57:21.638946 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: Minimální alokace zdrojů, kapacita 39900 milicore 66620178432 bajtů paměti, celková žádost 2343 milicore 9640186880 bajtů paměti, skóre 8
I1115 07:57:21.638961 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: Vyvážená alokace zdrojů, kapacita 39900 milicore 66620170240 bajtů paměti, celková žádost 4107 milicore 11307422720 bajtů paměti, skóre 9
I1115 07:57:21.638971 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: Vyvážená alokace zdrojů, kapacita 39900 milicore 66620178432 bajtů paměti, celková žádost 5847 milicore 24333637120 bajtů paměti, skóre 7
I1115 07:57:21.638975 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: Minimální alokace zdrojů, kapacita 39900 milicore 66620170240 bajtů paměti, celková žádost 4107 milicore 11307422720 bajtů paměti, skóre 8
I1115 07:57:21.638990 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: Minimální alokace zdrojů, kapacita 39900 milicore 66620178432 bajtů paměti, celková žádost 5847 milicore 24333637120 bajtů paměti, skóre 7
I1115 07:57:21.639022 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: Priorita toleraceání kyseliny, Skóre: (10)
I1115 07:57:21.639030 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: Priorita toleraceání kyseliny, Skóre: (10)
I1115 07:57:21.639034 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: Priorita toleraceání kyseliny, Skóre: (10)
I1115 07:57:21.639041 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: Priorita afinity uzlu, Skóre: (0)
I1115 07:57:21.639053 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: Priorita afinity uzlu, Skóre: (0)
I1115 07:57:21.639059 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: Priorita afinity uzlu, Skóre: (0)
I1115 07:57:21.639061 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: Priorita afinity mezi pody, Skóre: (0)
I1115 07:57:21.639063 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: Priorita rozložení selektoru, Skóre: (10)
I1115 07:57:21.639073 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: Priorita afinity mezi pody, Skóre: (0)
I1115 07:57:21.639077 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: Priorita rozložení selektoru, Skóre: (10)
I1115 07:57:21.639085 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: Priorita afinity mezi pody, Skóre: (0)
I1115 07:57:21.639088 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: Priorita rozložení selektoru, Skóre: (10)
I1115 07:57:21.639103 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: Priorita rozložení selektoru, Skóre: (10)
I1115 07:57:21.639109 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: Priorita rozložení selektoru, Skóre: (10)
I1115 07:57:21.639114 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: Priorita rozložení selektoru, Skóre: (10)
I1115 07:57:21.639127 1 generic_scheduler.go:781] Host nxs-k8s-s10 => Skóre 100037
I1115 07:57:21.639150 1 generic_scheduler.go:781] Host nxs-k8s-s8 => Skóre 100034
I1115 07:57:21.639154 1 generic_scheduler.go:781] Host nxs-k8s-s9 => Skóre 100037
I1115 07:57:21.639267 1 scheduler_binder.go:269] AssumePodVolumes pro pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", uzel "nxs-k8s-s10"
I1115 07:57:21.639286 1 scheduler_binder.go:279] AssumePodVolumes pro pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", uzel "nxs-k8s-s10": všechny PVC jsou přiřazeny a není co dělat
I1115 07:57:21.639333 1 factory.go:733] Pokoušíme se vázat cronjob-cron-events-1573793820-xt6q9 na nxs-k8s-s10Zde vidíme, že scheduler nejprve filtruje a vytváří seznam tří uzlů, na kterých je možné spustit (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Následně provádí výpočet bodů podle několika parametrů (včetně BalancedResourceAllocation, LeastResourceAllocation) pro každý z těchto uzlů, aby určil nejvhodnější uzel. Nakonec je plánován na uzlu s nejvyšším počtem bodů (zde jsou dva uzly se stejným počtem bodů 100037, proto je vybrán náhodný z nich — nxs-k8s-s10).
Výstup: pokud na uzlu běží pody, pro které nejsou stanovena omezení, bude to pro k8s (z pohledu spotřeby zdrojů) obdobné, jako kdyby na tomto uzlu tyto pody vůbec nebyly. Proto, pokud máte, dejme tomu, pod s náročným procesem (např. wowza) a pro něj nejsou stanovena omezení, může nastat situace, kdy tento pod ve skutečnosti spotřebuje všechny zdroje uzlu, ale pro k8s je tento uzel považován za nenáročný a při hodnocení dostane stejné množství bodů jako uzel, na kterém žádné pracovní pody nejsou, což nakonec může vést k nerovnoměrnému rozdělení zátěže mezi uzly.
Vysídlení podu
Jak je známo, každému podu je přidělen jedna ze tří QoS tříd:
- guaranuted — je přiděleno tehdy, když je pro každý kontejner v podu stanoveno request a limit pro paměť a CPU, přičemž tyto hodnoty musí být shodné
- burstable — alespoň jeden kontejner v podu má request a limit, přičemž request < limit
- best effort — když žádný kontejner v podu není omezen na zdroje
Při tom, když na uzlu dochází k nedostatku zdrojů (místa na disku, paměti), kubelet začíná řadit a vyměňovat pody podle určitého algoritmu, který bere v úvahu prioritu podu a jeho QoS třídu. Například, pokud se jedná o RAM, body se přidělují na základě QoS třídy následujícím způsobem:
- Guaranteed: -998
- BestEffort: 1000
- Burstable: min(max(2, 1000 — (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)
Tedy při stejném přednostním hodnocení bude kubelet nejprve vyměňovat z uzlu pody s QoS třídou best effort.
Výstup: pokud chcete snížit pravděpodobnost vysídlení potřebného podu z uzlu v případě nedostatku zdrojů na něm, měli byste kromě priority také dbát na stanovení request/limit pro něj.
Mechanismus horizontálního automatického škálování podů aplikace (HPA)
Když je potřeba automaticky zvyšovat a snižovat počet podů v závislosti na využití zdrojů (systémových — CPU/RAM nebo uživatelských — rps), může nám v řešení pomoci taková entita k8s jako HPA (Horizontální automatizátor podů). Jeho algoritmus spočívá v následujícím:
- Určují se aktuální hodnoty sledovaného zdroje (currentMetricValue)
- Určují se požadované hodnoty pro zdroj (desiredMetricValue), které jsou pro systémové zdroje nastaveny pomocí request
- Určuje se aktuální počet replik (currentReplicas)
- Podle následujícího vzorce se vypočítá požadovaný počet replik (desiredReplicas)
desiredReplicas = [ currentReplicas * ( currentMetricValue / desiredMetricValue )]
Při tom nedojde k škálování, když je poměr (currentMetricValue / desiredMetricValue) blízký 1 (při tom můžeme sami nastavit povolenou chybu, výchozí hodnota je 0.1).
Zvažme fungování hpa na příkladu aplikace app-test (popisované jako nasazení), kde je třeba měnit počet replik v závislosti na spotřebě CPU:
Manifest aplikace
kind: Deployment apiVersion: apps/v1beta2 metadata: name: app-test spec: selector: matchLabels: app: app-test replicas: 2 template: metadata: labels: app: app-test spec: containers: - name: nginx image: registry.nixys.ru/generic-images/nginx imagePullPolicy: Always resources: requests: cpu: 60m ports: - name: http containerPort: 80 - name: nginx-exporter image: nginx/nginx-prometheus-exporter resources: requests: cpu: 30m ports: - name: nginx-exporter containerPort: 9113 args: - -nginx.scrape-uri - http://127.0.0.1:80/nginx-statusTj. vidíme, že pod s aplikací se zpočátku spouští ve dvou exemplářích, z nichž každý obsahuje dva kontejnery nginx a nginx-exporter, pro které je nastaveno requests pro CPU.
Manifest HPA
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: app-test-hpa spec: maxReplicas: 10 minReplicas: 2 scaleTargetRef: apiVersion: extensions/v1beta1 kind: Deployment name: app-test metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 30Tj. vytvořili jsme hpa, který bude sledovat nasazení app-test a regulovat počet podů s aplikací na základě ukazatele cpu (očekáváme, že pod by měl spotřebovávat 30% procent od požadovaného CPU), přičemž počet replik se pohybuje v rozmezí 2-10.
Nyní zvažme mechanismus fungování hpa, pokud zatížíme jeden z podů:
# kubectl top pod NAME CPU(cores) MEMORY(bytes) app-test-78559f8f44-pgs58 101m 243Mi app-test-78559f8f44-cj4jz 4m 240Mi
Celkově máme následující:
- Žádaná hodnota (desiredMetricValue) — podle nastavení hpa je nastavena na 30%
- Aktuální hodnota (currentMetricValue) — pro výpočet controller-manager počítá průměrnou spotřebu zdrojů v %, tedy toto přibližně provádí:
- Získává absolutní hodnoty metrik podů z metric-serveru, t.j. 101m a 4m
- Vypočítává průměrnou absolutní hodnotu, t.j. (101m + 4m) / 2 = 53m
- Získává absolutní hodnotu pro požadovanou spotřebu zdroje (k tomu se sčítají requesty všech kontejnerů) 60m + 30m = 90m
- Vypočítává průměrné procento spotřeby CPU vzhledem k requestu podu, t.j. 53m / 90m * 100% = 59%
Nyní máme vše potřebné, abychom určili, zda je třeba měnit počet replik, proto vypočítáváme koeficient:
ratio = 59% / 30% = 1.96
T.j. počet replik by měl být zvýšen přibližně 2x a činit [2 * 1.96] = 4.
Výstup: Jak si můžete všimnout, pro to, aby tento mechanismus fungoval, je nutné mít requesty pro všechny kontejnery v monitorovaném podu.
Mechanismus horizontálního autoskalování uzlů (Cluster Autoscaler)
Aby se vyrovnaly negativní dopady na systém při výkyvech zátěže, někdy nestačí mít nastavený hpa. Například podle nastavení v hpa controller manager rozhodne, že je třeba zvýšit počet replik 2x, ale na uzlech nejsou žádné volné zdroje pro spuštění takového počtu podů (t.j. uzel nemůže poskytnout požadované zdroje podu requests) a tyto pady přecházejí do stavu Pending.
V tomto případě, pokud má poskytovatel odpovídající IaaS/PaaS (např. GKE/GCE, AKS, EKS atd.), může nám pomoci takový nástroj, jako je Node Autoscaler. Umožňuje nastavit maximální a minimální počet uzlů v klastru a automaticky upravovat aktuální počet uzlů (prostřednictvím API cloudového poskytovatele pro objednávání/odstraňování uzlu), když se pozoruje nedostatek zdrojů v klastru a pady nemohou být naplánovány (nacházejí se ve stavu Pending).
Výstup: Pro možnost autoskalování uzlů je nutné nastavit requesty v kontejnerech podů, aby k8s mohlo správně posoudit zatížení uzlů a podle toho oznámit, že pro spuštění dalšího podu nejsou v klastru dostatečné zdroje.
Závěr
Je třeba poznamenat, že nastavení omezení zdrojů pro kontejner není povinnou podmínkou pro úspěšné spuštění aplikace, nicméně je to přesto lepší udělat z následujících důvodů:
- Pro přesnější fungování plánovače v oblasti vyvažování zátěže mezi uzly k8s
- Pro snížení pravděpodobnosti vzniku události "vystěhování podu"
- Pro fungování horizontálního automatického škálování podů aplikace (HPA)
- Pro fungování horizontálního automatického škálování uzlů (Cluster Autoscaling) u cloudových poskytovatelů
Také si přečtěte další články na našem blogu:
Zdroj: habr.com
