10 uobičajenih pogrešaka pri korištenju Kubernetesa

Bilješka. prev.: Autori ovog članka su inženjeri iz male češke tvrtke pipetail. Uspjeli su sastaviti prekrasan popis [ponekad banalnih, ali ipak] vrlo hitnih problema i zabluda povezanih s radom Kubernetes klastera.

10 uobičajenih pogrešaka pri korištenju Kubernetesa

Tijekom godina korištenja Kubernetesa, radili smo s velikim brojem klastera (i upravljanih i neupravljanih – na GCP-u, AWS-u i Azureu). S vremenom smo počeli primjećivati ​​da se neke greške stalno ponavljaju. No, tu nema nikakve sramote: većinu smo napravili sami!

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

1. Resursi: zahtjevi i ograničenja

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

CPU zahtjev obično ili uopće nije navedeno ili ima vrlo nisku vrijednost (kako biste postavili što više mahuna na svaki čvor). Stoga čvorovi postaju preopterećeni. Tijekom vremena velikog opterećenja, procesorska snaga čvora je u potpunosti iskorištena i određeno radno opterećenje prima samo ono što je "zatražilo" CPU prigušivanje. To dovodi do povećane latencije aplikacije, vremenskih ograničenja i drugih neugodnih posljedica. (Pročitajte više o tome u našem drugom nedavnom prijevodu: "CPU ograničenja i agresivno prigušivanje u Kubernetesu" - cca. prev.)

BestEffort (krajnje ne preporučeno):

resources: {}

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

   resources:
      Requests:
        cpu: "1m"

S druge strane, prisutnost CPU ograničenja može dovesti do nerazumnog preskakanja taktnih ciklusa od strane modula, čak i ako procesor čvora nije u potpunosti učitan. Opet, to može dovesti do povećanih kašnjenja. Kontroverze se nastavljaju oko parametra CPU CFS kvota u Linux kernelu i CPU throttling ovisno o postavljenim ograničenjima, kao i onemogućavanje CFS kvote... Jao, CPU ograničenja mogu uzrokovati više problema nego što ih mogu riješiti. Više informacija o tome možete pronaći na poveznici ispod.

Pretjeran izbor (pretjerano zalaganje) problemi s pamćenjem mogu dovesti do većih problema. Dosezanje ograničenja CPU-a podrazumijeva preskakanje taktnih ciklusa, dok dostizanje ograničenja memorije podrazumijeva ubijanje modula. Jeste li ikada promatrali OOMkill? Da, upravo o tome govorimo.

Želite li smanjiti vjerojatnost da se to dogodi? Nemojte previše dodijeliti memoriju i koristite Guaranteed QoS (Quality of Service) postavljanjem zahtjeva za memoriju na ograničenje (kao u donjem primjeru). Pročitajte više o ovome u Prezentacije Henninga Jacobsa (Vodeći inženjer u Zalandu).

Rasprsnuti (veća šansa da vas OOM ubije):

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

Zajamčena:

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

Što bi potencijalno moglo pomoći pri postavljanju resursa?

S metrics-poslužitelj možete vidjeti trenutnu potrošnju CPU resursa i korištenje memorije po podovima (i spremnicima unutar njih). Najvjerojatnije ga već koristite. Samo pokrenite sljedeće naredbe:

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

Međutim, prikazuju samo trenutnu upotrebu. Može vam dati grubu ideju o redu veličine, ali u konačnici će vam trebati povijest promjena metrike tijekom vremena (kako bi odgovorili na pitanja poput: "Koliko je bilo najveće opterećenje CPU-a?", "Koliko je bilo opterećenje jučer ujutro?", itd.). Za ovo možete koristiti Prometej, DataDog i drugi alati. Oni jednostavno dobivaju metriku s metrics-poslužitelja i pohranjuju je, a korisnik ih može upitati i iscrtati u skladu s tim.

VerticalPodAutoscaler to omogućuje automatizirati ovaj proces. Prati povijest korištenja procesora i memorije te postavlja nove zahtjeve i ograničenja na temelju tih informacija.

Učinkovito korištenje računalne snage nije lak zadatak. To je kao da stalno igrate Tetris. Ako plaćate previše za računalnu snagu s niskom prosječnom potrošnjom (recimo ~10%), preporučujemo da pogledate proizvode temeljene na AWS Fargate ili Virtual Kubelet. Izgrađeni su na modelu naplate bez poslužitelja/plaćanja po korištenju, što se u takvim uvjetima može pokazati jeftinijim.

2. Sonde za živost i spremnost

Prema zadanim postavkama, provjere živosti i spremnosti nisu omogućene u Kubernetesu. A ponekad ih zaborave upaliti...

Ali kako drugačije možete pokrenuti ponovno pokretanje usluge u slučaju kobne pogreške? I kako balanser opterećenja zna da je mahuna spremna prihvatiti promet? Ili da može podnijeti više prometa?

Ovi se testovi često međusobno brkaju:

  • Živost — provjera "preživljavanja", koja ponovno pokreće kapsulu ako ne uspije;
  • Spremnost — provjera spremnosti, ako ne uspije, odspaja pod s usluge Kubernetes (ovo se može provjeriti pomoću kubectl get endpoints) i promet ne dolazi do njega dok sljedeća provjera nije uspješno dovršena.

Obje ove provjere IZVODI TIJEKOM CIJELOG ŽIVOTNOG CIKLUSA PODA. Vrlo je važno.

Uobičajena zabluda je da se sonde spremnosti pokreću samo pri pokretanju kako bi balanser mogao znati da je kapsula spremna (Ready) i može početi s obradom prometa. Međutim, ovo je samo jedna od mogućnosti njihove upotrebe.

Druga je mogućnost da saznate da je promet na kapsuli prekomjeran i preopterećuje ga (ili modul izvodi proračune koji zahtijevaju velike resurse). U ovom slučaju pomaže provjera spremnosti smanjite opterećenje mahune i “ohladite” je. Uspješan završetak provjere spremnosti u budućnosti omogućuje ponovno povećajte opterećenje mahune. U ovom slučaju (ako test spremnosti ne uspije), neuspjeh testa živosti bio bi vrlo kontraproduktivan. Zašto ponovno pokretati mahunarku koja je zdrava i naporno radi?

Stoga je u nekim slučajevima bolje uopće nema provjera nego omogućiti ih s netoč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 živost ostaviti po strani.

Obje vrste provjera ne bi smjele uspjeti kada uobičajene ovisnosti ne uspiju, inače će to dovesti do kaskadnog kvara (poput lavine) svih modula. Drugim riječima, ne ozlijedi sebe.

3. LoadBalancer za svaku HTTP uslugu

Najvjerojatnije imate HTTP usluge u svom klasteru koje želite proslijediti u vanjski svijet.

Ako uslugu otvorite kao type: LoadBalancer, njegov kontroler (ovisno o pružatelju usluga) osigurat će i dogovoriti vanjski LoadBalancer (ne mora nužno raditi na L7, već čak i na L4), a to može utjecati na trošak (vanjska statička IPv4 adresa, računalna snaga, naplata po sekundi ) zbog potrebe stvaranja velikog broja takvih resursa.

U ovom slučaju, puno je logičnije koristiti jedan vanjski balanser opterećenja, otvarajući usluge kao type: NodePort. Ili još bolje, proširite nešto poput nginx-ulazni-kontroler (Ili traefik), koji će biti jedini Čvorni priključak krajnja točka povezana s vanjskim balanserom opterećenja i usmjerit će promet u klasteru pomoću ulazak- Resursi Kubernetesa.

Druge (mikro)usluge unutar klastera koje međusobno komuniciraju mogu "komunicirati" koristeći usluge kao što su KlasterIP 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 troškove usluga u oblaku.

4. Automatsko skaliranje klastera bez uzimanja u obzir njegovih značajki

Kada dodajete čvorove u klaster i uklanjate ih iz klastera, ne biste se trebali oslanjati na neke osnovne metrike kao što je upotreba CPU-a na tim čvorovima. Planiranje mahuna mora uzeti u obzir mnoge ograničenja, kao što je afinitet pod/čvora, kvarovi i tolerancije, zahtjevi za resursima, QoS, itd. Korištenje vanjskog autoscalera koji ne uzima u obzir ove nijanse može dovesti do problema.

Zamislite da bi određena jedinica trebala biti zakazana, ali sva raspoloživa CPU snaga je zatražena/rastavljena i jedinica 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 (ugradnja) — uklanjanje čvora iz klastera uvijek je teže implementirati. Zamislite da imate pod sa stanjem (s povezanom trajnom pohranom). Trajni volumeni obično pripadaju specifična zona dostupnosti i ne repliciraju se u regiji. Stoga, ako vanjski alat za automatsko skaliranje izbriše čvor s ovim modulom, planer neće moći zakazati ovaj modul na drugom čvoru, budući da se to može učiniti samo u zoni dostupnosti gdje se nalazi trajna pohrana. Pod će ostati u stanju Pending.

Vrlo popularan u Kubernetes zajednici klaster-autoscaler. Radi na klasteru, podržava API-je glavnih pružatelja usluga oblaka, uzima u obzir sva ograničenja i može se skalirati u gore navedenim slučajevima. Također se može proširiti uz zadržavanje svih postavljenih ograničenja, čime se štedi novac (koji bi inače bio potrošen na neiskorišteni kapacitet).

5. Zanemarivanje IAM/RBAC mogućnosti

Čuvajte se korištenja IAM korisnika s trajnim tajnama za strojeva i aplikacija. Organizirajte privremeni pristup pomoću uloga i računa usluga (servisni računi).

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

10 uobičajenih pogrešaka pri korištenju Kubernetesa

Zaboravite na kube2iam i idite ravno na IAM uloge za račune usluga (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 primjedba. Nije tako teško, zar ne?

Također, nemojte dodijeliti privilegije računima usluga i profilima instanci admin и cluster-adminako im ne treba. Ovo je malo teže implementirati, posebno u RBAC K8, ali svakako vrijedi 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. Neugodna situacija, zar ne? Ali zašto su sve replike bile na istom čvoru? Zar Kubernetes ne bi trebao osigurati visoku dostupnost (HA)?!

Nažalost, Kubernetes planer, na vlastitu inicijativu, ne poštuje pravila odvojenog postojanja (anti-afinitet) za mahune. Oni moraju biti izričito 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 raspoređeni na različitim čvorovima (ovaj uvjet se provjerava samo tijekom raspoređivanja, ali ne i tijekom njihovog rada - dakle 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 istražiti ovu temu.

7. Ignoriranje PodDisruptionBudgetsa

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

PDB vam omogućuje 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, imam uslugu čuvara zoološkog vrta, i bez obzira što radite, želio bih imati barem 2 replike ove usluge uvijek dostupne."

Možete pročitati više o ovome здесь.

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

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

Česta zabluda je da ako implementirate non-prod load u jedan imenski prostor, a prod load u drugi, onda oni neće ni na koji način utjecati jedno na drugo... Međutim, određena razina izolacije može se postići korištenjem zahtjeva/ograničenja resursa, postavljanjem kvota i postavljanjem priorityClasses. Određenu "fizičku" izolaciju u podatkovnoj ravni osiguravaju afiniteti, tolerancije, kvarovi (ili birači čvorova), ali takvo je razdvajanje prilično težak implementirati.

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

9. externalTrafficPolicy: Klaster

Vrlo često opažamo da sav promet unutar klastera dolazi kroz uslugu kao što je NodePort, za koju je postavljena zadana politika externalTrafficPolicy: Cluster... Znači da Čvorni priključak 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 pogrešaka pri korištenju Kubernetesa

U isto vrijeme, pravi moduli povezani s gore spomenutom uslugom NodePort obično su dostupni samo na određenom podskup ovih čvorova. Drugim riječima, ako se povežem s čvorom koji nema potreban pod, on će proslijediti promet na drugi čvor, dodajući poskok i povećanje latencije (ako se čvorovi nalaze u različitim zonama dostupnosti/podatkovnim centrima, latencija može biti prilično visoka; osim toga, troškovi izlaznog prometa će se povećati).

S druge strane, ako određena Kubernetes usluga ima postavljenu politiku externalTrafficPolicy: Local, tada se NodePort otvara samo na onim čvorovima na kojima su potrebni podovi stvarno pokrenuti. Kada koristite vanjski balanser opterećenja koji provjerava stanje (zdravstveni pregled) krajnje točke (kako to radi AWS ELB), On slat će promet samo do potrebnih čvorova, što će imati blagotvoran učinak na kašnjenja, računalne potrebe, izlazne račune (i zdrav razum nalaže isto).

Postoji velika vjerojatnost da već koristite nešto slično traefik ili nginx-ulazni-kontroler kao krajnja točka NodePort (ili LoadBalancer, koji također koristi NodePort) za usmjeravanje ulaznog HTTP prometa, a postavljanje ove opcije može značajno smanjiti kašnjenje za takve zahtjeve.

В ova publikacija Možete saznati više o externalTrafficPolicy, njegovim prednostima i nedostacima.

10. Nemojte se vezati za klastere i nemojte zlorabiti kontrolnu razinu

Ranije je bilo uobičajeno zvati poslužitelje pravim imenima: Anton, HAL9000 i Colossus... Danas su zamijenjeni nasumično generiranim identifikatorima. Međutim, navika je ostala, a sada vlastita imena idu u klastere.

Tipična priča (temeljena na stvarnim događajima): sve je počelo s dokazom koncepta, pa je klaster dobio ponosno ime testiranje… Godine su prošle, a on se JOŠ UVIJEK koristi u proizvodnji i svi ga se boje dotaknuti.

Nema ničeg zabavnog u pretvaranju grozdova u kućne ljubimce, stoga preporučujemo da ih povremeno uklanjate dok vježbate oporavak od katastrofe (ovo će pomoći inženjerstvo kaosa - cca. prev.). Osim toga, ne bi škodilo raditi na kontrolnom sloju (kontrolna ravnina). Bojati se dodirnuti ga nije dobar znak. itd mrtav? Ljudi, stvarno ste u nevolji!

S druge strane, ne treba se zanositi manipuliranjem. S vremenom kontrolni sloj može postati spor. Najvjerojatnije je to zbog velikog broja objekata koji se stvaraju bez njihove rotacije (česta situacija kada se koristi Helm sa zadanim postavkama, zbog čega se njegovo stanje u konfiguracijskim mapama/tajnama ne ažurira - kao rezultat toga, tisuće objekata se nakupljaju u kontrolni sloj) ili sa stalnim uređivanjem kube-api objekata (za automatsko skaliranje, za CI/CD, za nadzor, zapisnike događaja, kontrolere itd.).

Osim toga, preporučujemo da provjerite SLA/SLO ugovore s upravljanim Kubernetes pružateljem i obratite pozornost na jamstva. Prodavač može jamčiti 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, i dobiti odgovor tek nakon 10 minuta, a to neće predstavljati kršenje uvjeta ugovora o usluzi.

11. Bonus: korištenje najnovije oznake

Ali ovo je već klasika. U posljednje vrijeme ovu tehniku ​​rjeđe susrećemo jer su mnogi, poučeni gorkim iskustvom, prestali koristiti oznaku :latest i počeo prikvačivati ​​verzije. hura!

ECR održava nepromjenjivost slikovnih oznaka; Preporučujemo da se upoznate s ovom izvanrednom značajkom.

Rezime

Ne očekujte da će sve raditi preko noći: Kubernetes nije lijek za sve. Loša aplikacija ostat će takav čak i u Kubernetesu (i vjerojatno će biti gore). Nepažnja će dovesti do pretjerane složenosti, sporog i stresnog rada kontrolnog sloja. Osim toga, riskirate ostati bez strategije oporavka od katastrofe. Ne očekujte da će Kubernetes pružiti izolaciju i visoku dostupnost odmah po otvaranju. Provedite malo vremena kako biste svoju aplikaciju učinili stvarno izvornom za oblak.

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

Oni koji se žele dodati na popis pogrešaka danih u ovom članku mogu nas kontaktirati na Twitteru (@MarekBartik, @MstrsPromatrač).

PS od prevoditelja

Pročitajte i na našem blogu:

Izvor: www.habr.com

Dodajte komentar