10 bežných chýb pri používaní Kubernetes

Poznámka. preklad.: Autormi tohto článku sú inžinieri z malej českej firmy pipetail. Podarilo sa im dať dokopy úžasný zoznam [niekedy banálnych, no stále] veľmi naliehavých problémov a mylných predstáv súvisiacich s prevádzkou klastrov Kubernetes.

10 bežných chýb pri používaní Kubernetes

Za roky používania Kubernetes sme pracovali s veľkým množstvom klastrov (spravovaných aj nespravovaných – na GCP, AWS a Azure). Postupom času sme si začali všímať, že niektoré chyby sa neustále opakujú. Nie je to však žiadna hanba: väčšinu z nich sme urobili sami!

Článok obsahuje najčastejšie chyby a uvádza aj spôsob ich opravy.

1. Zdroje: požiadavky a limity

Táto položka si určite zaslúži najväčšiu pozornosť a prvé miesto v zozname.

CPU požiadavka zvyčajne buď nie je špecifikovaný vôbec, alebo má veľmi nízku hodnotu (na umiestnenie čo najväčšieho počtu strukov na každý uzol). Tak dochádza k preťaženiu uzlov. V čase vysokej záťaže je výpočtový výkon uzla plne využitý a konkrétna pracovná záťaž dostane len to, čo si „vyžiadala“ Škrtenie procesora. To vedie k zvýšenej latencii aplikácií, časovým limitom a ďalším nepríjemným následkom. (Prečítajte si o tom viac v našom ďalšom nedávnom preklade: “Limity CPU a agresívne obmedzovanie v Kubernetes" - približne. preklad.)

BestEffort (extrémne nie odporúčané):

resources: {}

Extrémne nízka požiadavka na CPU (extrémne nie odporúčané):

   resources:
      Requests:
        cpu: "1m"

Na druhej strane, prítomnosť limitu CPU môže viesť k nerozumnému preskakovaniu taktovacích cyklov modulmi, aj keď procesor uzla nie je plne zaťažený. Opäť to môže viesť k zvýšeným oneskoreniam. Kontroverzia okolo parametra pokračuje Kvóta CPU CFS v linuxovom jadre a obmedzovaní CPU v závislosti od nastavených limitov, ako aj zakázaní kvóty CFS... Bohužiaľ, limity CPU môžu spôsobiť viac problémov, ako vyriešiť. Viac informácií o tom nájdete na nižšie uvedenom odkaze.

Prílišný výber (nadmerné) problémy s pamäťou môžu viesť k väčším problémom. Dosiahnutie limitu CPU znamená preskočenie hodinových cyklov, zatiaľ čo dosiahnutie limitu pamäte znamená zabitie modulu. Pozorovali ste niekedy OOMkill? Áno, presne o tom hovoríme.

Chcete minimalizovať pravdepodobnosť, že sa to stane? Neprideľujte príliš veľa pamäte a používajte zaručenú QoS (Quality of Service) nastavením požiadavky na pamäť na limit (ako v príklade nižšie). Prečítajte si o tom viac v Prezentácie Henninga Jacobsa (vedúci inžinier Zalando).

Trhateľný (vyššia šanca na získanie OOMkilled):

   resources:
      requests:
        memory: "128Mi"
        cpu: "500m"
      limits:
        memory: "256Mi"
        cpu: 2

Garantujeme:

   resources:
      requests:
        memory: "128Mi"
        cpu: 2
      limits:
        memory: "128Mi"
        cpu: 2

Čo môže potenciálne pomôcť pri nastavovaní zdrojov?

S metrický server môžete vidieť aktuálnu spotrebu zdrojov CPU a využitie pamäte modulmi (a kontajnermi v nich). S najväčšou pravdepodobnosťou ho už používate. Stačí spustiť nasledujúce príkazy:

kubectl top pods
kubectl top pods --containers
kubectl top nodes

Zobrazujú však iba aktuálne využitie. Môže vám poskytnúť približnú predstavu o rádovej veľkosti, ale nakoniec budete potrebovať históriu zmien metrík v priebehu času (na zodpovedanie otázok ako: „Aké bolo maximálne zaťaženie procesora?“, „Aké bolo zaťaženie včera ráno?“ atď.). Na to môžete použiť Prometheus, DataDog a iné nástroje. Jednoducho získajú metriky zo servera metrík a uložia ich a používateľ ich môže vyhľadávať a podľa toho vykresľovať.

VerticalPodAutoscaler umožňuje automatizovať tento proces. Sleduje históriu využitia CPU a pamäte a na základe týchto informácií nastavuje nové požiadavky a limity.

Efektívne využitie výpočtového výkonu nie je ľahká úloha. Je to ako hrať Tetris stále. Ak platíte príliš veľa za výpočtový výkon s nízkou priemernou spotrebou (povedzme ~10 %), odporúčame vám pozrieť sa na produkty založené na AWS Fargate alebo Virtual Kubelet. Sú postavené na fakturačnom modeli bez servera/platby za použitie, ktorý môže byť v takýchto podmienkach lacnejší.

2. Sondy živosti a pripravenosti

V predvolenom nastavení nie sú v Kubernetes povolené kontroly živosti a pripravenosti. A niekedy ich zabudnú zapnúť...

Ale ako inak môžete spustiť reštart služby v prípade závažnej chyby? A ako nástroj na vyrovnávanie zaťaženia vie, že modul je pripravený prijať premávku? Alebo že zvládne väčšiu premávku?

Tieto testy sa často navzájom zamieňajú:

  • Živosť — kontrola „prežitia“, ktorá reštartuje modul, ak zlyhá;
  • pripravenosť — kontrola pripravenosti, ak zlyhá, odpojí modul od služby Kubernetes (toto je možné skontrolovať pomocou kubectl get endpoints) a premávka sa k nemu dostane až po úspešnom dokončení ďalšej kontroly.

Obe tieto kontroly VYKONÁVANÉ POČAS CELÉHO ŽIVOTNÉHO CYKLU POD. Je to veľmi dôležité.

Bežnou mylnou predstavou je, že sondy pripravenosti sa spustia iba pri spustení, takže balancér môže vedieť, že modul je pripravený (Ready) a môže začať spracovávať návštevnosť. Je to však len jedna z možností ich využitia.

Ďalšou je možnosť zistenia, že prevádzka na podu je nadmerná a preťažuje to (alebo modul vykonáva výpočty náročné na zdroje). V tomto prípade pomáha kontrola pripravenosti znížte zaťaženie modulu a „ochlaďte ho“.. Úspešné absolvovanie kontroly pripravenosti v budúcnosti umožňuje opäť zvýšte zaťaženie podu. V tomto prípade (ak test pripravenosti zlyhá) by zlyhanie testu živosti bolo veľmi kontraproduktívne. Prečo reštartovať pod, ktorý je zdravý a tvrdo pracuje?

Preto je v niektorých prípadoch lepšia žiadna kontrola, ako jej aktivácia s nesprávne nakonfigurovanými parametrami. Ako je uvedené vyššie, ak kontrola živosti kópie kontrola pripravenosti, potom máte veľké problémy. Možnou možnosťou je konfigurácia iba test pripravenostiA nebezpečná živosť nechať bokom.

Oba typy kontrol by nemali zlyhať, keď zlyhajú bežné závislosti, inak to povedie ku kaskádovému (lavínovému) zlyhaniu všetkých modulov. Inými slovami, neubližuj si.

3. LoadBalancer pre každú službu HTTP

S najväčšou pravdepodobnosťou máte vo svojom klastri HTTP služby, ktoré by ste chceli preposlať do vonkajšieho sveta.

Ak otvoríte službu ako type: LoadBalancer, jeho kontrolór (v závislosti od poskytovateľa služieb) poskytne a dohodne externý LoadBalancer (nemusí bežať nevyhnutne na L7, ale dokonca aj na L4), čo môže ovplyvniť náklady (externá statická adresa IPv4, výpočtový výkon, fakturácia za sekundu ) z dôvodu potreby vytvorenia veľkého množstva takýchto zdrojov.

V tomto prípade je oveľa logickejšie použiť jeden externý vyrovnávač zaťaženia, otváranie služieb ako type: NodePort. Alebo ešte lepšie, rozšíriť niečo ako nginx-ingress-controller (Alebo traefik), ktorý bude jediný Port uzla koncový bod spojený s externým nástrojom na vyvažovanie záťaže a bude smerovať prevádzku v klastri pomocou vniknutiu- Zdroje Kubernetes.

Iné vnútroklastrové (mikro)služby, ktoré na seba vzájomne pôsobia, môžu „komunikovať“ pomocou služieb ako napr ClusterIP a vstavaný mechanizmus zisťovania služieb prostredníctvom DNS. Jednoducho nepoužívajte ich verejné DNS/IP, pretože to môže ovplyvniť latenciu a zvýšiť náklady na cloudové služby.

4. Automatické škálovanie klastra bez zohľadnenia jeho vlastností

Pri pridávaní uzlov do klastra a ich odstraňovaní z klastra by ste sa nemali spoliehať na niektoré základné metriky, ako je využitie procesora v týchto uzloch. Plánovanie strukov musí brať do úvahy mnohé obmedzenia, ako je afinita pod/uzlov, kazy a tolerancie, požiadavky na zdroje, QoS atď. Používanie externého autoscaleru, ktorý nezohľadňuje tieto nuansy, môže viesť k problémom.

Predstavte si, že by sa mal naplánovať určitý modul, ale je potrebné/rozobrať všetok dostupný výkon CPU a modul uviazne v stave Pending. Externý autoscaler vidí priemernú aktuálnu záťaž CPU (nie požadovanú) a neiniciuje expanziu (škálovanie) - nepridá ďalší uzol. V dôsledku toho nebude tento modul naplánovaný.

V tomto prípade reverzné škálovanie (rozsah) — odstránenie uzla z klastra je vždy ťažšie implementovať. Predstavte si, že máte stavový modul (s pripojeným trvalým ukladacím priestorom). Trvalé objemy zvyčajne patrí špecifická zóna dostupnosti a nie sú replikované v regióne. Ak teda externý automatický škálovač vymaže uzol s týmto modulom, plánovač nebude môcť naplánovať tento modul na inom uzle, pretože to možno vykonať iba v zóne dostupnosti, kde sa nachádza trvalé úložisko. Modul bude zaseknutý v stave Pending.

Veľmi populárny v komunite Kubernetes cluster-autoscaler. Beží na klastri, podporuje API od hlavných cloudových poskytovateľov, zohľadňuje všetky obmedzenia a môže sa škálovať vo vyššie uvedených prípadoch. Je tiež schopný škálovať pri zachovaní všetkých nastavených limitov, čím šetrí peniaze (ktoré by inak boli vynaložené na nevyužitú kapacitu).

5. Zanedbávanie schopností IAM/RBAC

Dajte si pozor na používanie používateľov IAM s trvalými tajomstvami pre stroje a aplikácie. Zorganizujte dočasný prístup pomocou rolí a servisných účtov (servisné účty).

Často sa stretávame s tým, že prístupové kľúče (a tajomstvá) sú napevno zakódované v konfigurácii aplikácie, ako aj zanedbávanie rotácie tajomstiev napriek tomu, že máte prístup do Cloud IAM. V prípade potreby použite roly IAM a servisné účty namiesto používateľov.

10 bežných chýb pri používaní Kubernetes

Zabudnite na kube2iam a prejdite priamo na roly IAM pre servisné účty (ako je popísané v poznámka s rovnakým názvom Štěpán Vraný):

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-app-role
  name: my-serviceaccount
  namespace: default

Jedna anotácia. Nie je to také ťažké, však?

Taktiež neudeľujte privilégiá pre servisné účty a profily inštancií admin и cluster-adminak to nepotrebujú. Toto je trochu náročnejšie na implementáciu, najmä v RBAC K8, ale rozhodne stojí za námahu.

6. Nespoliehajte sa na automatickú anti-afinitu pre strúčiky

Predstavte si, že máte tri repliky nejakého nasadenia na uzle. Uzol padá a spolu s ním aj všetky repliky. Nepríjemná situácia, však? Ale prečo boli všetky repliky na rovnakom uzle? Nemá Kubernetes poskytovať vysokú dostupnosť (HA)?!

Bohužiaľ, plánovač Kubernetes z vlastnej iniciatívy nespĺňa pravidlá samostatnej existencie (anti-afinita) pre lusky. Musia byť výslovne uvedené:

// опущено для краткости
      labels:
        app: zk
// опущено для краткости
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - zk
              topologyKey: "kubernetes.io/hostname"

To je všetko. Teraz budú moduly naplánované na rôznych uzloch (táto podmienka sa kontroluje iba počas plánovania, ale nie počas ich prevádzky - preto requiredDuringSchedulingIgnoredDuringExecution).

Tu hovoríme o podAntiAffinity na rôznych uzloch: topologyKey: "kubernetes.io/hostname", - a nie o rôznych zónach dostupnosti. Ak chcete zaviesť plnohodnotnú HA, budete musieť túto tému prehĺbiť.

7. Ignorovanie PodDisruptionBudgets

Predstavte si, že máte produkčnú záťaž na klastri Kubernetes. Pravidelne musia byť uzly a samotný klaster aktualizované (alebo vyradené z prevádzky). PodDisruptionBudget (PDB) je niečo ako zmluva o záruke služieb medzi správcami klastra a používateľmi.

PDB vám umožňuje vyhnúť sa prerušeniam služieb spôsobeným nedostatkom uzlov:

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: zookeeper

V tomto príklade ako používateľ klastra poviete správcom: „Hej, mám službu zookeepera a nech robíte čokoľvek, chcel by som mať vždy k dispozícii aspoň 2 repliky tejto služby.“

Môžete si o tom prečítať viac tu.

8. Viacerí používatelia alebo prostredia v spoločnom klastri

Priestory názvov Kubernetes (priestor mien) neposkytujú silnú izoláciu.

Bežnou mylnou predstavou je, že ak nasadíte neprodukčné zaťaženie do jedného menného priestoru a produkčné zaťaženie do iného, sa navzájom nijako neovplyvnia... Určitú úroveň izolácie je však možné dosiahnuť pomocou požiadaviek/obmedzení zdrojov, nastavením kvót a nastavením prioritných tried. Určitú „fyzickú“ izoláciu v dátovej rovine poskytujú afinity, tolerancie, škvrny (alebo selektory uzlov), ale takéto oddelenie je dosť komplikovaná realizovať.

Tí, ktorí potrebujú kombinovať oba typy pracovných záťaží v rovnakom klastri, sa budú musieť vysporiadať so zložitosťou. Ak takáto potreba neexistuje a môžete si ju dovoliť ešte jeden klaster (povedzme vo verejnom cloude), potom je lepšie to urobiť. Tým sa dosiahne oveľa vyššia úroveň izolácie.

9. ExternalTrafficPolicy: Cluster

Veľmi často vidíme, že všetka prevádzka vo vnútri klastra prichádza cez službu ako NodePort, pre ktorú je nastavená predvolená politika externalTrafficPolicy: Cluster... Znamená to, že Port uzla je otvorený na každom uzle v klastri a ktorýkoľvek z nich môžete použiť na interakciu s požadovanou službou (súborom modulov).

10 bežných chýb pri používaní Kubernetes

Zároveň sú skutočné moduly spojené s vyššie uvedenou službou NodePort zvyčajne dostupné iba na určitom podmnožina týchto uzlov. Inými slovami, ak sa pripojím k uzlu, ktorý nemá požadovaný modul, prepošle prevádzku do iného uzla, pridanie chmeľu a zvýšenie latencie (ak sú uzly umiestnené v rôznych zónach dostupnosti/dátových centrách, latencia môže byť dosť vysoká; navyše sa zvýšia náklady na výstupnú prevádzku).

Na druhej strane, ak má určitá služba Kubernetes nastavenú politiku externalTrafficPolicy: Local, potom sa NodePort otvorí iba na tých uzloch, kde skutočne bežia požadované moduly. Pri použití externého vyrovnávača záťaže, ktorý kontroluje stav (zdravotná kontrola) koncové body (ako to robí AWS ELB), On bude posielať premávku len do nevyhnutných uzlov, čo bude mať priaznivý vplyv na meškania, výpočtové potreby, výstupné účty (a zdravý rozum diktuje to isté).

Je veľká šanca, že už niečo podobné používate traefik alebo nginx-ingress-controller ako koncový bod NodePort (alebo LoadBalancer, ktorý tiež používa NodePort) na smerovanie vstupnej prevádzky HTTP a nastavenie tejto možnosti môže výrazne znížiť latenciu takýchto požiadaviek.

В túto publikáciu Môžete sa dozvedieť viac o externalTrafficPolicy, jej výhodách a nevýhodách.

10. Neviažte sa na zhluky a nezneužívajte riadiacu rovinu

Predtým bolo zvyčajné volať servery správnymi menami: Anton, HAL9000 a Colossus... Dnes ich nahradili náhodne generované identifikátory. Zvyk však zostal a teraz vlastné mená idú do zhlukov.

Typický príbeh (založený na skutočných udalostiach): všetko to začalo proof of concept, takže klaster mal hrdé meno Testovanie… Prešli roky a STÁLE sa používa vo výrobe a každý sa ho bojí dotknúť.

Na tom, ako sa zhluky menia na domácich miláčikov, nie je nič zábavné, preto ich počas cvičenia odporúčame pravidelne odstraňovať zotavenie po havárii (toto pomôže chaosové inžinierstvo - približne. preklad.). Okrem toho by nebolo na škodu popracovať na riadiacej vrstve (riadiaca rovina). Báť sa ho dotknúť nie je dobré znamenie. atď mŕtvy? Chlapci, máte vážne problémy!

Na druhej strane by ste sa nemali nechať uniesť manipuláciou. S časom riadiaca vrstva sa môže spomaliť. S najväčšou pravdepodobnosťou je to spôsobené veľkým počtom objektov, ktoré sa vytvárajú bez ich rotácie (bežná situácia pri použití Helmu s predvolenými nastaveniami, preto sa jeho stav v configmaps/secrets neaktualizuje - v dôsledku toho sa v kontrolná vrstva) alebo s neustálou úpravou objektov kube-api (na automatické škálovanie, pre CI/CD, na monitorovanie, protokoly udalostí, ovládače atď.).

Okrem toho odporúčame skontrolovať zmluvy SLA/SLO so spravovaným poskytovateľom Kubernetes a venovať pozornosť zárukám. Predajca môže zaručiť kontrola dostupnosti vrstvy (alebo jeho podkomponentov), ​​ale nie oneskorenie požiadaviek p99, ktoré mu odošlete. Inými slovami, môžete vstúpiť kubectl get nodesa dostanete odpoveď až po 10 minútach, pričom nejde o porušenie podmienok zmluvy o poskytovaní služieb.

11. Bonus: použitie najnovšieho štítku

Ale toto je už klasika. V poslednej dobe sa s touto technikou stretávame menej často, keďže mnohí, poučení z trpkej skúsenosti, značku prestali používať :latest a začali pripínať verzie. Hurá!

ECR zachováva nemennosť obrázkových značiek; Odporúčame vám oboznámiť sa s touto pozoruhodnou funkciou.

Zhrnutie

Nečakajte, že všetko bude fungovať cez noc: Kubernetes nie je všeliek. Zlá aplikácia zostane takto aj v Kubernetes (a zrejme bude ešte horšie). Neopatrnosť povedie k nadmernej zložitosti, pomalej a stresujúcej práci riadiacej vrstvy. Okrem toho riskujete, že zostanete bez stratégie obnovy po havárii. Nečakajte, že Kubernetes poskytne izoláciu a vysokú dostupnosť hneď po vybalení. Venujte nejaký čas tomu, aby bola vaša aplikácia skutočne natívna v cloude.

S neúspešnými skúsenosťami rôznych tímov sa môžete zoznámiť v túto zbierku príbehov od Henninga Jacobsa.

Tí, ktorí chcú pridať do zoznamu chýb uvedených v tomto článku, nás môžu kontaktovať na Twitteri (@MarekBartik, @MstrsObserver).

PS od prekladateľa

Prečítajte si aj na našom blogu:

Zdroj: hab.com

Pridať komentár