Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus
Tämä artikkeli auttaa sinua ymmärtämään, kuinka kuormituksen tasapainotus toimii Kubernetesissa, mitä tapahtuu, kun skaalataan pitkäikäisiä yhteyksiä ja miksi sinun tulee harkita asiakaspuolen tasapainottamista, jos käytät HTTP/2-, gRPC-, RSockets-, AMQP- tai muita pitkäikäisiä protokollia. . 

Hieman siitä, kuinka liikenne jaetaan uudelleen Kubernetesissa 

Kubernetes tarjoaa kaksi kätevää abstraktiota sovellusten käyttöönottoon: palvelut ja käyttöönotot.

Käyttöönotot kuvaavat, kuinka ja kuinka monta kopiota sovelluksestasi tulee olla käynnissä kulloinkin. Jokainen sovellus otetaan käyttöön Pod-yksikönä ja sille on määritetty IP-osoite.

Palvelut ovat toiminnaltaan samanlaisia ​​kuin kuormituksen tasapainottaja. Ne on suunniteltu jakamaan liikennettä useisiin koteloihin.

Katsotaan miltä se näyttää.

  1. Alla olevassa kaaviossa näet kolme esimerkkiä samasta sovelluksesta ja kuormituksen tasapainottimesta:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  2. Kuormituksen tasapainotinta kutsutaan palveluksi ja sille on määritetty IP-osoite. Kaikki saapuvat pyynnöt ohjataan johonkin ryhmistä:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  3. Käyttöönottoskenaario määrittää sovelluksen esiintymien lukumäärän. Sinun ei melkein koskaan tarvitse laajentaa suoraan alla:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  4. Jokaiselle podille on määritetty oma IP-osoite:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

On hyödyllistä ajatella palveluita IP-osoitteiden kokoelmana. Aina kun käytät palvelua, yksi IP-osoitteista valitaan luettelosta ja sitä käytetään kohdeosoitteena.

Se näyttää tältä.

  1. Palveluun on vastaanotettu curl 10.96.45.152 pyyntö:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  2. Palvelu valitsee määränpääksi yhden kolmesta pod-osoitteesta:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  3. Liikenne ohjataan tiettyyn ryhmään:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

Jos sovelluksesi koostuu käyttöliittymästä ja taustajärjestelmästä, sinulla on kummallekin sekä palvelu että käyttöönotto.

Kun käyttöliittymä tekee pyynnön taustajärjestelmälle, sen ei tarvitse tietää tarkalleen kuinka monta podia backend palvelee: niitä voi olla yksi, kymmenen tai sata.

Lisäksi käyttöliittymä ei tiedä mitään taustaosaa palvelevien pod-osoitteiden osoitteista.

Kun käyttöliittymä tekee pyynnön taustajärjestelmälle, se käyttää taustapalvelun IP-osoitetta, joka ei muutu.

Näin se näyttää.

  1. Under 1 pyytää sisäistä taustakomponenttia. Sen sijaan, että valitsisi tietyn taustajärjestelmän, se lähettää palvelulle pyynnön:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  2. Palvelu valitsee kohdeosoitteeksi yhden taustapäätyypeistä:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  3. Liikenne kulkee Pod 1:stä Pod 5:een, jonka palvelu valitsee:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  4. Alle 1 ei tiedä tarkalleen kuinka monta alle 5:n kaltaista podia on piilotettu palvelun taakse:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

Mutta miten palvelu tarkalleen jakaa pyynnöt? Näyttää siltä, ​​​​että käytetään round robin -tasapainotusta? Selvitetään se. 

Tasapainotus Kubernetes-palveluissa

Kubernetes-palveluita ei ole olemassa. Palvelulle, jolle on määritetty IP-osoite ja portti, ei ole prosessia.

Voit varmistaa tämän kirjautumalla mihin tahansa klusterin solmuun ja suorittamalla komennon netstat -ntlp.

Et edes löydä palvelulle osoitettua IP-osoitetta.

Palvelun IP-osoite sijaitsee ohjauskerroksessa, ohjaimessa ja tallennettu tietokantaan - etcd. Samaa osoitetta käyttää toinen komponentti - kube-proxy.
Kube-välityspalvelin vastaanottaa luettelon kaikkien palveluiden IP-osoitteista ja luo joukon iptables-sääntöjä klusterin jokaiselle solmulle.

Näissä säännöissä sanotaan: "Jos näemme palvelun IP-osoitteen, meidän on muutettava pyynnön kohdeosoitetta ja lähetettävä se johonkin podista."

Palvelun IP-osoitetta käytetään vain sisääntulopisteenä, eikä sitä palvele mikään tätä IP-osoitetta ja porttia kuunteleva prosessi.

Katsotaanpa tätä

  1. Tarkastellaan kolmen solmun klusteria. Jokaisessa solmussa on tyynyt:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  2. Beigiksi maalatut sidotut palot ovat osa palvelua. Koska palvelua ei ole olemassa prosessina, se näkyy harmaana:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  3. Ensimmäinen ryhmä pyytää palvelua ja sen on siirryttävä johonkin liitetyistä podista:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  4. Mutta palvelua ei ole olemassa, prosessia ei ole olemassa. Kuinka se toimii?

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  5. Ennen kuin pyyntö poistuu solmusta, se käy läpi iptables-säännöt:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  6. Iptables-säännöt tietävät, että palvelua ei ole olemassa, ja korvaavat sen IP-osoitteen jollakin kyseiseen palveluun liittyvien pod-osoitteiden IP-osoitteista:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  7. Pyyntö saa kelvollisen IP-osoitteen kohdeosoitteeksi ja se käsitellään normaalisti:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  8. Verkkotopologiasta riippuen pyyntö saavuttaa lopulta pod:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

Voiko iptables tasapainottaa kuormitusta?

Ei, iptablesia käytetään suodatukseen, eikä niitä ole suunniteltu tasapainottamiseen.

On kuitenkin mahdollista kirjoittaa joukko sääntöjä, jotka toimivat kuten pseudo-tasapainotin.

Ja tämä on juuri se, mitä Kubernetesissa toteutetaan.

Jos sinulla on kolme podia, kube-proxy kirjoittaa seuraavat säännöt:

  1. Valitse ensimmäinen osa todennäköisyydellä 33 %, muussa tapauksessa siirry seuraavaan sääntöön.
  2. Valitse toinen todennäköisyydellä 50%, muussa tapauksessa siirry seuraavaan sääntöön.
  3. Valitse alta kolmas.

Tämä järjestelmä johtaa siihen, että jokainen pod valitaan 33 %:n todennäköisyydellä.

Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

Eikä ole mitään takeita siitä, että Pod 2 valitaan seuraavaksi Pod 1:n jälkeen.

Huomata: iptables käyttää satunnaisjakaumaa tilastollista moduulia. Näin ollen tasapainotusalgoritmi perustuu satunnaiseen valintaan.

Nyt kun ymmärrät, miten palvelut toimivat, katsotaanpa mielenkiintoisempia palveluskenaarioita.

Pitkäikäiset yhteydet Kubernetesissa eivät skaalaudu oletusarvoisesti

Jokaista HTTP-pyyntöä käyttöliittymästä taustajärjestelmään palvelee erillinen TCP-yhteys, joka avataan ja suljetaan.

Jos käyttöliittymä lähettää taustalle 100 pyyntöä sekunnissa, 100 erilaista TCP-yhteyttä avataan ja suljetaan.

Voit lyhentää pyyntöjen käsittelyaikaa ja kuormitusta avaamalla yhden TCP-yhteyden ja käyttämällä sitä kaikissa myöhemmissä HTTP-pyynnöissä.

HTTP-protokollassa on ominaisuus nimeltä HTTP keep-alive tai yhteyden uudelleenkäyttö. Tässä tapauksessa yhtä TCP-yhteyttä käytetään useiden HTTP-pyyntöjen ja vastausten lähettämiseen ja vastaanottamiseen:

Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

Tämä ominaisuus ei ole oletusarvoisesti käytössä: sekä palvelin että asiakas on määritettävä vastaavasti.

Itse asennus on yksinkertainen ja käytettävissä useimmille ohjelmointikielille ja ympäristöille.

Tässä muutamia linkkejä esimerkkeihin eri kielillä:

Mitä tapahtuu, jos käytämme Keep-alive-toimintoa Kubernetes-palvelussa?
Oletetaan, että sekä käyttöliittymä että taustaosa tukevat pysymistä elossa.

Meillä on yksi kopio käyttöliittymästä ja kolme kopiota taustaosasta. Käyttöliittymä tekee ensimmäisen pyynnön ja avaa TCP-yhteyden taustajärjestelmään. Pyyntö saapuu palveluun, kohdeosoitteeksi valitaan yksi taustapäätyypeistä. Taustaosa lähettää vastauksen ja käyttöliittymä vastaanottaa sen.

Toisin kuin tavallisessa tilanteessa, jossa TCP-yhteys suljetaan vastauksen saatuaan, se pidetään nyt avoinna muita HTTP-pyyntöjä varten.

Mitä tapahtuu, jos käyttöliittymä lähettää lisää pyyntöjä taustalle?

Näiden pyyntöjen välittämiseen käytetään avointa TCP-yhteyttä, kaikki pyynnöt menevät samaan taustajärjestelmään, johon ensimmäinen pyyntö meni.

Eikö iptablesin pitäisi jakaa liikennettä uudelleen?

Ei tässä tapauksessa.

Kun TCP-yhteys luodaan, se käy läpi iptables-säännöt, jotka valitsevat tietyn taustajärjestelmän, johon liikenne kulkee.

Koska kaikki myöhemmät pyynnöt ovat jo avoimessa TCP-yhteydessä, iptables-sääntöjä ei enää kutsuta.

Katsotaan miltä se näyttää.

  1. Ensimmäinen pod lähettää pyynnön palveluun:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  2. Tiedät jo mitä seuraavaksi tapahtuu. Palvelua ei ole olemassa, mutta on olemassa iptables-sääntöjä, jotka käsittelevät pyynnön:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  3. Yksi taustapäätyypeistä valitaan kohdeosoitteeksi:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  4. Pyyntö saapuu koteloon. Tässä vaiheessa kahden podin välille muodostetaan jatkuva TCP-yhteys:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  5. Kaikki myöhemmät pyynnöt ensimmäisestä ryhmästä kulkevat jo muodostetun yhteyden kautta:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

Tuloksena on nopeampi vasteaika ja suurempi suorituskyky, mutta menetät kyvyn skaalata taustaa.

Vaikka taustajärjestelmässä olisi kaksi podia, liikenne kulkee aina yhteen niistä.

Voiko tämän korjata?

Koska Kubernetes ei osaa tasapainottaa pysyviä yhteyksiä, tämä tehtävä kuuluu sinulle.

Palvelut ovat kokoelma IP-osoitteita ja portteja, joita kutsutaan päätepisteiksi.

Sovelluksesi voi saada luettelon päätepisteistä palvelusta ja päättää, kuinka pyynnöt jaetaan niiden välillä. Voit avata jatkuvan yhteyden jokaiseen podiin ja tasapainottaa pyyntöjä näiden yhteyksien välillä käyttämällä kiertoajoa.

Tai hakea lisää monimutkaiset tasapainotusalgoritmit.

Tasapainotuksesta vastaavan asiakaspuolen koodin tulee noudattaa tätä logiikkaa:

  1. Hanki luettelo päätepisteistä palvelusta.
  2. Avaa pysyvä yhteys jokaiselle päätepisteelle.
  3. Kun pyyntö on tehtävä, käytä jotakin avoimista yhteyksistä.
  4. Päivitä päätepisteiden luettelo säännöllisesti, luo uusia tai sulje vanhat pysyvät yhteydet, jos luettelo muuttuu.

Tältä se tulee näyttämään.

  1. Sen sijaan, että ensimmäinen pod lähettäisi pyynnön palveluun, voit tasapainottaa pyyntöjä asiakaspuolella:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  2. Sinun on kirjoitettava koodi, joka kysyy, mitkä podit ovat osa palvelua:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  3. Kun sinulla on luettelo, tallenna se asiakaspuolelle ja käytä sitä yhteyden muodostamiseen podeihin:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

  4. Olet vastuussa kuormituksen tasapainotusalgoritmista:

    Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

Nyt herää kysymys: koskeeko tämä ongelma vain HTTP:n elossapitoa?

Asiakaspuolen kuormituksen tasapainotus

HTTP ei ole ainoa protokolla, joka voi käyttää pysyviä TCP-yhteyksiä.

Jos sovelluksesi käyttää tietokantaa, TCP-yhteyttä ei avata joka kerta, kun sinun on tehtävä pyyntö tai haettava asiakirja tietokannasta. 

Sen sijaan jatkuva TCP-yhteys tietokantaan avataan ja sitä käytetään.

Jos tietokanta on otettu käyttöön Kubernetesissa ja pääsy tarjotaan palveluna, kohtaat samat ongelmat, jotka on kuvattu edellisessä osassa.

Yksi tietokannan replika ladataan enemmän kuin muut. Kube-proxy ja Kubernetes eivät auta tasapainottamaan yhteyksiä. Sinun on huolehdittava kyselyjen tasapainottamisesta tietokantaasi.

Riippuen siitä, mitä kirjastoa käytät yhteyden muodostamiseen tietokantaan, sinulla voi olla erilaisia ​​vaihtoehtoja tämän ongelman ratkaisemiseksi.

Alla on esimerkki MySQL-tietokantaklusterin käyttämisestä Node.js:stä:

var mysql = require('mysql');
var poolCluster = mysql.createPoolCluster();

var endpoints = /* retrieve endpoints from the Service */

for (var [index, endpoint] of endpoints) {
  poolCluster.add(`mysql-replica-${index}`, endpoint);
}

// Make queries to the clustered MySQL database

On monia muita protokollia, jotka käyttävät pysyviä TCP-yhteyksiä:

  • WebSocketit ja suojatut WebSocketit
  • HTTP-/ 2
  • gRPC
  • Rpistokkeet
  • AMQP

Sinun pitäisi jo tuntea useimmat näistä protokollista.

Mutta jos nämä protokollat ​​ovat niin suosittuja, miksi ei ole olemassa standardoitua tasapainotusratkaisua? Miksi asiakaslogiikkaa pitää muuttaa? Onko olemassa natiivi Kubernetes-ratkaisua?

Kube-proxy ja iptables on suunniteltu kattamaan yleisimmät käyttötapaukset Kubernetesin käyttöönoton yhteydessä. Tämä on mukavuussyistä.

Jos käytät verkkopalvelua, joka paljastaa REST API:n, olet onnekas - tässä tapauksessa pysyviä TCP-yhteyksiä ei käytetä, voit käyttää mitä tahansa Kubernetes-palvelua.

Mutta kun alat käyttää pysyviä TCP-yhteyksiä, sinun on selvitettävä, kuinka jakaa kuorma tasaisesti taustaohjelmien kesken. Kubernetes ei sisällä valmiita ratkaisuja tähän tapaukseen.

On kuitenkin varmasti vaihtoehtoja, jotka voivat auttaa.

Tasapainottaa pitkäikäisiä yhteyksiä Kubernetesissa

Kubernetesissa on neljä erilaista palvelua:

  1. KlusteriIP
  2. Solmuportti
  3. LoadBalancer
  4. kannaton

Kolme ensimmäistä palvelua toimivat virtuaalisen IP-osoitteen perusteella, jota kube-proxy käyttää iptables-sääntöjen rakentamiseen. Mutta kaikkien palveluiden perusta on päätön palvelu.

Päättömään palveluun ei ole liitetty IP-osoitetta, ja se tarjoaa vain mekanismin siihen liittyvien koteloiden (päätepisteiden) IP-osoitteiden ja porttien noutamiseen.

Kaikki palvelut perustuvat päättömään palveluun.

ClusterIP-palvelu on päätön palvelu, jossa on joitain lisäyksiä: 

  1. Hallintakerros määrittää sille IP-osoitteen.
  2. Kube-proxy luo tarvittavat iptables-säännöt.

Tällä tavalla voit ohittaa kube-proxyn ja käyttää suoraan päättömästä palvelusta saatua päätepisteluetteloa sovelluksesi kuormituksen tasapainottamiseen.

Mutta kuinka voimme lisätä samanlaisen logiikan kaikkiin klusterin sovelluksiin?

Jos sovelluksesi on jo otettu käyttöön, tämä tehtävä saattaa tuntua mahdottomalta. Vaihtoehtoinen vaihtoehto on kuitenkin olemassa.

Service Mesh auttaa sinua

Olet luultavasti jo huomannut, että asiakaspuolen kuormantasausstrategia on melko vakio.

Kun sovellus käynnistyy, se:

  1. Hakee luettelon IP-osoitteista palvelusta.
  2. Avaa ja ylläpitää yhteyspoolia.
  3. Päivittää ajoittain poolia lisäämällä tai poistamalla päätepisteitä.

Kun sovellus haluaa tehdä pyynnön, se:

  1. Valitsee käytettävissä olevan yhteyden jollakin logiikalla (esim. round-robin).
  2. Suorittaa pyynnön.

Nämä vaiheet toimivat sekä WebSockets-, gRPC- että AMQP-yhteyksissä.

Voit erottaa tämän logiikan erilliseksi kirjastoksi ja käyttää sitä sovelluksissasi.

Voit kuitenkin käyttää sen sijaan palveluverkkoja, kuten Istio tai Linkerd.

Service Mesh laajentaa sovellustasi prosessilla, joka:

  1. Hakee automaattisesti palvelun IP-osoitteita.
  2. Testaa yhteyksiä, kuten WebSockets ja gRPC.
  3. Tasapainottaa pyynnöt käyttämällä oikeaa protokollaa.

Service Mesh auttaa hallitsemaan liikennettä klusterin sisällä, mutta se on melko resurssiintensiivistä. Muita vaihtoehtoja ovat käyttää kolmannen osapuolen kirjastoja, kuten Netflix Ribbon, tai ohjelmoitavia välityspalvelimia, kuten Envoy.

Mitä tapahtuu, jos jätät huomioimatta tasapainotusongelmat?

Voit halutessasi olla käyttämättä kuormituksen tasapainotusta etkä silti huomaa muutoksia. Katsotaanpa muutamia työskenaarioita.

Jos sinulla on enemmän asiakkaita kuin palvelimia, tämä ei ole niin suuri ongelma.

Oletetaan, että on viisi asiakasta, jotka muodostavat yhteyden kahteen palvelimeen. Vaikka tasapainotusta ei olisi, molempia palvelimia käytetään:

Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

Yhteydet eivät ehkä ole jakautuneet tasaisesti: ehkä neljä asiakasta on yhteydessä samaan palvelimeen, mutta on hyvä mahdollisuus, että molempia palvelimia käytetään.

Ongelmallisempi on päinvastainen skenaario.

Jos sinulla on vähemmän asiakkaita ja enemmän palvelimia, resurssit voivat olla vajaakäytössä ja mahdollinen pullonkaula ilmaantuu.

Oletetaan, että siellä on kaksi asiakasta ja viisi palvelinta. Parhaassa tapauksessa kaksi pysyvää yhteyttä kahteen palvelimeen viidestä.

Loput palvelimet ovat käyttämättömänä:

Kubernetesin kuormituksen tasaus ja pitkäikäisten yhteyksien skaalaus

Jos nämä kaksi palvelinta eivät pysty käsittelemään asiakaspyyntöjä, vaakasuuntainen skaalaus ei auta.

Johtopäätös

Kubernetes-palvelut on suunniteltu toimimaan useimmissa tavallisissa verkkosovellusskenaarioissa.

Kun kuitenkin alat työskennellä pysyviä TCP-yhteyksiä käyttävien sovellusprotokollien, kuten tietokantojen, gRPC:n tai WebSockettien, kanssa, palvelut eivät enää sovellu. Kubernetes ei tarjoa sisäisiä mekanismeja pysyvien TCP-yhteyksien tasapainottamiseksi.

Tämä tarkoittaa, että sinun on kirjoitettava sovelluksia asiakaspuolen tasapainotusta ajatellen.

Työryhmän valmistama käännös Kubernetes aaS osoitteesta Mail.ru.

Mitä muuta luettavaa aiheesta:

  1. Kolme automaattista skaalaustasoa Kubernetesissa ja niiden tehokas käyttö
  2. Kubernetes piratismin hengessä toteutusmallilla.
  3. Telegram-kanavamme digitaalisesta muutoksesta.

Lähde: will.com

Lisää kommentti