Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes
Questu articulu vi aiuterà à capisce cumu funziona l'equilibriu di carica in Kubernetes, ciò chì succede quandu si scalanu e cunnessione di longa durata, è perchè duvete cunsiderà l'equilibriu di u cliente se utilizate HTTP/2, gRPC, RSockets, AMQP, o altri protokolli longevi. . 

Un pocu di cumu u trafficu hè ridistribuitu in Kubernetes 

Kubernetes furnisce duie astrazioni convenienti per implementà l'applicazioni: servizii è implementazioni.

I dispiegamenti descrizanu cumu è quante copie di a vostra applicazione deve esse in esecuzione in ogni mumentu. Ogni applicazione hè implementata cum'è Pod è hè assignatu un indirizzu IP.

I servizii sò simili in funzione à un balancer di carica. Sò pensati per distribuisce u trafficu in parechje pods.

Videmu ciò chì pare.

  1. In u diagramma sottu, pudete vede trè istanze di a stessa applicazione è un equilibratore di carica:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  2. U balancer di carica hè chjamatu serviziu è hè assignatu un indirizzu IP. Ogni dumanda entrante hè rediretta à unu di i pods:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  3. U scenariu di implementazione determina u numeru di casi di l'applicazione. Ùn avete quasi mai bisognu di espansione direttamente sottu:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  4. Ogni pod hè assignatu u so propiu indirizzu IP:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

Hè utile à pensà à i servizii cum'è una cullizzioni di indirizzi IP. Ogni volta chì accede à u serviziu, unu di l'indirizzi IP hè sceltu da a lista è utilizatu cum'è l'indirizzu di destinazione.

Sembra cusì.

  1. Una dumanda curl 10.96.45.152 hè ricevutu à u serviziu:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  2. U serviziu selezziunate unu di trè indirizzi pod cum'è destinazione:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  3. U trafficu hè reindirizzatu à un pod specificu:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

Se a vostra applicazione hè custituita da un frontend è un backend, allora avete un serviziu è una implementazione per ognunu.

Quandu u frontend face una dumanda à u backend, ùn hà micca bisognu di sapè esattamente quanti pods serve u backend: puderia esse unu, deci o centu.

Inoltre, u frontend ùn sapi nunda di l'indirizzi di i pods chì serve u backend.

Quandu u frontend face una dumanda à u backend, usa l'indirizzu IP di u serviziu backend, chì ùn cambia micca.

Questu hè ciò chì pare.

  1. Under 1 richiede u cumpunente backend internu. Invece di selezziunate una specifica per u backend, face una dumanda à u serviziu:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  2. U serviziu selezziunate unu di i pods backend cum'è l'indirizzu di destinazione:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  3. U trafficu va da Pod 1 à Pod 5, sceltu da u serviziu:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  4. Under 1 ùn sà micca esattamente quanti pods cum'è sottu 5 sò oculati daretu à u serviziu:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

Ma cumu esattamente u serviziu distribuisce e dumande? Sembra chì l'equilibriu round-robin hè adupratu? Scupritemu. 

Equilibratu in i servizii Kubernetes

I servizii Kubernetes ùn esistenu micca. Ùn ci hè micca prucessu per u serviziu chì hè assignatu un indirizzu IP è un portu.

Pudete verificà questu loging in ogni nodu in u cluster è eseguisce u cumandamentu netstat -ntlp.

Ùn puderà mancu truvà l'indirizzu IP attribuitu à u serviziu.

L'indirizzu IP di u serviziu hè situatu in a capa di cuntrollu, in u controller, è arregistratu in a basa di dati - etcd. U listessu indirizzu hè utilizatu da un altru cumpunente - kube-proxy.
Kube-proxy riceve una lista di indirizzi IP per tutti i servizii è genera un set di reguli iptables in ogni node in u cluster.

Queste regule dicenu: "Se vedemu l'indirizzu IP di u serviziu, avemu bisognu di mudificà l'indirizzu di destinazione di a dumanda è mandà à unu di i pods".

L'indirizzu IP di u serviziu hè utilizatu solu cum'è un puntu di ingressu è ùn hè micca servutu da alcun prucessu chì ascolta l'indirizzu IP è u portu.

Fighjemu questu

  1. Cunsiderate un cluster di trè nodi. Ogni nodu hà pods:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  2. I baccelli legati dipinti beige sò parti di u serviziu. Perchè u serviziu ùn esiste micca cum'è un prucessu, hè mostratu in grisgiu:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  3. U primu pod richiede un serviziu è deve andà à unu di i pods associati:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  4. Ma u serviziu ùn esiste micca, u prucessu ùn esiste micca. Cumu funziona?

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  5. Prima chì a dumanda abbanduneghja u node, passa per e regule iptables:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  6. E regule iptables sapemu chì u serviziu ùn esiste micca è rimpiazzà u so indirizzu IP cù unu di l'indirizzi IP di i pods assuciati cù quellu serviziu:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  7. A dumanda riceve un indirizzu IP validu cum'è l'indirizzu di destinazione è hè trattatu nurmale:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  8. Sicondu a topologia di a rete, a dumanda eventualmente ghjunghje à u pod:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

Pò l'equilibriu di carica iptables?

No, iptables sò usati per filtru è ùn sò micca stati pensati per equilibrà.

In ogni casu, hè pussibule di scrive un inseme di regule chì travaglianu cum'è pseudo-balancer.

È questu hè esattamente ciò chì hè implementatu in Kubernetes.

Se avete trè pods, kube-proxy scriverà e seguenti regule:

  1. Selezziunate u primu sottu cù una probabilità di 33%, altrimenti vai à a regula dopu.
  2. Sceglite u sicondu cù una probabilità di 50%, altrimenti vai à a regula dopu.
  3. Selezziunà u terzu sottu.

Stu sistema risulta chì ogni pod hè sceltu cù una probabilità di 33%.

Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

È ùn ci hè micca garanzia chì Pod 2 serà sceltu dopu dopu à Pod 1.

Vita: iptables usa un modulu statisticu cù distribuzione aleatoria. Cusì, l'algoritmu di equilibriu hè basatu annantu à a selezzione aleatoria.

Avà chì avete capitu cumu funziona i servizii, fighjemu i scenarii di serviziu più interessanti.

I cunnessione di longa vita in Kubernetes ùn sò micca scalate per automaticamente

Ogni dumanda HTTP da u frontend à u backend hè servita da una cunnessione TCP separata, chì hè aperta è chjusa.

Se u frontend manda 100 richieste per seconda à u backend, allora 100 diverse cunnessione TCP sò aperte è chjuse.

Pudete riduce u tempu di trasfurmazione di e dumande è a carica aprendu una cunnessione TCP è aduprendu per tutte e richieste HTTP successive.

U protocolu HTTP hà una funzione chjamata HTTP keep-alive, o reutilizazione di cunnessione. In questu casu, una sola cunnessione TCP hè aduprata per mandà è riceve parechje dumande è risposte HTTP:

Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

Questa funzione ùn hè micca attivata per difettu: u servitore è u cliente deve esse cunfigurati in cunfurmità.

A cunfigurazione stessu hè simplice è accessibile per a maiò parte di i linguaggi di prugrammazione è l'ambienti.

Eccu alcuni ligami per esempi in diverse lingue:

Chì succede se usemu mantene a vita in un serviziu Kubernetes?
Assumimu chì sia u frontend sia u supportu backend mantenenu in vita.

Avemu una copia di u frontend è trè copie di u backend. U frontend face a prima dumanda è apre una cunnessione TCP à u backend. A dumanda righjunghji u serviziu, unu di i pods backend hè sceltu cum'è l'indirizzu di destinazione. U backend manda una risposta, è u frontend riceve.

A cuntrariu di a situazione abituale induve a cunnessione TCP hè chjusa dopu avè ricivutu una risposta, hè avà mantenuta aperta per più richieste HTTP.

Chì succede se u frontend manda più richieste à u backend?

Per rinvià queste dumande, una cunnessione TCP aperta serà utilizata, tutte e dumande andaranu à u listessu backend induve a prima dumanda hè andata.

Iptables ùn deve micca redistribuisce u trafficu?

Micca in stu casu.

Quandu una cunnessione TCP hè creata, passa per e regule iptables, chì selezziunate un backend specificu induve u trafficu andarà.

Siccomu tutte e dumande sussegwenti sò in una cunnessione TCP digià aperta, e regule iptables ùn sò più chjamate.

Videmu ciò chì pare.

  1. U primu pod manda una dumanda à u serviziu:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  2. Sapete digià ciò chì succede dopu. U serviziu ùn esiste micca, ma ci sò e regule iptables chì processanu a dumanda:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  3. Unu di i pods backend serà sceltu cum'è l'indirizzu di destinazione:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  4. A dumanda ghjunghje à u pod. À questu puntu, una cunnessione TCP persistente trà i dui pods serà stabilitu:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  5. Ogni dumanda successiva da u primu pod passerà per a cunnessione digià stabilita:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

U risultatu hè un tempu di risposta più veloce è un throughput più altu, ma perde a capacità di scala u backend.

Ancu s'è avete dui pods in u backend, cù una cunnessione constante, u trafficu andarà sempre à unu di elli.

Pò esse riparatu?

Siccomu Kubernetes ùn sapi micca cumu per equilibrà e cunnessione persistenti, sta operazione vi tocca.

I servizii sò una cullizzioni di indirizzi IP è porti chjamati endpoints.

A vostra applicazione pò uttene una lista di punti finali da u serviziu è decide cumu distribuisce e dumande trà elli. Pudete apre una cunnessione persistente à ogni pod è e dumande di equilibriu trà queste cunnessione usendu round-robin.

O applica più algoritmi cumplessi di equilibriu.

U codice di u cliente chì hè rispunsevule per l'equilibriu deve seguità sta logica:

  1. Ottene una lista di endpoints da u serviziu.
  2. Apertura una cunnessione persistente per ogni endpoint.
  3. Quandu una dumanda deve esse fatta, utilizate una di e cunnessione aperte.
  4. Aghjurnà regularmente a lista di punti finali, creanu novi o chjude e vechji cunnessione persistenti se a lista cambia.

Questu hè ciò chì parerà.

  1. Invece di u primu pod chì invià a dumanda à u serviziu, pudete equilibrà e dumande da u cliente:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  2. Avete bisognu di scrive codice chì dumanda quale pods sò parti di u serviziu:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  3. Una volta avete a lista, salvala nantu à u latu di u cliente è l'utilizate per cunnette à i pods:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

  4. Sò rispunsevuli di l'algoritmu di equilibriu di carica:

    Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

Avà a quistione si pone: stu prublema hè solu appiicata à HTTP keep-alive?

Bilanciamentu di carica da u cliente

HTTP ùn hè micca l'unicu protokollu chì pò utilizà cunnessione TCP persistenti.

Se a vostra applicazione usa una basa di dati, allora una cunnessione TCP ùn hè micca aperta ogni volta chì avete bisognu di fà una dumanda o ricuperà un documentu da a basa di dati. 

Invece, una cunnessione TCP persistente à a basa di dati hè aperta è utilizata.

Se a vostra basa di dati hè implementata nantu à Kubernetes è l'accessu hè furnitu cum'è un serviziu, allora truverete i stessi prublemi descritti in a sezione precedente.

Una replica di basa di dati serà più caricata cà l'altri. Kube-proxy è Kubernetes ùn aiutanu micca à equilibrà e cunnessione. Duvete piglià cura di equilibrà e dumande à a vostra basa di dati.

Sicondu a biblioteca chì utilizate per cunnette à a basa di dati, pudete avè diverse opzioni per risolve stu prublema.

Quì sottu hè un esempiu di accede à un cluster di basa di dati MySQL da Node.js:

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

Ci sò parechji altri protokolli chì utilizanu cunnessione TCP persistenti:

  • WebSockets è WebSockets assicurati
  • HTTP / 2
  • gRPC
  • RSockets
  • AMQP

Avete digià esse familiarizatu cù a maiò parte di sti protokolli.

Ma se sti protokolli sò cusì populari, perchè ùn ci hè micca una suluzione standardizata di equilibriu? Perchè a logica di u cliente deve cambià? Ci hè una soluzione nativa Kubernetes?

Kube-proxy è iptables sò pensati per copre i casi di usu più cumuni quandu si implementanu in Kubernetes. Questu hè per comodità.

Sè vo aduprate un serviziu web chì espone una API REST, site in furtuna - in questu casu, i cunnessione TCP persistenti ùn sò micca utilizati, pudete aduprà qualsiasi serviziu Kubernetes.

Ma una volta chì cuminciate à aduprà cunnessione TCP persistenti, duverete capisce cumu distribuisce uniformemente a carica in i backends. Kubernetes ùn cuntene solu suluzione pronta per questu casu.

Tuttavia, ci sò certamenti opzioni chì ponu aiutà.

Equilibrà e cunnessione longu in Kubernetes

Ci sò quattru tippi di servizii in Kubernetes:

  1. ClusterIP
  2. NodePort
  3. LoadBalancer
  4. Senza capu

I primi trè servizii operanu basatu annantu à un indirizzu IP virtuale, chì hè utilizatu da kube-proxy per custruisce e regule iptables. Ma a basa fundamentale di tutti i servizii hè un serviziu senza capu.

U serviziu senza capu ùn hà micca indirizzu IP assuciatu cù ellu è furnisce solu un mecanismu per ricuperà una lista di indirizzi IP è porti di i pods (endpoints) assuciati cun ellu.

Tutti i servizii sò basati nantu à u serviziu senza testa.

U serviziu ClusterIP hè un serviziu senza testa cù alcune aghjunte: 

  1. A strata di gestione li assigna un indirizzu IP.
  2. Kube-proxy genera e regule iptables necessarie.

In questu modu pudete ignurà kube-proxy è aduprà direttamente a lista di punti finali ottenuti da u serviziu senza testa per equilibrà a vostra applicazione.

Ma cumu pudemu aghjunghje una logica simile à tutte l'applicazioni implementate in u cluster?

Se a vostra applicazione hè digià implementata, questu compitu pò pare micca impussibile. Tuttavia, ci hè una opzione alternativa.

Service Mesh vi aiuterà

Probabilmente avete digià nutatu chì a strategia di bilanciamentu di carica di u cliente hè abbastanza standard.

Quandu l'applicazione principia, hè:

  1. Ottene una lista di l'indirizzi IP da u serviziu.
  2. Apre è mantene una piscina di cunnessione.
  3. Aggiorna periodicamente a piscina aghjustendu o rimuovendu endpoints.

Una volta chì l'applicazione vole fà una dumanda, questu:

  1. Selezziunate una cunnessione dispunibile utilizendu una certa logica (per esempiu, round-robin).
  2. Esegue a dumanda.

Questi passi funzionanu per e cunnessione WebSockets, gRPC è AMQP.

Pudete separà sta logica in una biblioteca separata è aduprà in e vostre applicazioni.

In ogni casu, pudete aduprà e rete di serviziu cum'è Istio o Linkerd invece.

Service Mesh aumenta a vostra applicazione cù un prucessu chì:

  1. Ricerca automaticamente l'indirizzi IP di serviziu.
  2. Testa e cunnessione cum'è WebSockets è gRPC.
  3. Equilibra e dumande utilizendu u protocolu currettu.

Service Mesh aiuta à gestisce u trafficu in u cluster, ma hè abbastanza risorsa intensiva. Altre opzioni sò aduprendu biblioteche di terze parti cum'è Netflix Ribbon o proxy programabili cum'è Envoy.

Chì succede si ignora i prublemi di equilibriu?

Pudete sceglie micca di utilizà l'equilibriu di carica è ancu ùn avvistà micca cambiamenti. Fighjemu uni pochi di scenarii di travagliu.

Sì avete più clienti chì servitori, questu ùn hè micca un prublema cusì grande.

Diciamu chì ci sò cinque clienti chì cunnette cù dui servitori. Ancu s'ellu ùn ci hè micca equilibriu, i dui servitori seranu utilizati:

Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

E cunnessione ùn ponu esse distribuite uniformemente: forse quattru clienti cunnessi à u stessu servitore, ma ci hè una bona chance chì i dui servitori seranu utilizati.

Ciò chì hè più problematicu hè u scenariu oppostu.

Sì avete menu clienti è più servitori, i vostri risorse ponu esse sottoutilizati è appariscerà un putenziale collu di bottiglia.

Diciamu chì ci sò dui clienti è cinque servitori. In u megliu casu, ci saranu duie cunnessione permanente à dui servitori fora di cinque.

I servitori rimanenti saranu inattivi:

Bilanciamentu di carica è scala di cunnessione di longa durata in Kubernetes

Sì sti dui servitori ùn ponu micca trattà e dumande di i clienti, a scala horizontale ùn aiuta micca.

cunchiusioni

I servizii Kubernetes sò pensati per travaglià in a maiò parte di i scenarii di applicazioni web standard.

In ogni casu, quandu avete principiatu à travaglià cù protokolli di l'applicazione chì utilizanu cunnessione TCP persistenti, cum'è basa di dati, gRPC o WebSockets, i servizii ùn sò più adattati. Kubernetes ùn furnisce micca miccanismi interni per equilibrà e cunnessione TCP persistenti.

Questu significa chì duvete scrive l'applicazioni cù l'equilibriu di u cliente in mente.

Traduzzione preparata da a squadra Kubernetes aaS da Mail.ru.

Chì altru à leghje nantu à u tema:

  1. Trè livelli di autoscaling in Kubernetes è cumu aduprà in modu efficace
  2. Kubernetes in u spiritu di pirateria cù un mudellu per l'implementazione.
  3. U nostru canale Telegram nantu à a trasfurmazioni digitale.

Source: www.habr.com

Add a comment