Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Konferenssissa 27. huhtikuuta Lakko 2019, osana "DevOps" -osiota annettiin raportti "Autoscaling and Resource Management in Kubernetes". Siinä kerrotaan, kuinka voit käyttää K8s-laitteita sovelluksiesi korkean käytettävyyden ja huippusuorituskyvyn varmistamiseksi.

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Perinteisesti esittelemme mielellämme video raportista (44 minuuttia, paljon informatiivisempi kuin artikkeli) ja päätiivistelmä tekstimuodossa. Mennä!

Analysoidaan raportin aihe sana sanalta ja aloitetaan lopusta.

Kubernetes

Oletetaan, että isännässämme on Docker-kontit. Minkä vuoksi? Toistettavuuden ja eristyksen varmistamiseksi, mikä puolestaan ​​mahdollistaa yksinkertaisen ja hyvän käyttöönoton, CI/CD. Meillä on monia tällaisia ​​konteilla varustettuja ajoneuvoja.

Mitä Kubernetes tarjoaa tässä tapauksessa?

  1. Lopetamme näiden koneiden ajattelemisen ja alamme työskennellä "pilven" kanssa konttien klusteri tai palot (säiliöryhmät).
  2. Lisäksi emme edes ajattele yksittäisiä paloja, vaan hallitsemme enemmänоsuurempia ryhmiä. Sellainen korkean tason primitiivit Salli meidän sanoa, että tietyn työkuorman suorittamiseen on malli, ja tässä on tarvittava määrä esiintymiä sen suorittamiseen. Jos muutamme mallia myöhemmin, kaikki esiintymät muuttuvat.
  3. Kanssa deklaratiivinen API Sen sijaan, että suorittaisimme tiettyjen komentojen sarjan, kuvaamme "maailman rakennetta" (YAML:ssa), jonka Kubernetes on luonut. Ja vielä: kun kuvaus muuttuu, myös sen todellinen näyttö muuttuu.

Resurssienhallinta

prosessori

Ajetaan palvelimella nginx, php-fpm ja mysql. Näissä palveluissa on itse asiassa käynnissä vielä enemmän prosesseja, joista jokainen vaatii laskentaresursseja:

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)
(dian numerot ovat "papukaijoja", kunkin prosessin abstrakti laskentatehotarve)

Tämän kanssa työskentelyn helpottamiseksi on loogista yhdistää prosessit ryhmiin (esimerkiksi kaikki nginx-prosessit yhdeksi ryhmäksi "nginx"). Yksinkertainen ja ilmeinen tapa tehdä tämä on laittaa jokainen ryhmä säilöön:

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Jatkamiseksi sinun on muistettava, mikä säilö on (Linuxissa). Niiden ilmestyminen mahdollisti ytimen kolmen keskeisen ominaisuuden ansiosta, jotka on otettu käyttöön melko kauan sitten: kyvyt, nimiavaruudet и ryhmät. Ja jatkokehitystä auttoivat muut tekniikat (mukaan lukien kätevät "kuoret", kuten Docker):

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Raportin yhteydessä olemme vain kiinnostuneita ryhmät, koska ohjausryhmät ovat osa säilöjen (Docker jne.) toiminnallisuutta, joka toteuttaa resurssien hallinnan. Ryhmiin yhdistetyt prosessit, kuten halusimme, ovat kontrolliryhmiä.

Palataan näiden prosessien suoritinvaatimuksiin ja nyt prosessiryhmiin:

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)
(Toistan, että kaikki luvut ovat abstrakteja ilmauksia resurssien tarpeesta)

Samaan aikaan CPU:lla itsessään on tietty rajallinen resurssi (esimerkissä tämä on 1000), jota kaikilta saattaa puuttua (kaikkien ryhmien tarpeiden summa on 150+850+460=1460). Mitä tässä tapauksessa tapahtuu?

Ydin alkaa jakaa resursseja ja tekee sen "reilusti" antaen jokaiselle ryhmälle saman määrän resursseja. Mutta ensimmäisessä tapauksessa niitä on enemmän kuin tarvitaan (333>150), joten ylijäämä (333-150=183) jää varaan, joka myös jakautuu tasaisesti kahden muun kontin kesken:

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Seurauksena: ensimmäisessä kontissa oli tarpeeksi resursseja, toisessa - sillä ei ollut tarpeeksi resursseja, kolmannessa - sillä ei ollut tarpeeksi resursseja. Tämä on seurausta toimista "rehellinen" aikataulu Linuxissa - CFS. Sen toimintaa voidaan säätää tehtävän avulla paino jokainen säiliö. Esimerkiksi näin:

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Tarkastellaan tapausta resurssien puutteesta toisessa säilössä (php-fpm). Kaikki konttiresurssit jaetaan tasaisesti prosessien kesken. Tämän seurauksena pääprosessi toimii hyvin, mutta kaikki työntekijät hidastavat ja saavat alle puolet tarvitsemastaan:

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Näin CFS-aikataulu toimii. Kutsumme edelleen konteille määrittämiämme painoja pyynnöt. Miksi näin on - katso lisää.

Katsotaanpa koko tilannetta toiselta puolelta. Kuten tiedätte, kaikki tiet johtavat Roomaan, ja tietokoneen tapauksessa CPU: hin. Yksi prosessori, monta tehtävää - tarvitset liikennevalon. Yksinkertaisin tapa hallita resursseja on "liikennevalo": ne antoivat yhdelle prosessille kiinteän pääsyajan CPU:lle, sitten seuraavalle jne.

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Tätä lähestymistapaa kutsutaan koviksi kiintiöiksi (kova rajoittava). Muistetaan se yksinkertaisesti sellaisena rajoja. Jos kuitenkin jaat rajoitukset kaikille konteille, syntyy ongelma: mysql ajoi tietä pitkin ja jossain vaiheessa sen prosessorin tarve loppui, mutta kaikki muut prosessit joutuvat odottamaan CPU:ta tyhjäkäynnillä.

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Palataan Linux-ytimeen ja sen vuorovaikutukseen prosessorin kanssa - kokonaiskuva on seuraava:

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

cgroupilla on kaksi asetusta - pohjimmiltaan nämä ovat kaksi yksinkertaista "käännettä", joiden avulla voit määrittää:

  1. kontin paino (pyynnöt) on osakkeet;
  2. prosenttiosuus kokonaisprosessoriajasta konttitehtävien parissa työskentelemiseen (rajat) on kiintiö.

Kuinka mitata CPU?

On olemassa erilaisia ​​tapoja:

  1. Mikä on papukaijat, kukaan ei tiedä - sinun on neuvoteltava joka kerta.
  2. korko selkeämpi, mutta suhteellinen: 50% palvelimesta, jossa on 4 ydintä ja 20 ydintä, ovat täysin eri asioita.
  3. Voit käyttää jo mainittuja paino, jotka Linux tietää, mutta ne ovat myös suhteellisia.
  4. Sopivin vaihtoehto on mitata laskentaresurssit sekuntia. Nuo. sekunteina prosessorin ajasta suhteessa reaaliajan sekunteihin: 1 sekunti prosessoriaikaa annettiin yhtä todellista sekuntia kohden - tämä on yksi koko CPU-ydin.

Puhumisen helpottamiseksi he alkoivat mitata suoraan ytimiä, mikä tarkoittaa niillä samaa CPU-aikaa suhteessa todelliseen. Koska Linux ymmärtää painot, mutta ei niin paljon suorittimen aikaa/ytimiä, tarvittiin mekanismi kääntääkseen yhdestä toiseen.

Tarkastellaanpa yksinkertaista esimerkkiä palvelimella, jossa on 3 CPU-ydintä, jossa kolmelle podille annetaan painot (500, 1000 ja 1500), jotka on helppo muuntaa niille allokoitujen ytimien vastaaviksi osiksi (0,5, 1 ja 1,5).

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Jos otat toisen palvelimen, jossa on kaksi kertaa enemmän ytimiä (6), ja sijoitat samat kotelot sinne, ytimien jakautuminen voidaan helposti laskea kertomalla yksinkertaisesti kahdella (2, 1 ja 2, vastaavasti). Mutta tärkeä hetki tapahtuu, kun tälle palvelimelle ilmestyy neljäs pod, jonka paino on mukavuussyistä 3. Se vie osan CPU-resursseista (puolet ytimistä), ja jäljellä oleville podille ne lasketaan uudelleen (puolitetaan):

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Kubernetes ja CPU-resurssit

Kubernetesissa prosessoriresurssit mitataan yleensä milliadrax, eli Peruspainoksi otetaan 0,001 ydintä. (Samaa asiaa Linux/cgroups-terminologiassa kutsutaan prosessorin jaoksi, vaikka tarkemmin sanottuna 1000 milliydintä = 1024 CPU-osuutta.) K8s varmistaa, että se ei sijoita palvelimelle enempää podeja kuin on prosessoriresurssit kaikkien podien painojen summalla.

Miten tämä tapahtuu? Kun lisäät palvelimen Kubernetes-klusteriin, raportoidaan, kuinka monta CPU-ydintä sillä on käytettävissä. Ja kun luot uutta podia, Kubernetes-ajastin tietää, kuinka monta ydintä tämä pod tarvitsee. Siten pod osoitetaan palvelimelle, jossa on tarpeeksi ytimiä.

Mitä tapahtuu jos ei pyyntö on määritetty (eli podissa ei ole määritettyä määrää sen tarvitsemia ytimiä)? Selvitetään, kuinka Kubernetes yleensä laskee resursseja.

Podille voit määrittää sekä pyynnöt (CFS-aikataulu) että rajat (muistatko liikennevalon?):

  • Jos ne määritetään yhtäläisiksi, podille määritetään QoS-luokka taattu. Tämä aina käytettävissä oleva määrä ytimiä on taattu.
  • Jos pyyntö on pienempi kuin raja - QoS-luokka räjähtävä. Nuo. Odotamme esimerkiksi podin käyttävän aina yhtä ydintä, mutta tämä arvo ei ole sille rajoitus: joskus pod voi käyttää enemmän (kun palvelimella on vapaita resursseja tähän).
  • Siellä on myös QoS-luokka paras ponnistus — se sisältää juuri ne palot, joille pyyntöä ei ole määritelty. Resurssit annetaan heille viimeisenä.

Память

Muistin kanssa tilanne on samanlainen, mutta hieman erilainen - loppujen lopuksi näiden resurssien luonne on erilainen. Yleisesti ottaen analogia on seuraava:

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Katsotaan kuinka pyynnöt toteutetaan muistissa. Anna podien elää palvelimella ja muuttaa muistin kulutusta, kunnes yksi niistä kasvaa niin suureksi, että sen muisti loppuu. Tässä tapauksessa OOM-tappaja ilmestyy ja tappaa suurimman prosessin:

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Tämä ei aina sovi meille, joten on mahdollista säännellä, mitkä prosessit ovat meille tärkeitä ja joita ei pidä tappaa. Käytä tätä varten parametria oom_score_adj.

Palataan CPU:n QoS-luokkiin ja piirretään analogia oom_score_adj-arvojen kanssa, jotka määrittävät podien muistinkulutusprioriteetit:

  • Alin oom_score_adj arvo podille -998 - tarkoittaa, että tällainen pod tulisi tappaa viimeisenä, tämä taattu.
  • Korkein - 1000 - on paras ponnistus, tällaiset palot tapetaan ensin.
  • Laskeaksesi jäljellä olevat arvot (räjähtävä) on kaava, jonka ydin kiteytyy siihen, että mitä enemmän resursseja pod on pyytänyt, sitä vähemmän todennäköistä on, että se tapetaan.

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Toinen "käänne" - limit_in_bytes - rajoja varten. Sen avulla kaikki on yksinkertaisempaa: määritämme yksinkertaisesti myönnetyn muistin enimmäismäärän, ja täällä (toisin kuin CPU) ei ole kysymys siitä, kuinka se mitataan (muisti).

Yhteensä

Jokainen Kubernetesin pod on annettu requests и limits - molemmat parametrit suorittimelle ja muistille:

  1. pyyntöjen perusteella toimii Kubernetes-ajastin, joka jakaa podeja palvelimien kesken;
  2. kaikkien parametrien perusteella podin QoS-luokka määritetään;
  3. Suhteelliset painot lasketaan suorittimen pyyntöjen perusteella;
  4. CFS-aikataulu on konfiguroitu CPU-pyyntöjen perusteella;
  5. OOM-killer on määritetty muistipyyntöjen perusteella;
  6. "liikennevalo" on määritetty suorittimen rajojen perusteella;
  7. Muistirajojen perusteella cgroupille on määritetty raja.

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Yleisesti ottaen tämä kuva vastaa kaikkiin kysymyksiin siitä, kuinka pääosa resurssienhallinnasta tapahtuu Kubernetesissa.

Automaattinen skaalaus

K8s cluster-autoscaler

Kuvitellaan, että koko klusteri on jo varattu ja uusi pod on luotava. Vaikka pod ei näy, se roikkuu tilassa Odotustilassa. Jotta se ilmestyisi, voimme yhdistää klusteriin uuden palvelimen tai... asentaa cluster-autoscalerin, joka tekee sen puolestamme: tilaa virtuaalikoneen pilvipalveluntarjoajalta (API-pyynnön avulla) ja yhdistä se klusteriin. , jonka jälkeen pod lisätään .

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Tämä on Kubernetes-klusterin automaattinen skaalaus, joka toimii hyvin (kokemuksemme mukaan). Kuitenkin, kuten muuallakin, tässä on joitain vivahteita...

Niin kauan kuin lisäsimme klusterin kokoa, kaikki oli hyvin, mutta mitä tapahtuu, kun klusteri alkoi vapauttaa itsensä? Ongelmana on, että podien siirtäminen (isäntien vapauttamiseksi) on teknisesti erittäin vaikeaa ja kallista resurssien kannalta. Kubernetes käyttää täysin erilaista lähestymistapaa.

Harkitse 3 palvelimen klusteria, jossa on käyttöönotto. Siinä on 6 podia: nyt niitä on 2 jokaiselle palvelimelle. Jostain syystä halusimme sammuttaa yhden palvelimista. Tätä varten käytämme komentoa kubectl drain, joka:

  • kieltää uusien koteloiden lähettämisen tälle palvelimelle;
  • poistaa olemassa olevat podit palvelimelta.

Koska Kubernetes on vastuussa palojen lukumäärän (6) ylläpitämisestä, se yksinkertaisesti tulee luomaan uudelleen ne muissa solmuissa, mutta ei siinä, joka on poistettu käytöstä, koska se on jo merkitty ei-käytettävissä uusien podien isännöintiin. Tämä on Kubernetesin perusmekaniikka.

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Tässä on kuitenkin myös vivahde. Samanlaisessa tilanteessa StatefulSetin (Deploymentin sijaan) toiminnot ovat erilaisia. Nyt meillä on jo tilallinen sovellus - esimerkiksi kolme podia MongoDB:n kanssa, joista yhdessä on jonkinlainen ongelma (tiedot ovat vioittuneet tai jokin muu virhe, joka estää podia käynnistymästä oikein). Ja päätämme jälleen poistaa yhden palvelimen käytöstä. Mitä tapahtuu?

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

MongoDB voisi kuolee, koska se tarvitsee päätösvaltaisuuden: kolmen asennuksen klusterissa vähintään kahden on toimittava. Kuitenkin tämä ei tapahdu - kiitokset PodDisruptionBudget. Tämä parametri määrittää tarvittavan työpalojen vähimmäismäärän. Tietäen, että yksi MongoDB-tyypeistä ei enää toimi, ja nähdä, että PodDisruptionBudget on asetettu MongoDB:lle minAvailable: 2, Kubernetes ei salli podin poistamista.

Bottom line: jotta podien siirto (ja itse asiassa uudelleenluominen) toimisi oikein, kun klusteri vapautetaan, sinun on määritettävä PodDisruptionBudget.

Vaakasuora skaalaus

Ajatellaanpa toista tilannetta. Kubernetesissa on sovellus, joka toimii käyttöönottona. Käyttäjäliikenne tulee sen podeihin (niitä on esimerkiksi kolme), ja mittaamme niissä tietyn indikaattorin (esim. prosessorin kuormituksen). Kun kuormitus kasvaa, tallennamme sen aikataulun mukaisesti ja lisäämme podien määrää pyyntöjen jakamiseksi.

Nykyään Kubernetesissa tätä ei tarvitse tehdä manuaalisesti: koteloiden lukumäärän automaattinen lisäys/vähennys konfiguroidaan mitattujen kuormitusilmaisimien arvojen mukaan.

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Tärkeimmät kysymykset tässä ovat: mitä tarkalleen mitataan и miten tulkita saadut arvot (palojen lukumäärän muuttamisen päätöksen tekemiseksi). Voit mitata paljon:

Automaattinen skaalaus ja resurssien hallinta Kubernetesissa (yleiskatsaus ja videoraportti)

Kuinka tehdä tämä teknisesti - kerää mittareita jne. – Puhuin raportissa yksityiskohtaisesti aiheesta Valvonta ja Kubernetes. Ja tärkein neuvo optimaalisten parametrien valitsemiseksi on koe!

On KÄYTÄ menetelmää (Käyttökylläisyys ja virheet), jonka merkitys on seuraava. Millä perusteella on järkevää skaalata esimerkiksi php-fpm? Perustuu siihen, että työntekijät ovat loppumassa, tämä on käyttö. Ja jos työntekijät ovat loppuneet eikä uusia yhteyksiä oteta vastaan, tämä on jo kyllästyminen. Molemmat parametrit on mitattava ja arvoista riippuen on suoritettava skaalaus.

Sen sijaan johtopäätös

Raportissa on jatkoa: vertikaalisesta skaalauksesta ja oikeiden resurssien valitsemisesta. Puhun tästä tulevissa videoissa meidän YouTube - Tilaa niin et jää paitsi!

Videot ja diat

Video esityksestä (44 minuuttia):

Raportin esittely:

PS.

Muita raportteja Kubernetesista blogissamme:

Lähde: will.com

Lisää kommentti