10 Algemene Kubernetes-foute

Let wel. vertaal.: Die skrywers van hierdie artikel is ingenieurs van 'n klein Tsjeggiese maatskappy se pypstert. Hulle het daarin geslaag om 'n wonderlike lys saam te stel van [soms banale, maar steeds] sulke werklike probleme en wanopvattings wat verband hou met die werking van Kubernetes-klusters.

10 Algemene Kubernetes-foute

Oor die jare waarin ons Kubernetes gebruik het, het ons met 'n groot aantal groeperings gewerk (beide bestuur en onbestuur - op GCP, AWS en Azure). Met verloop van tyd het ons begin agterkom dat sommige foute voortdurend herhaal word. Daar is egter niks om oor skaam te wees nie: ons het die meeste daarvan self gedoen!

Die artikel bevat die mees algemene foute, en noem ook hoe om dit reg te stel.

1. Hulpbronne: versoeke en limiete

Hierdie item verdien beslis die beste aandag en die eerste plek op die lys.

SVE versoek gewoonlik óf glad nie gestel nie óf het 'n baie lae waarde (om soveel as moontlik peule op elke nodus te akkommodeer). Die nodusse word dus oorlaai. Tydens hoë las word die verwerkingskrag van die nodus ten volle benut en 'n spesifieke werklading ontvang slegs wat dit "versoek" het deur SVE verswakking. Dit lei tot verhoogde vertragings in die toepassing, time-outs en ander onaangename gevolge. (Lees meer hieroor in ons ander onlangse vertaling: "SVE-beperkings en aggressiewe versnelling in Kubernetes"- ongeveer. vertaal.)

Beste poging (uiters geen aanbeveel):

resources: {}

Uiters lae CPU-versoek (uiters geen aanbeveel):

   resources:
      Requests:
        cpu: "1m"

Aan die ander kant, om 'n SVE-limiet te hê, kan veroorsaak dat peule siklusse onredelik oorslaan, selfs al is die knooppunt se SVE nie ten volle gelaai nie. Weereens, dit kan lei tot verhoogde vertragings. Debat gaan voort rondom CPU CFS-kwota in die Linux-kern en SVE-versperring afhangende van die gestelde limiete, sowel as die deaktivering van die CFS-kwota ... Helaas, SVE-limiete kan meer probleme veroorsaak as wat dit kan oplos. Jy kan meer hieroor uitvind by die skakel hieronder.

Oortoewysing (oorbegaan) geheue kan tot groter probleme lei. Om die SVE-limiet te tref, veroorsaak dat siklusse oorgeslaan word, terwyl die slaan van die geheuelimiet veroorsaak dat die peul doodgemaak word. Het jy al gekyk OOM doodmaak? Ja, ons praat oor hom.

Wil jy die kans dat dit gebeur, verminder? Moenie buitensporige hoeveelhede geheue toewys nie en gebruik Gewaarborgde QoS (Dienskwaliteit) deur die geheueversoek tot die limiet te stel (soos in die voorbeeld hieronder). Lees meer hieroor in Henning Jacobs aanbiedings (Hoofingenieur Zalando).

Barsbaar (hoër kans om OOM doodgemaak te word):

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

Gewaarborg:

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

Wat sal moontlik help wanneer hulpbronne opgestel word?

Met metrieke-bediener jy kan die huidige SVE-verbruik en geheuegebruik van peule (en houers daarin) sien. Die kans is goed dat jy dit reeds gebruik. Voer net die volgende opdragte uit:

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

Hulle wys egter net huidige gebruik. Daarmee kan u 'n rowwe idee kry van die orde van grootte, maar op die ou end sal u dit nodig hê geskiedenis van metrieke oor tyd (om vrae te beantwoord soos: "Wat was die pieklading op die SVE?", "Wat was die las gisteroggend?" - ens.). Hiervoor kan jy gebruik Prometheus, DataDog en ander gereedskap. Hulle kry eenvoudig die metrieke van metrics-server en stoor dit, en die gebruiker kan dit navraag doen en dienooreenkomstig plot.

VerticalPodAutoscaler dit laat outomatiseer hierdie proses. Dit hou rekord van SVE- en geheuegebruikgeskiedenis en stel nuwe versoeke en limiete op gebaseer op hierdie inligting.

Doeltreffende gebruik van rekenaarkrag is nie 'n maklike taak nie. Dit is soos om heeltyd Tetris te speel. As jy te veel betaal vir rekenaarkrag teen 'n lae gemiddelde verbruik (sê ~10%), beveel ons aan dat jy kyk na produkte gebaseer op AWS Fargate of Virtual Kubelet. Hulle is gebou op 'n bedienerlose/betaal-per-gebruik-faktureringmodel, wat in sulke toestande goedkoper kan wees.

2. Lewendigheid en gereedheidsondersoeke

By verstek is lewendheid- en gereedheidskontroles nie in Kubernetes geaktiveer nie. En soms vergeet hulle om hulle aan te skakel ...

Maar hoe anders kan jy 'n diens herbegin in die geval van 'n noodlottige fout? En hoe weet die load balancer dat 'n sekere peul gereed is om verkeer te ontvang? Of dat dit in staat is om meer verkeer te hanteer?

Dikwels word hierdie toetse met mekaar verwar:

  • Lewendigheid - kontroleer "oorlewingbaarheid", wat die peul weer begin by mislukking;
  • gereedheid - 'n gereedheidskontrole, as dit misluk, ontkoppel dit die peul van die Kubernetes-diens (dit kan nagegaan word met kubectl get endpoints) en geen verkeer word daarna gestuur totdat die volgende kontrole suksesvol voltooi is nie.

Albei hierdie tjeks HET TYDENS DIE POD SE HELE LEWENSSIklus OPGETREE. Dit is baie belangrik.

Dit is 'n algemene wanopvatting dat gereedheidsondersoeke slegs met opstart uitgevoer word sodat die balanseerder kan weet dat die peul gereed is (Ready) en kan die verkeer begin verwerk. Dit is egter net een van die opsies vir hul gebruik.

Die ander is die vermoë om uit te vind dat die verkeer op die peul buitensporig is en oorlaai dit (of die peul doen hulpbron-intensiewe berekeninge). In hierdie geval help die gereedheidstoets verminder die las op die peul en "koel" dit. Suksesvolle voltooiing van die gereedheidskontrole in die toekoms laat toe verhoog weer die las op die peul. In hierdie geval (wanneer die gereedheidsondersoek misluk), sal dit baie teenproduktief wees om die lewendheidskontrole te misluk. Hoekom weer 'n peul begin wat gesond is en hard werk?

Daarom is die volledige afwesigheid van tjeks in sommige gevalle beter as die insluiting daarvan met verkeerd gekonfigureerde parameters. Soos hierbo genoem, as lewendheidskontrole kopieer gereedheidskontroledan is jy in groot moeilikheid. Moontlike opsie is om te konfigureer slegs gereedheidstoetsEn gevaarlike lewendigheid laat eenkant.

Beide tipes kontroles behoort nie te misluk wanneer gedeelde afhanklikhede misluk nie, anders sal dit veroorsaak dat alle peule afval. Met ander woorde, moenie jouself seermaak nie.

3. LoadBalancer vir elke HTTP-diens

Heel waarskynlik het u HTTP-dienste in u groepering wat u graag na die buitewêreld wil aanstuur.

As jy die diens oopmaak as type: LoadBalancer, sal sy beheerder (afhangende van die diensverskaffer) 'n eksterne LoadBalancer verskaf en onderhandel (nie noodwendig op L7 loop nie, eerder selfs op L4), en dit kan die koste (eksterne statiese IPv4-adres, rekenaarkrag, per sekonde fakturering) beïnvloed. aan die behoefte om 'n groot aantal sulke hulpbronne te skep.

In hierdie geval is dit baie meer logies om een ​​eksterne lasbalanseerder te gebruik, openingsdienste as type: NodePort. Of, nog beter, brei iets uit soos nginx-ingang-beheerder (Of traefik), wat die enigste sal wees NodePort eindpunt wat met 'n eksterne lasbalanseerder geassosieer word en sal verkeer in die groep stuur deur gebruik te maak binnedring- Kubernetes hulpbronne.

Ander intracluster (mikro) dienste wat met mekaar in wisselwerking is, kan "kommunikeer" deur dienste soos ClusterIP en 'n ingeboude diensontdekkingsmeganisme via DNS. Moet net nie hul publieke DNS/IP gebruik nie, aangesien dit vertraging kan beïnvloed en wolkdienskoste kan verhoog.

4. Outomatiese skaal van 'n groep sonder om die kenmerke daarvan in ag te neem

Wanneer jy nodusse by die cluster voeg en dit daaruit verwyder, moet jy nie staatmaak op sommige basiese maatstawwe soos die SVE-gebruik op hierdie nodusse nie. Peulbeplanning moet gedoen word met inagneming van die stel beperkingssoos peul/node-affiniteit, vlekke en tolerasies, hulpbronversoeke, QoS, ens. Die gebruik van 'n eksterne outoscaler wat nie hierdie nuanses in ag neem nie, kan tot probleme lei.

Stel jou voor dat 'n peul geskeduleer moet word, maar alle beskikbare SVE-krag word versoek/uitmekaargehaal en die peul vas in staat Pending. Die eksterne outoscaler sien die gemiddelde huidige SVE-lading (nie die versoekte een nie) en begin nie die uitbreiding nie (uitskaal) - voeg nie 'n ander nodus by nie. Gevolglik sal hierdie peul nie geskeduleer word nie.

Die herskaling egter (inskaal) - Die verwydering van 'n nodus uit 'n groepering is altyd moeiliker om te implementeer. Stel jou voor jy het 'n statige peul (met aanhoudende berging aangeheg). Aanhoudende volumes behoort gewoonlik aan gedefinieerde beskikbaarheidsone en word nie in die streek gerepliseer nie. Dus, as 'n eksterne outoskaaler die nodus met hierdie peul uitvee, dan sal die skeduleerder nie hierdie peul na 'n ander nodus kan skeduleer nie, aangesien dit slegs gedoen kan word in die beskikbaarheidsone waar die aanhoudende berging geleë is. Peul sal in staat hang Pending.

In die Kubernetes-gemeenskap is dit baie gewild cluster-outoskaaler. Dit loop in 'n groepie, ondersteun API's van groot wolkverskaffers, neem alle beperkings in ag en kan in die bogenoemde gevalle skaal. Dit is ook in staat om in te skaal terwyl al die gestelde limiete gehandhaaf word, en sodoende geld bespaar (wat andersins op onopgeëiste kapasiteit vermors sou word).

5. Verwaarlosing van IAM/RBAC-vermoëns

Pasop vir die gebruik van IAM-gebruikers met aanhoudende geheime om masjiene en toepassings. Organiseer tydelike toegang deur rolle en diensrekeninge te gebruik (diensrekeninge).

Ons sien dikwels dat toegangsleutels (en geheime) 'hardgekodeer' word in die toepassing se konfigurasie, sowel as nalaat om geheime te roteer ondanks toegang tot Cloud IAM. Gebruik IAM-rolle en diensrekeninge in plaas van gebruikers waar toepaslik.

10 Algemene Kubernetes-foute

Vergeet van kube2iam en spring reguit na IAM-rolle vir diensrekeninge (soos beskryf in noot met dieselfde naam Stěpán Vrany):

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

Een abstrak. Nie so moeilik nie, reg?

Moet ook nie diensrekeninge en instansieprofiele bevoorreg nie. admin и cluster-adminas hulle dit nie nodig het nie. Dit is 'n bietjie moeiliker om te implementeer, veral in RBAC K8's, maar beslis die moeite werd.

6. Moenie staatmaak op outomatiese anti-affiniteit vir peule nie

Stel jou voor dat jy drie replikas van een of ander ontplooiing op 'n nodus het. Die nodus val, en daarmee saam al die replikas. Slegte situasie, reg? Maar hoekom was al die replikas op dieselfde nodus? Behoort Kubernetes nie hoë beskikbaarheid (HA) te verskaf nie?!

Helaas, die Kubernetes-skeduleerder respekteer op eie inisiatief nie die reëls van afsonderlike bestaan ​​nie (anti-affiniteit) vir peule. Hulle moet uitdruklik geskryf word:

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

Dis al. Nou sal die peule na verskillende nodusse geskeduleer word (hierdie toestand word slegs tydens skedulering nagegaan, maar nie hul werking nie - dus requiredDuringSchedulingIgnoredDuringExecution).

Hier praat ons van podAntiAffinity op verskillende nodusse: topologyKey: "kubernetes.io/hostname", eerder as verskillende beskikbaarheidsones. Om 'n volwaardige HA te implementeer, moet jy dieper in hierdie onderwerp delf.

7. Ignoreer PodDisruptionBudgets

Stel jou voor dat jy 'n produksiewerklading op 'n Kubernetes-kluster het. Van tyd tot tyd moet die nodusse en die groep self opgedateer (of uit diens gestel word). PodDisruptionBudget (PDB) is 'n soort waarborgdiensooreenkoms tussen groepadministrateurs en gebruikers.

PDB vermy diensonderbrekings wat veroorsaak word deur 'n gebrek aan nodusse:

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

In hierdie voorbeeld sê jy, as die gebruiker van die groepering, aan die administrateurs: "Haai, ek het 'n dieretuinwagdiens, en maak nie saak wat jy doen nie, ek wil hê dat ten minste 2 replikas van hierdie diens altyd beskikbaar moet wees. "

Jy kan meer hieroor lees hier.

8. Veelvuldige gebruikers of omgewings in 'n gedeelde groepering

Kubernetes Naamruimtes (naamruimtes) nie sterk isolasie verskaf nie.

Dit is 'n algemene wanopvatting dat as jy 'n nie-prod loonvrag in een naamruimte en 'n prod loonvrag in 'n ander ontplooi, sal mekaar nie beïnvloed nie… Daar kan egter 'n mate van isolasie bereik word met hulpbronversoeke/beperkings, stel kwotas, stel prioriteitsklasse. Sommige "fisiese" isolasie in die datavlak word verskaf deur affiniteite, tolerasies, vlekke (of nodeselektors), maar so 'n skeiding is redelik moeilik implementeer.

Diegene wat albei tipes werkladings in dieselfde groep moet kombineer, sal kompleksiteit moet verdra. As daar nie so 'n behoefte is nie, en jy kan bekostig om te begin 'n ander groepie (sê, in 'n publieke wolk), is dit beter om dit te doen. Dit sal 'n baie hoër vlak van isolasie bereik.

9. eksterne verkeersbeleid: groepering

Baie dikwels sien ons dat alle verkeer binne die groepering deur 'n NodePort-tipe diens kom, waarvoor die beleid by verstek gestel is externalTrafficPolicy: Cluster... Dit beteken dat NodePort is oop op elke nodus in die groepie, en jy kan enige van hulle gebruik om met die verlangde diens (stel peule) te kommunikeer.

10 Algemene Kubernetes-foute

Terselfdertyd is regte peule wat met die voorgenoemde NodePort-diens geassosieer word, gewoonlik slegs op sommige beskikbaar subset van hierdie nodusse. Met ander woorde, as ek aan 'n nodus koppel wat nie die regte peul het nie, sal dit verkeer na 'n ander node herlei, 'n hop byvoeg (hop) en die verhoging van die latency (as die nodusse in verskillende beskikbaarheidsones / datasentrums is, kan die latency redelik hoog wees; daarbenewens sal die koste van uitgangsverkeer toeneem).

Aan die ander kant, as 'n Kubernetes-diens 'n beleid het externalTrafficPolicy: Local, dan word die NodePort slegs oopgemaak op daardie nodusse waar die vereiste peule eintlik loop. Wanneer 'n eksterne lasbalanseerder gebruik word wat die toestande nagaan (gesondheids ondersoek) eindpunte (hoe AWS ELB), Hy sal slegs verkeer na die verlangde nodusse stuur, wat vertragings, berekeningsbehoeftes, rekeninge vir uitgang gunstig sal beïnvloed (en gesonde verstand dikteer dieselfde ding).

Daar is 'n groot kans dat jy reeds iets soos traefik of nginx-ingang-beheerder as 'n NodePort-eindpunt (of LoadBalancer, wat ook NodePort gebruik) om HTTP-ingangverkeer te stuur, en die instelling van hierdie opsie kan latensie vir sulke versoeke aansienlik verminder.

В hierdie publikasie jy kan meer leer oor eksterne verkeersbeleid, die voordele en nadele daarvan.

10. Moenie aan trosse geheg raak nie en moenie die beheervlak misbruik nie

Voorheen was dit gebruiklik om bedieners met eiename te noem: Anton, HAL9000 en Colossus... Vandag is hulle vervang deur ewekansig gegenereerde identifiseerders. Die gewoonte het egter gebly, en nou kry trosse hul eie name.

Tipiese storie (gebaseer op werklike gebeure): dit het alles begin met 'n bewys van konsep, so die groep het 'n trotse naam gedra toets... Jare het verbygegaan, en dit word STEEDS in produksie gebruik, en almal is bang om daaraan te raak.

Daar is niks snaaks daaraan om trosse in troeteldiere te verander nie, so ons beveel aan dat u dit gereeld verwyder, terwyl u oefen in ramp herstel (dit sal help chaos ingenieurswese - ongeveer. vertaal.). Boonop maak dit nie seer om die beheerlaag te versorg nie (beheervliegtuig). Om bang te wees om aan hom te raak is nie 'n goeie teken nie. Ens dood? Ouens, julle het regtig opgefok!

Aan die ander kant, moenie meegevoer raak met manipulasies met hom nie. Met tyd beheerlaag kan stadig word. Dit is waarskynlik te wyte aan 'n groot aantal voorwerpe wat sonder hul rotasie geskep word ('n algemene situasie wanneer Helm met verstekinstellings gebruik word, en daarom word die toestand daarvan in configmaps / geheime nie opgedateer nie - gevolglik versamel duisende voorwerpe in die beheerlaag) of met konstante redigering van kube-api-voorwerpe (vir outomatiese skaal, vir CI / CD, vir monitering, gebeurtenislogboeke, beheerders, ens.).

Daarbenewens beveel ons aan dat u die SLA / SLO-ooreenkomste met die bestuurde Kubernetes-verskaffer nagaan en aandag gee aan waarborge. Verkoper kan waarborg beheer laag toeganklikheid (of sy subkomponente), maar nie die p99 vertraging van versoeke wat jy aan dit stuur nie. Met ander woorde, jy kan inskryf kubectl get nodes, en ontvang eers 'n antwoord na 10 minute, en dit sal nie 'n skending van die bepalings van die diensooreenkoms wees nie.

11. Bonus: die gebruik van die nuutste merker

Nou is dit 'n klassieke. Onlangs het ons nie so 'n tegniek so dikwels teëgekom nie, aangesien baie, geleer deur bitter ervaring, opgehou het om die merker te gebruik :latest en begin weergawes vaspen. Hoera!

ECR ondersteun onveranderlikheid van beeldmerkers; Ons beveel aan dat jy jouself vergewis van hierdie merkwaardige kenmerk.

Opsomming

Moenie verwag dat alles met 'n waai van jou hand sal werk nie: Kubernetes is nie 'n wondermiddel nie. Slegte app sal selfs in Kubernetes so bly (en moontlik selfs erger). Sorgeloosheid sal lei tot oormatige kompleksiteit, stadige en stresvolle werk van die beheerlaag. Daarbenewens loop jy die risiko om sonder 'n rampherstelstrategie gelaat te word. Moenie verwag dat Kubernetes buite die kassie sal sorg vir isolasie en hoë beskikbaarheid nie. Spandeer 'n geruime tyd om jou program werklik wolkgebonde te maak.

Jy kan kennis maak met die onsuksesvolle ervaring van verskeie spanne in hierdie versameling stories deur Henning Jacobs.

Diegene wat die lys van foute wat in hierdie artikel verskaf word wil aanvul, kan ons op Twitter kontak (@MarekBartik, @MstrsObserver).

PS van vertaler

Lees ook op ons blog:

Bron: will.com

Voeg 'n opmerking