10 uobičajenih Kubernetes grešaka

Bilješka. transl.: Autori ovog članka su inženjeri iz male češke kompanije pipetail. Uspjeli su sastaviti divnu listu [ponekad banalnih, ali ipak] vrlo hitnih problema i zabluda vezanih za rad Kubernetes klastera.

10 uobičajenih Kubernetes grešaka

Tokom godina korišćenja Kubernetesa, radili smo sa velikim brojem klastera (upravljanih i neupravljanih - na GCP, AWS i Azure). Vremenom smo počeli da primećujemo da se neke greške stalno ponavljaju. Međutim, u tome nema sramote: većinu smo uradili sami!

Članak sadrži najčešće greške i spominje kako ih ispraviti.

1. Resursi: zahtjevi i ograničenja

Ova stavka definitivno zaslužuje najveću pažnju i prvo mjesto na listi.

CPU zahteva obično ili uopće nije navedeno ili ima vrlo nisku vrijednost (da postavite što više mahuna na svaki čvor). Dakle, čvorovi postaju preopterećeni. U vremenima velikog opterećenja procesorska snaga čvora se u potpunosti koristi i određeno radno opterećenje prima samo ono što je "zatražilo" CPU throttling. To dovodi do povećanog kašnjenja aplikacije, vremenskog ograničenja i drugih neugodnih posljedica. (Više o ovome pročitajte u našem drugom nedavnom prijevodu: “CPU ograničenja i agresivno prigušivanje u Kubernetesu" - cca. prevod)

BestEffort (ekstremno ne preporučeno):

resources: {}

Ekstremno nizak CPU zahtjev (izuzetno ne preporučeno):

   resources:
      Requests:
        cpu: "1m"

S druge strane, prisustvo CPU ograničenja može dovesti do nerazumnog preskakanja ciklusa takta od strane podova, čak i ako procesor čvora nije u potpunosti učitan. Opet, ovo može dovesti do povećanog kašnjenja. Kontroverze se nastavljaju oko parametra CPU CFS kvota u Linux kernelu i CPU throttling u zavisnosti od postavljenih ograničenja, kao i onemogućavanje CFS kvote... Jao, ograničenja CPU-a mogu uzrokovati više problema nego što mogu riješiti. Više informacija o ovome možete pronaći na linku ispod.

Pretjerana selekcija (preterivanje) problemi s pamćenjem mogu dovesti do većih problema. Dostizanje ograničenja CPU-a podrazumijeva preskakanje ciklusa takta, dok dostizanje ograničenja memorije podrazumijeva ubijanje modula. Da li ste ikada posmatrali OOMkill? Da, upravo o tome govorimo.

Želite li smanjiti vjerovatnoću da se ovo dogodi? Nemojte previše dodijeliti memoriju i koristite zajamčeni QoS (kvalitet usluge) postavljanjem zahtjeva za memorijom na ograničenje (kao u primjeru ispod). Više o ovome pročitajte u Prezentacije Henninga Jacobsa (Glavni inženjer u Zalandu).

Burstable (veća šansa da dobijete OOMkill):

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

Garantovano:

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

Šta će potencijalno pomoći pri postavljanju resursa?

Uz pomoć metrics-server možete vidjeti trenutnu potrošnju CPU resursa i korištenje memorije po podovima (i kontejnerima unutar njih). Najvjerovatnije ga već koristite. Samo pokrenite sljedeće naredbe:

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

Međutim, oni prikazuju samo trenutnu upotrebu. Može vam dati grubu predstavu o redu veličine, ali na kraju će vam trebati historija promjena metrike tokom vremena (da odgovorite na pitanja poput: “Koliko je bilo maksimalno opterećenje CPU-a?”, “Koliko je bilo opterećenje juče ujutro?”, itd.). Za ovo možete koristiti Prometej, DataDog i drugi alati. Oni jednostavno dobijaju metriku od metrics-servera i pohranjuju ih, a korisnik ih može upitati i u skladu s tim nacrtati.

VerticalPodAutoscaler dozvoljava automatizirati ovaj proces. Prati istoriju korišćenja CPU-a i memorije i postavlja nove zahteve i ograničenja na osnovu ovih informacija.

Efikasno korištenje računarske snage nije lak zadatak. To je kao da stalno igrate Tetris. Ako plaćate previše za računarsku snagu sa niskom prosječnom potrošnjom (recimo ~10%), preporučujemo da pogledate proizvode bazirane na AWS Fargate ili Virtual Kubelet. Izgrađeni su na modelu naplate bez servera/plati po upotrebi, što bi u takvim uslovima moglo biti jeftinije.

2. Sonde za živost i spremnost

Podrazumevano, provjere živosti i spremnosti nisu omogućene u Kubernetesu. I ponekad zaborave da ih uključe...

Ali kako drugačije možete pokrenuti ponovno pokretanje usluge u slučaju fatalne greške? I kako balansator opterećenja zna da je pod spreman da prihvati promet? Ili da može podnijeti veći promet?

Ovi testovi se često brkaju jedni s drugima:

  • Život — provjera “preživljivosti”, koja ponovo pokreće modul ako ne uspije;
  • Spremnost — provjera spremnosti, ako ne uspije, isključuje pod s Kubernetes servisa (ovo se može provjeriti pomoću kubectl get endpoints) i promet do njega ne stiže dok se sljedeća provjera ne završi uspješno.

Obje ove provjere IZVODI SE TOKOM CIJELOG ŽIVOTNOG CIKLUSA POD. To je veoma važno.

Uobičajena zabluda je da se sonde spremnosti pokreću samo pri pokretanju kako bi balanser mogao znati da je modul spreman (Ready) i može započeti obradu prometa. Međutim, ovo je samo jedna od opcija za njihovu upotrebu.

Druga je mogućnost da se otkrije da je promet na podlozi pretjeran i preopterećuje ga (ili pod izvodi proračune koji zahtijevaju velike resurse). U ovom slučaju pomaže provjera spremnosti smanjiti opterećenje na mahunu i "ohladiti" je. Uspješan završetak provjere spremnosti u budućnosti omogućava ponovo povećajte opterećenje na mahunu. U ovom slučaju (ako test spremnosti ne uspije), neuspjeh testa životnosti bio bi vrlo kontraproduktivan. Zašto ponovo pokrenuti pod koji je zdrav i naporan?

Stoga je u nekim slučajevima bolje da nema provjera nego da ih omogućite s pogrešno konfiguriranim parametrima. Kao što je gore navedeno, ako provjera živosti kopije provjera spremnosti, onda ste u velikoj nevolji. Moguća opcija je konfiguracija samo test spremnostii opasna životnost ostavi po strani.

Obje vrste provjera ne bi trebale propasti kada uobičajene ovisnosti ne uspiju, inače će to dovesti do kaskadnog (lavina) neuspjeha svih podova. Drugim riječima, nemojte se povrediti.

3. LoadBalancer za svaku HTTP uslugu

Najvjerovatnije imate HTTP usluge u svom klasteru koje biste željeli proslijediti u vanjski svijet.

Ako otvorite uslugu kao type: LoadBalancer, njegov kontroler (ovisno o provajderu usluge) će obezbijediti i pregovarati o eksternom LoadBalancer-u (koji ne mora nužno raditi na L7, već čak i na L4), a to može utjecati na cijenu (eksterna statička IPv4 adresa, računarska snaga, naplata po sekundi ) zbog potrebe stvaranja velikog broja takvih resursa.

U ovom slučaju, mnogo je logičnije koristiti jedan eksterni balansator opterećenja, otvarajući usluge kao type: NodePort. Ili još bolje, proširite nešto slično nginx-ingress-kontroler (ili traefik), koji će biti jedini NodePort krajnja točka povezana s vanjskim balansatorom opterećenja i usmjerit će promet u klaster koristeći ulazak-Kubernetes resursi.

Druge unutar-klasterske (mikro)usluge koje međusobno komuniciraju mogu “komunicirati” koristeći usluge kao što su ClusterIP i ugrađeni mehanizam za otkrivanje usluga putem DNS-a. Samo nemojte koristiti njihov javni DNS/IP, jer to može utjecati na kašnjenje i povećati cijenu usluga u oblaku.

4. Automatsko skaliranje klastera bez uzimanja u obzir njegovih karakteristika

Kada dodajete čvorove i uklanjate ih iz klastera, ne biste se trebali oslanjati na neke osnovne metrike kao što je korištenje CPU-a na tim čvorovima. Planiranje podova mora uzeti u obzir mnoge ograničenja, kao što su afinitet pod/čvorova, mrlje i tolerancije, zahtjevi za resursima, QoS, itd. Upotreba eksternog automatskog skalera koji ne uzima u obzir ove nijanse može dovesti do problema.

Zamislite da bi određeni pod trebao biti zakazan, ali je sva raspoloživa CPU snaga zatražena/rastavljena i pod zaglavi u stanju Pending. Vanjski autoscaler vidi prosječno trenutno opterećenje CPU-a (ne traženo) i ne pokreće proširenje (razmjerno) - ne dodaje još jedan čvor. Kao rezultat toga, ova grupa neće biti zakazana.

U ovom slučaju, obrnuto skaliranje (razmjerno) — uklanjanje čvora iz klastera je uvijek teže implementirati. Zamislite da imate modul sa stanjem (sa povezanim postojanim skladištem). Persistent volumes obično pripadaju određena zona dostupnosti i ne repliciraju se u regionu. Prema tome, ako eksterni automatski skaler izbriše čvor sa ovim podom, planer neće moći zakazati ovaj pod na drugom čvoru, jer se to može učiniti samo u zoni dostupnosti u kojoj se nalazi trajna pohrana. Pod će biti zaglavljen u stanju Pending.

Veoma popularan u Kubernetes zajednici cluster-autoscaler. Radi na klasteru, podržava API-je velikih provajdera u oblaku, uzima u obzir sva ograničenja i može se skalirati u gore navedenim slučajevima. Takođe je u mogućnosti da se poveća uz održavanje svih postavljenih ograničenja, čime se štedi novac (koji bi inače bio potrošen na neiskorišteni kapacitet).

5. Zanemarivanje IAM/RBAC sposobnosti

Čuvajte se korištenja IAM korisnika sa trajnim tajnama za mašine i aplikacije. Organizirajte privremeni pristup koristeći uloge i servisne račune (uslužni računi).

Često se susrećemo sa činjenicom da su pristupni ključevi (i tajne) tvrdo kodirani u konfiguraciji aplikacije, kao i da zanemarujemo rotaciju tajni uprkos tome što imamo pristup Cloud IAM-u. Koristite IAM uloge i servisne račune umjesto korisnika gdje je to prikladno.

10 uobičajenih Kubernetes grešaka

Zaboravite na kube2iam i idite direktno na IAM uloge za servisne račune (kao što je opisano u istoimena bilješka Š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 napomena. Nije tako teško, zar ne?

Također, nemojte dodijeliti privilegije za račune usluge i profile instance admin и cluster-adminako im ne zatreba. Ovo je malo teže implementirati, posebno u RBAC K8s, ali je svakako vrijedno truda.

6. Nemojte se oslanjati na automatski anti-afinitet za mahune

Zamislite da imate tri replike neke implementacije na čvoru. Čvor pada, a zajedno s njim i sve replike. Neprijatna situacija, zar ne? Ali zašto su sve replike bile na istom čvoru? Zar Kubernetes ne bi trebao pružiti visoku dostupnost (HA)?!

Nažalost, Kubernetes planer, samoinicijativno, ne poštuje pravila odvojenog postojanja (protiv afiniteta) za mahune. Oni moraju biti eksplicitno navedeni:

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

To je sve. Sada će podovi biti zakazani na različitim čvorovima (ovaj uvjet se provjerava samo tokom zakazivanja, ali ne i tokom njihovog rada - stoga requiredDuringSchedulingIgnoredDuringExecution).

Ovdje govorimo o podAntiAffinity na različitim čvorovima: topologyKey: "kubernetes.io/hostname", - a ne o različitim zonama dostupnosti. Da biste implementirali punopravni HA, morat ćete dublje proučiti ovu temu.

7. Ignoriranje PodDisruptionBudgets

Zamislite da imate proizvodno opterećenje na Kubernetes klasteru. Povremeno, čvorovi i sam klaster moraju se ažurirati (ili poništiti). PodDisruptionBudget (PDB) je nešto poput ugovora o garanciji usluge između administratora klastera i korisnika.

PDB vam omogućava da izbjegnete prekide usluge uzrokovane nedostatkom čvorova:

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

U ovom primjeru, vi, kao korisnik klastera, kažete administratorima: „Hej, ja imam uslugu čuvara zoološkog vrta, i bez obzira što radiš, želio bih da imam barem 2 replike ove usluge uvijek dostupne.“

Možete pročitati više o tome ovdje.

8. Više korisnika ili okruženja u zajedničkom klasteru

Kubernetes imenski prostori (imenski prostori) ne pružaju jaku izolaciju.

Uobičajena zabluda je da ako implementirate ne-prod load u jedan imenski prostor i prod load u drugi, onda neće uticati jedno na drugo ni na koji način... Međutim, određeni nivo izolacije se može postići korištenjem zahtjeva/ograničenja resursa, postavljanjem kvota i postavljanjem prioritetnih klasa. Neka "fizička" izolacija u podatkovnoj ravni je osigurana afinitetima, tolerancijama, mrljama (ili selektorima čvorova), ali takvo razdvajanje je prilično teško implementirati.

Oni koji trebaju kombinirati obje vrste opterećenja u istom klasteru morat će se suočiti sa složenošću. Ako nema takve potrebe, a možete si je priuštiti još jedan klaster (recimo, u javnom oblaku), onda je bolje to učiniti. Time će se postići mnogo viši nivo izolacije.

9. externalTrafficPolicy: Klaster

Vrlo često vidimo da sav promet unutar klastera dolazi preko servisa kao što je NodePort, za koji je postavljena zadana politika externalTrafficPolicy: Cluster... Znači to NodePort je otvoren na svakom čvoru u klasteru i možete koristiti bilo koji od njih za interakciju sa željenom uslugom (skupom podova).

10 uobičajenih Kubernetes grešaka

U isto vrijeme, pravi podovi povezani s gore spomenutom uslugom NodePort obično su dostupni samo na određenom podskup ovih čvorova. Drugim riječima, ako se povežem na čvor koji nema traženi pod, on će proslijediti promet drugom čvoru, dodavanje poskoka i povećanje latencije (ako se čvorovi nalaze u različitim zonama dostupnosti/podatkovnim centrima, kašnjenje može biti prilično veliko; osim toga, troškovi izlaznog saobraćaja će se povećati).

S druge strane, ako određeni Kubernetes servis ima postavljenu politiku externalTrafficPolicy: Local, tada se NodePort otvara samo na onim čvorovima na kojima su potrebni podovi zapravo pokrenuti. Kada koristite vanjski balanser opterećenja koji provjerava stanje (zdravstvena kontrola) krajnje tačke (kako radi AWS ELB), On će slati promet samo do potrebnih čvorova, što će blagotvorno uticati na kašnjenja, potrebe za računarom, izlazne račune (a zdrav razum nalaže isto).

Postoji velika šansa da već koristite nešto poput traefik ili nginx-ingress-kontroler kao NodePort krajnja tačka (ili LoadBalancer, koji takođe koristi NodePort) za rutiranje HTTP ulaznog saobraćaja, a postavljanje ove opcije može značajno smanjiti kašnjenje za takve zahteve.

В ovu publikaciju Možete saznati više o externalTrafficPolicy, njenim prednostima i nedostacima.

10. Nemojte se vezivati ​​za klastere i ne zloupotrebljavajte kontrolnu ravninu

Ranije je bilo uobičajeno nazivati ​​servere vlastitim imenima: Anton, HAL9000 i Colossus... Danas su ih zamijenili nasumično generirani identifikatori. Međutim, navika je ostala, a sada vlastita imena idu u klastere.

Tipična priča (zasnovana na stvarnim događajima): sve je počelo dokazom koncepta, tako da je klaster imao ponosno ime testiranje… Prošle su godine, a još uvijek se koristi u proizvodnji, a svi se boje da ga dodirnu.

Nema ništa zabavno u tome da se grozdovi pretvaraju u kućne ljubimce, pa preporučujemo da ih povremeno uklanjate dok vježbate oporavak od katastrofe (ovo će pomoći haos inženjering - cca. prevod). Osim toga, ne bi škodilo raditi na kontrolnom sloju (kontrolni avion). Bojiti se da ga dodirnete nije dobar znak. Itd smrt? Ljudi, stvarno ste u nevolji!

S druge strane, ne biste se trebali zanositi manipuliranjem. Sa vremenom kontrolni sloj može postati spor. Najvjerovatnije je to zbog velikog broja objekata koji se kreiraju bez njihove rotacije (česta situacija kada se koristi Helm sa zadanim postavkama, zbog čega se njegovo stanje u configmapama/tajnama ne ažurira - kao rezultat toga, hiljade objekata se akumuliraju u kontrolni sloj) ili sa stalnim uređivanjem kube-api objekata (za automatsko skaliranje, za CI/CD, za praćenje, evidencije događaja, kontrolere, itd.).

Osim toga, preporučujemo da provjerite SLA/SLO ugovore sa upravljanim Kubernetes provajderom i obratite pažnju na garancije. Prodavac može garantovati dostupnost kontrolnog sloja (ili njegove podkomponente), ali ne i p99 kašnjenje zahtjeva koje mu šaljete. Drugim riječima, možete ući kubectl get nodes, a odgovor ćete dobiti tek nakon 10 minuta i to neće predstavljati kršenje uslova ugovora o usluzi.

11. Bonus: korištenje najnovije oznake

Ali ovo je već klasik. U posljednje vrijeme rjeđe nailazimo na ovu tehniku, jer su mnogi, poučeni iz gorkog iskustva, prestali koristiti oznaku :latest i počeo zakačiti verzije. Ura!

ECR održava nepromjenjivost oznaka slike; Preporučujemo da se upoznate sa ovom izuzetnom funkcijom.

Rezime

Ne očekujte da će sve raditi preko noći: Kubernetes nije lijek za sve. Loša aplikacija tako će ostati čak iu Kubernetesu (i vjerovatno će biti gore). Nepažnja će dovesti do prevelike složenosti, sporog i stresnog rada kontrolnog sloja. Osim toga, rizikujete da ostanete bez strategije oporavka od katastrofe. Ne očekujte da će Kubernetes pružiti izolaciju i visoku dostupnost odmah iz kutije. Provedite neko vrijeme da svoju aplikaciju učinite istinski izvornom u oblaku.

Možete se upoznati sa neuspješnim iskustvima raznih timova u ovu zbirku priča autora Henninga Jacobsa.

Oni koji žele dodati na listu grešaka datih u ovom članku mogu nas kontaktirati na Twitteru (@MarekBartik, @MstrsObserver).

PS od prevodioca

Pročitajte i na našem blogu:

izvor: www.habr.com

Dodajte komentar