Kubernetes: Få fart på tjenestene dine ved å fjerne CPU-grenser

Tilbake i 2016 var vi i Buffer byttet til Kubernetes, og nå jobber rundt 60 noder (på AWS) og 1500 containere på vår k8s-klynge administrert av sparke. Vi gikk imidlertid over til mikrotjenester gjennom prøving og feiling, og selv etter flere år med arbeid med k8s står vi fortsatt overfor nye problemer. I dette innlegget skal vi snakke om prosessorbegrensninger: hvorfor vi trodde de var god praksis og hvorfor de endte opp med å ikke være så gode.

Prosessorbegrensninger og struping

Som mange andre Kubernetes-brukere, Google anbefaler på det sterkeste å sette CPU-grenser. Uten en slik innstilling kan beholdere i en node ta opp all prosessorkraft, som igjen forårsaker viktige Kubernetes-prosesser (f.eks. kubelet) slutter å svare på forespørsler. Å sette CPU-grenser er derfor en god måte å beskytte nodene dine på.

Prosessorgrenser setter en beholder til den maksimale CPU-tiden den kan bruke for en bestemt periode (standard er 100 ms), og beholderen vil aldri overskride denne grensen. I Kubernetes for struping beholder og forhindre at den overskrider grensen, brukes et spesialverktøy CFS-kvote, men disse kunstige CPU-grensene ender opp med å skade ytelsen og øke responstiden til containerne dine.

Hva kan skje hvis vi ikke setter prosessorgrenser?

Dessverre måtte vi selv møte dette problemet. Hver node har en prosess som er ansvarlig for å administrere containere kubelet, og han sluttet å svare på forespørsler. Noden, når dette skjer, vil gå inn i tilstanden NotReady, og beholdere fra den vil bli omdirigert et annet sted og skape de samme problemene på nye noder. Ikke et ideelt scenario, for å si det mildt.

Manifestasjon av problemet med struping og respons

Nøkkelberegningen for containersporing er trottling, viser den hvor mange ganger beholderen din har blitt strupet. Vi merket med interesse tilstedeværelsen av struping i enkelte beholdere, uavhengig av om prosessorbelastningen var ekstrem eller ikke. Som et eksempel, la oss ta en titt på en av våre viktigste APIer:

Kubernetes: Få fart på tjenestene dine ved å fjerne CPU-grenser

Som du kan se nedenfor, har vi satt grensen til 800m (0.8 eller 80 % kjerne), og toppverdier når i beste fall 200m (20 % kjerne). Det ser ut til at før vi struper tjenesten har vi fortsatt rikelig med prosessorkraft...

Kubernetes: Få fart på tjenestene dine ved å fjerne CPU-grenser
Du har kanskje lagt merke til at selv når prosessorbelastningen er under de angitte grensene - betydelig under - skjer det fortsatt struping.

Overfor dette oppdaget vi snart flere ressurser (problem på github, presentasjon på zadano, post på omio) om fallet i ytelse og responstid for tjenester på grunn av struping.

Hvorfor ser vi struping ved lav CPU-belastning? Kortversjonen er: "det er en feil i Linux-kjernen som forårsaker unødvendig struping av beholdere med spesifiserte prosessorgrenser." Hvis du er interessert i problemets natur, kan du lese presentasjonen (video и tekst alternativer) av Dave Chiluk.

Fjerne CPU-begrensninger (med ekstrem forsiktighet)

Etter lange diskusjoner bestemte vi oss for å fjerne prosessorrestriksjoner fra alle tjenester som direkte eller indirekte påvirket kritisk funksjonalitet for brukerne våre.

Avgjørelsen var ikke lett fordi vi setter stor pris på stabiliteten til klyngen vår. Tidligere har vi allerede eksperimentert med ustabiliteten til klyngen vår, og da forbrukte tjenestene for mange ressurser og bremset arbeidet til hele noden. Nå var alt noe annerledes: vi hadde en klar forståelse av hva vi forventet av våre klynger, samt en god strategi for å implementere de planlagte endringene.

Kubernetes: Få fart på tjenestene dine ved å fjerne CPU-grenser
Forretningskorrespondanse om et presserende spørsmål.

Hvordan beskytte nodene dine når restriksjoner oppheves?

Isolering av "ubegrensede" tjenester:

Tidligere har vi allerede sett noen noder komme inn i en tilstand notReady, først og fremst på grunn av tjenester som forbrukte for mange ressurser.

Vi bestemte oss for å plassere slike tjenester i separate ("merkede") noder slik at de ikke forstyrrer "relaterte" tjenester. Som et resultat, ved å merke noen noder og legge til toleranseparameteren til "urelaterte" tjenester, oppnådde vi større kontroll over klyngen, og det ble lettere for oss å identifisere problemer med noder. For å gjennomføre lignende prosesser selv, kan du gjøre deg kjent med dokumentasjon.

Kubernetes: Få fart på tjenestene dine ved å fjerne CPU-grenser

Tilordne en korrekt prosessor og minneforespørsel:

Vår største frykt var at prosessen ville forbruke for mange ressurser og noden ville slutte å svare på forespørsler. Siden vi nå (takket være Datadog) klart kunne overvåke alle tjenestene på klyngen vår, analyserte jeg flere måneders drift av de som vi planla å utpeke som "urelaterte". Jeg satte rett og slett maksimal CPU-bruk med en margin på 20%, og tildelte dermed plass i noden i tilfelle k8s prøver å tilordne andre tjenester til noden.

Kubernetes: Få fart på tjenestene dine ved å fjerne CPU-grenser

Som du kan se i grafen har maksimal belastning på prosessoren nådd 242m CPU-kjerner (0.242 prosessorkjerner). For en prosessorforespørsel er det nok å ta et tall som er litt større enn denne verdien. Vær oppmerksom på at siden tjenestene er brukersentriske, faller toppbelastningsverdier sammen med trafikk.

Gjør det samme med minnebruk og spørringer, og vips – du er klar! For større sikkerhet kan du legge til horisontal pod-autoskalering. Derfor, hver gang ressursbelastningen er høy, vil autoskalering skape nye pods, og kubernetes vil distribuere dem til noder med ledig plass. I tilfelle det ikke er plass igjen i selve klyngen, kan du angi et varsel til deg selv eller konfigurere tillegg av nye noder gjennom deres autoskalering.

Av minusene er det verdt å merke seg at vi tapte i "beholdertetthet", dvs. antall containere som kjører på én node. Vi kan også ha mange "avslapninger" ved lav trafikktetthet, og det er også en sjanse for at du når en høy prosessorbelastning, men autoskaleringsnoder bør hjelpe med sistnevnte.

Funn

Jeg er glad for å publisere disse utmerkede resultatene fra eksperimenter de siste ukene; vi har allerede sett betydelige forbedringer i responsen på tvers av alle modifiserte tjenester:

Kubernetes: Få fart på tjenestene dine ved å fjerne CPU-grenser

Vi oppnådde de beste resultatene på hjemmesiden vår (buffer.com), der akselererte tjenesten inn tjueto ganger!

Kubernetes: Få fart på tjenestene dine ved å fjerne CPU-grenser

Er Linux-kjernefeilen fikset?

Да, Feilen er allerede rettet og rettelsen er lagt til kjernen distribusjoner versjon 4.19 og høyere.

Men ved lesing kubernetes problemer på github for andre september 2020 vi kommer fortsatt over omtaler av noen Linux-prosjekter med en lignende feil. Jeg tror at noen Linux-distribusjoner fortsatt har denne feilen og jobber bare med å fikse den.

Hvis distribusjonsversjonen din er lavere enn 4.19, vil jeg anbefale å oppdatere til den nyeste, men uansett bør du prøve å fjerne prosessorrestriksjonene og se om strupingen vedvarer. Nedenfor kan du se en delvis liste over Kubernetes-administrasjonstjenester og Linux-distribusjoner:

  • Debian: fix integrert i den nyeste versjonen av distribusjonen, buster, og ser ganske frisk ut (August 2020). Noen tidligere versjoner kan også bli fikset.
  • Ubuntu: fiks integrert i siste versjon Ubuntu Focal Fossa 20.04
  • EKS har fått en løsning ennå i desember 2019. Hvis din versjon er lavere enn dette, bør du oppdatere AMI.
  • kops: Fra juni 2020 у kops 1.18+ Hovedvertsbildet vil være Ubuntu 20.04. Hvis din versjon av kops er eldre, kan det hende du må vente på en løsning. Vi selv venter nå.
  • GKE (Google Cloud): Fix integrert i januar 2020, men det er problemer med struping er fortsatt observert.

Hva skal jeg gjøre hvis reparasjonen løste strupeproblemet?

Jeg er ikke sikker på at problemet er helt løst. Når vi kommer til kjerneversjonen med rettelsen, vil jeg teste klyngen og oppdatere innlegget. Hvis noen allerede har oppdatert, vil jeg være interessert i å lese resultatene dine.

Konklusjon

  • Hvis du jobber med Docker-containere under Linux (uansett Kubernetes, Mesos, Swarm eller andre), kan containerne dine miste ytelsen på grunn av struping;
  • Prøv å oppdatere til den nyeste versjonen av distribusjonen din i håp om at feilen allerede er fikset;
  • Å fjerne prosessorgrenser vil løse problemet, men dette er en farlig teknikk som bør brukes med ekstrem forsiktighet (det er bedre å først oppdatere kjernen og sammenligne resultatene);
  • Hvis du har fjernet CPU-grenser, overvåk CPU- og minnebruken nøye og sørg for at CPU-ressursene overskrider forbruket.
  • Et trygt alternativ ville være å autoskalere poder for å lage nye poder i tilfelle høy maskinvarebelastning, slik at kubernetes tilordner dem til ledige noder.

Jeg håper dette innlegget hjelper deg med å forbedre ytelsen til containersystemene dine.

PS Her forfatteren korresponderer med lesere og kommentatorer (på engelsk).


Kilde: www.habr.com

Legg til en kommentar