Suorittimen rajoitukset ja aggressiivinen kuristus Kubernetesissa

Huomautus. käännös: Tämä Omion – eurooppalaisen matka-aggregaattorin – silmiä avaava historia vie lukijat perusteoriasta Kubernetes-konfiguraation kiehtoviin käytännön monimutkaisuuksiin. Tällaisten tapausten tuntemus auttaa paitsi laajentamaan näköalojasi myös ehkäisemään ei-triviaaleja ongelmia.

Suorittimen rajoitukset ja aggressiivinen kuristus Kubernetesissa

Onko sinulla koskaan ollut sovellus, joka on juuttunut paikalleen, lakannut vastaamasta terveystarkastuksiin etkä ole pystynyt ymmärtämään syytä? Yksi mahdollinen selitys liittyy suorittimen resurssikiintiörajoituksiin. Tästä puhumme tässä artikkelissa.

TL; DR:
Suosittelemme voimakkaasti poistamaan prosessorirajoitukset käytöstä Kubernetesissa (tai poistamaan CFS-kiintiöt käytöstä Kubeletissa), jos käytät Linux-ytimen versiota, jossa on CFS-kiintiövirhe. Ytimessä on saatavana vakava ja hyvin tunnettu bugi, joka johtaa liialliseen kuristukseen ja viivästyksiin
.

Omiossa koko infrastruktuuria hallinnoi Kubernetes. Kaikki tilalliset ja tilattomat työkuormamme toimivat yksinomaan Kubernetesissa (käytämme Google Kubernetes Engineä). Viimeisen kuuden kuukauden aikana olemme alkaneet havaita satunnaisia ​​hidastumista. Sovellukset jäätyvät tai lakkaavat vastaamasta terveystarkastuksiin, menettävät yhteyden verkkoon jne. Tämä käytös hämmensi meitä pitkään, ja lopulta päätimme ottaa ongelman vakavasti.

Artikkelin tiivistelmä:

  • Muutama sana konteista ja Kubernetesista;
  • Miten suorittimen pyynnöt ja rajoitukset toteutetaan;
  • Kuinka suorittimen rajoitus toimii moniytimisissä ympäristöissä;
  • Kuinka seurata suorittimen kuristusta;
  • Ongelmanratkaisu ja vivahteet.

Muutama sana konteista ja Kubernetesista

Kubernetes on pohjimmiltaan moderni standardi infrastruktuurimaailmassa. Sen päätehtävänä on konttiorkesterointi.

kontit

Aiemmin meidän piti luoda artefakteja, kuten Java JAR:ita/WAReja, Python Eggejä tai suoritettavia tiedostoja toimiakseen palvelimilla. Niiden toimimiseksi piti kuitenkin tehdä lisätyötä: ajonaikaisen ympäristön asentaminen (Java/Python), tarvittavien tiedostojen sijoittaminen oikeisiin paikkoihin, yhteensopivuuden varmistaminen tietyn käyttöjärjestelmän version kanssa jne. Toisin sanoen kokoonpanon hallintaan (joka oli usein kiistan lähde kehittäjien ja järjestelmänvalvojien välillä) oli kiinnitettävä erityistä huomiota.

Kontit muuttivat kaiken. Nyt artefakti on säilökuva. Se voidaan esittää eräänlaisena laajennettuna suoritettavana tiedostona, joka sisältää ohjelman lisäksi täysimittaisen suoritusympäristön (Java/Python/...) sekä tarvittavat tiedostot/paketit esiasennettuina ja valmiina juosta. Säilöjä voidaan ottaa käyttöön ja käyttää eri palvelimilla ilman lisätoimenpiteitä.

Lisäksi kontit toimivat omassa hiekkalaatikkoympäristössään. Heillä on oma virtuaalinen verkkosovitin, oma tiedostojärjestelmä, johon on rajoitettu pääsy, oma prosessihierarkia, omat prosessorin ja muistin rajoitukset jne. Kaikki tämä on toteutettu Linux-ytimen erityisen alijärjestelmän - nimiavaruuksien - ansiosta.

Kubernetes

Kuten aiemmin todettiin, Kubernetes on konttiorkesteri. Se toimii näin: annat sille joukon koneita ja sanot sitten: "Hei, Kubernetes, käynnistetään kymmenen konttia, joissa kussakin on 2 prosessoria ja 3 Gt muistia, ja pidetään ne käynnissä!" Kubernetes hoitaa loput. Se löytää vapaan kapasiteetin, käynnistää kontit ja käynnistää ne tarvittaessa uudelleen, julkaisee päivityksen versioita vaihdettaessa jne. Pohjimmiltaan Kubernetes mahdollistaa laitteistokomponentin abstraktion ja tekee monenlaisista järjestelmistä sopivia sovellusten käyttöönottoon ja suorittamiseen.

Suorittimen rajoitukset ja aggressiivinen kuristus Kubernetesissa
Kubernetes maallikon näkökulmasta

Mitä pyynnöt ja rajoitukset ovat Kubernetesissa

Okei, olemme peittäneet kontit ja Kubernetesin. Tiedämme myös, että samassa koneessa voi olla useita kontteja.

Yhteisen asunnon kanssa voidaan vetää analogia. Tilavat tilat (koneet/yksiköt) otetaan ja vuokrataan usealle vuokralaiselle (kontit). Kubernetes toimii kiinteistönvälittäjänä. Herää kysymys, miten vuokralaiset voidaan estää konflikteista keskenään? Entä jos joku heistä päättää lainata kylpyhuonetta puoleksi päivästä?

Tässä kohtaa pyynnöt ja rajat tulevat peliin. prosessori Pyydä tarvitaan vain suunnittelutarkoituksiin. Tämä on jotain kontin "toivelistaa", ja sitä käytetään sopivimman solmun valitsemiseen. Samaan aikaan CPU Raja voidaan verrata vuokrasopimukseen - heti kun valitsemme kontin yksikön, ei voi ylittää vahvistetut rajat. Ja tässä se ongelma syntyy...

Kuinka pyynnöt ja rajoitukset toteutetaan Kubernetesissa

Kubernetes käyttää ytimeen sisäänrakennettua kuristusmekanismia (kellojaksojen ohittaminen) suorittimen rajoitusten toteuttamiseksi. Jos sovellus ylittää rajan, kuristus on käytössä (eli se vastaanottaa vähemmän CPU-jaksoja). Muistin pyynnöt ja rajoitukset on järjestetty eri tavalla, joten ne on helpompi havaita. Voit tehdä tämän tarkistamalla podin viimeisimmän uudelleenkäynnistyksen tilan: onko se "OOMKilled". Prosessorin kuristaminen ei ole niin yksinkertaista, koska K8s tarjoaa mittareita vain käytön mukaan, ei c-ryhmien mukaan.

CPU-pyyntö

Suorittimen rajoitukset ja aggressiivinen kuristus Kubernetesissa
Kuinka CPU-pyyntö toteutetaan

Yksinkertaisuuden vuoksi tarkastellaan prosessia käyttämällä esimerkkinä konetta, jossa on 4-ytiminen CPU.

K8s käyttää ohjausryhmämekanismia (cgroups) ohjaamaan resurssien (muisti ja prosessori) allokointia. Sille on saatavilla hierarkkinen malli: lapsi perii emoryhmän rajat. Jakelun tiedot tallennetaan virtuaaliseen tiedostojärjestelmään (/sys/fs/cgroup). Prosessorin tapauksessa tämä on /sys/fs/cgroup/cpu,cpuacct/*.

K8s käyttää tiedostoa cpu.share prosessoriresurssien allokointiin. Tässä tapauksessa juuri c-ryhmä saa 4096 osuutta suoritinresursseista - 100% käytettävissä olevasta prosessorin tehosta (1 ydin = 1024; tämä on kiinteä arvo). Juuriryhmä jakaa resursseja suhteellisesti rekisteröityjen jälkeläisten osuuksien mukaan cpu.share, ja he puolestaan ​​tekevät saman jälkeläistensä kanssa jne. Tyypillisessä Kubernetes-solmussa juuri-c-ryhmässä on kolme lasta: system.slice, user.slice и kubepods. Kahta ensimmäistä alaryhmää käytetään resurssien jakamiseen kriittisten järjestelmälatausten ja käyttäjäohjelmien välillä K8:n ulkopuolella. Viimeinen - kubepods - Kubernetesin luoma resurssien jakamiseksi podien välillä.

Yllä oleva kaavio osoittaa, että ensimmäinen ja toinen alaryhmä saivat molemmat 1024 osakkeita kuberpod-alaryhmän kanssa 4096 osakkeita Kuinka tämä on mahdollista: loppujen lopuksi juuriryhmällä on pääsy vain 4096 osakkeita, ja hänen jälkeläistensä osakkeiden summa ylittää merkittävästi tämän määrän (6144)? Asia on siinä, että arvo on looginen, joten Linuxin ajastin (CFS) käyttää sitä prosessoriresurssien suhteelliseen jakamiseen. Meidän tapauksessamme kaksi ensimmäistä ryhmää saavat 680 todellisia osakkeita (16,6 % 4096:sta), ja kubepod saa loput 2736 osakkeita Katkosten sattuessa kaksi ensimmäistä ryhmää eivät käytä allokoituja resursseja.

Onneksi ajastimella on mekanismi, jolla vältetään käyttämättömien prosessoriresurssien tuhlaaminen. Se siirtää "vapaa" kapasiteetin globaaliin pooliin, josta se jaetaan ryhmille, jotka tarvitsevat lisäprosessoritehoa (siirto tapahtuu erissä pyöristyshäviöiden välttämiseksi). Samanlaista menetelmää sovelletaan kaikkiin jälkeläisten jälkeläisiin.

Tämä mekanismi varmistaa suorittimen tehon oikeudenmukaisen jakautumisen ja varmistaa, että kukaan prosessi ei "varasta" resursseja muilta.

CPU Limit

Huolimatta siitä, että rajoitusten ja pyyntöjen konfiguraatiot K8:ssa näyttävät samanlaisilta, niiden toteutus on radikaalisti erilainen: tämä harhaanjohtavin ja vähiten dokumentoitu osa.

K8s kytkeytyy CFS-kiintiömekanismi rajojen toteuttamiseksi. Niiden asetukset on määritetty tiedostoissa cfs_period_us и cfs_quota_us cgroup-hakemistossa (tiedosto sijaitsee myös siellä cpu.share).

Toisin kuin cpu.share, kiintiö perustuu ajanjakso, eikä käytettävissä olevalla prosessorin teholla. cfs_period_us määrittää jakson (epookin) keston - se on aina 100000 μs (100 ms). Tätä arvoa voi muuttaa K8:ssa, mutta se on toistaiseksi saatavilla vain alfaversiossa. Ajastin käyttää aikakausia käytettyjen kiintiöiden uudelleenkäynnistämiseen. Toinen tiedosto cfs_quota_us, määrittää käytettävissä olevan ajan (kiintiön) kullakin aikakaudella. Huomaa, että se on myös määritelty mikrosekunteina. Kiintiö voi ylittää aikakauden pituuden; toisin sanoen se voi olla yli 100 ms.

Tarkastellaan kahta skenaariota 16-ytimisissä koneissa (yleisin tietokonetyyppi, joka meillä on Omiolla):

Suorittimen rajoitukset ja aggressiivinen kuristus Kubernetesissa
Skenaario 1: 2 säiettä ja 200 ms raja. Ei kuristusta

Suorittimen rajoitukset ja aggressiivinen kuristus Kubernetesissa
Skenaario 2: 10 säiettä ja 200 ms raja. Kuristus alkaa 20 ms:n kuluttua, prosessoriresurssien käyttö jatkuu 80 ms:n kuluttua

Oletetaan, että asetat suorittimen rajaksi 2 ytimet; Kubernetes muuttaa tämän arvon 200 ms:ksi. Tämä tarkoittaa, että säiliö voi käyttää enintään 200 ms CPU-aikaa ilman kuristusta.

Ja tästä hauskuus alkaa. Kuten edellä mainittiin, käytettävissä oleva kiintiö on 200 ms. Jos työskentelet rinnakkain kymmenen säikeet 12-ytimisessä koneessa (katso skenaarion 2 kuvaa), kun kaikki muut podit ovat käyttämättöminä, kiintiö kuluu loppuun vain 20 ms:ssa (koska 10 * 20 ms = 200 ms), ja kaikki tämän podin säikeet roikkuvat » (kaasu) seuraavat 80 ms. Jo mainittu aikatauluvirhe, jonka vuoksi tapahtuu liiallista kuristusta ja kontti ei voi edes täyttää olemassa olevaa kiintiötä.

Kuinka arvioida kuristus paloissa?

Kirjaudu vain podiin ja suorita cat /sys/fs/cgroup/cpu/cpu.stat.

  • nr_periods — aikataulujaksojen kokonaismäärä;
  • nr_throttled — koostumuksen kuristettujen jaksojen määrä nr_periods;
  • throttled_time — kumulatiivinen kuristusaika nanosekunteina.

Suorittimen rajoitukset ja aggressiivinen kuristus Kubernetesissa

Mitä todella tapahtuu?

Tämän seurauksena saamme korkean kuristuksen kaikissa sovelluksissa. Joskus hän on mukana puolitoista kertaa vahvempi kuin laskettiin!

Tämä johtaa erilaisiin virheisiin - valmiustarkistusvirheisiin, säiliön jumiutumiseen, verkkoyhteyskatkoihin, aikakatkaisuihin palvelupuheluiden sisällä. Tämä johtaa viime kädessä lisääntyneeseen latenssiin ja korkeampiin virhesuhteisiin.

Päätös ja seuraukset

Täällä kaikki on yksinkertaista. Hylkäsimme suorittimen rajoituksista ja aloimme päivittää käyttöjärjestelmän ydintä klustereissa uusimpaan versioon, jossa vika korjattiin. Virheiden määrä (HTTP 5xx) palveluissamme laski välittömästi merkittävästi:

HTTP 5xx -virheet

Suorittimen rajoitukset ja aggressiivinen kuristus Kubernetesissa
HTTP 5xx -virheet yhdelle tärkeälle palvelulle

Vastausaika p95

Suorittimen rajoitukset ja aggressiivinen kuristus Kubernetesissa
Kriittisen palvelupyynnön latenssi, 95. prosenttipiste

Käyttökustannukset

Suorittimen rajoitukset ja aggressiivinen kuristus Kubernetesissa
Käyttötuntien määrä

Mikä on saalis?

Kuten artikkelin alussa todettiin:

Yhteisen asunnon kanssa voidaan vetää analogia... Kubernetes toimii kiinteistönvälittäjänä. Mutta miten vuokralaiset vältetään ristiriidoista keskenään? Entä jos joku heistä päättää lainata kylpyhuonetta puoleksi päivästä?

Tässä on saalis. Yksi huolimaton säiliö voi syödä kaikki koneen käytettävissä olevat prosessoriresurssit. Jos sinulla on älykäs sovelluspino (esimerkiksi JVM, Go, Node VM on määritetty oikein), tämä ei ole ongelma: voit työskennellä tällaisissa olosuhteissa pitkään. Mutta jos sovellukset ovat huonosti optimoituja tai niitä ei ole optimoitu ollenkaan (FROM java:latest), tilanne saattaa riistäytyä hallinnasta. Omiossa meillä on automatisoitu Docker-perustiedostot riittävällä oletusasetuksella pääkielipinolle, joten tätä ongelmaa ei ollut olemassa.

Suosittelemme mittareiden seuraamista KÄYTTÖ (käyttö, kylläisyys ja virheet), API-viiveet ja virhesuhteet. Varmista, että tulokset vastaavat odotuksia.

viittaukset

Tämä on meidän tarinamme. Seuraavat materiaalit auttoivat suuresti ymmärtämään, mitä tapahtui:

Kubernetes-virheraportit:

Oletko törmännyt vastaaviin ongelmiin käytännössä tai sinulla on kokemusta kuristamisesta konttituotantoympäristöissä? Jaa tarinasi kommenteissa!

PS kääntäjältä

Lue myös blogistamme:

Lähde: will.com

Lisää kommentti