ProHoster > Blog > İdarə > Kubernetes-də uzun ömürlü bağlantıları yükləyin və balanslaşdırın
Kubernetes-də uzun ömürlü bağlantıları yükləyin və balanslaşdırın
Bu məqalə Kubernetes-də yük balansının necə işlədiyini, uzunmüddətli bağlantıları miqyaslandırarkən nə baş verdiyini və HTTP/2, gRPC, RSockets, AMQP və ya digər uzunömürlü protokollardan istifadə edirsinizsə, niyə müştəri tərəfində balanslaşdırmanı nəzərdən keçirməli olduğunuzu anlamağa kömək edəcək. .
Kubernetes-də trafikin necə yenidən paylanması haqqında bir az
Kubernetes proqramların yerləşdirilməsi üçün iki rahat abstraksiya təqdim edir: Xidmətlər və Yerləşdirmələr.
Tətbiqlər istənilən vaxt tətbiqinizin necə və neçə nüsxəsinin işlədilməsini təsvir edir. Hər bir proqram bir Pod kimi yerləşdirilir və bir IP ünvanı təyin olunur.
Xidmətlər funksiyasına görə yük balanslaşdırıcısına bənzəyir. Onlar trafiki çoxlu podlar arasında paylamaq üçün nəzərdə tutulub.
Gəlin görək necə görünür.
Aşağıdakı diaqramda eyni tətbiqin üç nümunəsini və yük balanslaşdırıcısını görə bilərsiniz:
Yük balanslaşdırıcısı Xidmət adlanır və ona IP ünvanı verilir. İstənilən daxil olan sorğu podlardan birinə yönləndirilir:
Yerləşdirmə ssenarisi tətbiqin nümunələrinin sayını müəyyən edir. Siz demək olar ki, heç vaxt birbaşa aşağıda genişlənməli olmayacaqsınız:
Hər bir pod öz IP ünvanı təyin edilir:
Xidmətləri IP ünvanlarının toplusu kimi düşünmək faydalıdır. Siz xidmətə hər dəfə daxil olanda siyahıdan IP ünvanlarından biri seçilir və təyinat ünvanı kimi istifadə olunur.
Bu belə görünür.
Xidmətə curl 10.96.45.152 sorğusu qəbul edilir:
Xidmət təyinat olaraq üç pod ünvanından birini seçir:
Trafik xüsusi poda yönləndirilir:
Tətbiqiniz ön və arxa hissədən ibarətdirsə, hər biri üçün həm xidmət, həm də yerləşdirmə olacaq.
Frontend backend-ə sorğu göndərdikdə, arxa tərəfin neçə pod-a xidmət etdiyini dəqiq bilməyə ehtiyac yoxdur: bir, on və ya yüz ola bilər.
Həmçinin, frontend, arxa tərəfə xidmət edən podların ünvanları haqqında heç nə bilmir.
Frontend backend-ə sorğu göndərdikdə, dəyişməyən backend xidmətinin IP ünvanından istifadə edir.
Burada görünür necə.
1 altında daxili backend komponenti tələb olunur. Backend üçün xüsusi birini seçmək əvəzinə, xidmətə sorğu göndərir:
Xidmət təyinat ünvanı kimi arxa panellərdən birini seçir:
Trafik xidmət tərəfindən seçilmiş Pod 1-dən Pod 5-ə keçir:
1-dən aşağı xidmətin arxasında 5-dən aşağı kimi neçə podun gizləndiyini dəqiq bilmir:
Bəs xidmət sorğuları tam olaraq necə paylayır? Deyəsən, round-robin balanslaşdırma istifadə olunur? Gəlin bunu anlayaq.
Kubernetes xidmətlərində balanslaşdırma
Kubernetes xidmətləri mövcud deyil. IP ünvanı və port təyin edilmiş xidmət üçün heç bir proses yoxdur.
Siz klasterdəki istənilən node daxil olmaqla və netstat -ntlp əmrini işlətməklə bunu yoxlaya bilərsiniz.
Siz hətta xidmətə ayrılmış IP ünvanını tapa bilməyəcəksiniz.
Xidmətin IP ünvanı idarəetmə təbəqəsində, nəzarətçidə yerləşir və verilənlər bazasında qeyd olunur - və s. Eyni ünvan başqa bir komponent tərəfindən istifadə olunur - kube-proxy.
Kube-proxy bütün xidmətlər üçün IP ünvanlarının siyahısını alır və klasterdəki hər bir qovşaqda bir sıra iptables qaydaları yaradır.
Bu qaydalar deyir: "Xidmətin IP ünvanını görsək, sorğunun təyinat ünvanını dəyişdirməli və onu podlardan birinə göndərməliyik."
Xidmətin IP ünvanı yalnız giriş nöqtəsi kimi istifadə olunur və həmin IP ünvanı və portu dinləyən heç bir proses tərəfindən xidmət edilmir.
Gəlin buna baxaq.
Üç qovşaqdan ibarət klasteri nəzərdən keçirək. Hər bir qovşaqda podlar var:
Bej rəngə boyanmış bağlanmış podlar xidmətin bir hissəsidir. Xidmət bir proses olaraq mövcud olmadığı üçün boz rəngdə göstərilir:
Birinci pod xidmət tələb edir və əlaqəli podlardan birinə keçməlidir:
Amma xidmət yoxdur, proses yoxdur. Bu necə işləyir?
Sorğu qovşağı tərk etməzdən əvvəl iptables qaydalarından keçir:
iptables qaydaları xidmətin mövcud olmadığını bilir və onun IP ünvanını həmin xidmətlə əlaqəli podların IP ünvanlarından biri ilə əvəz edir:
Sorğu təyinat ünvanı kimi etibarlı IP ünvanı alır və normal şəkildə emal olunur:
Şəbəkə topologiyasından asılı olaraq sorğu nəhayət pod-a çatır:
iptables balansı yükləyə bilərmi?
Xeyr, iptables filtrləmə üçün istifadə olunur və balanslaşdırma üçün nəzərdə tutulmamışdır.
Üç podunuz varsa, kube-proxy aşağıdakı qaydaları yazacaq:
33% ehtimalı ilə birinci sub seçin, əks halda növbəti qaydaya keçin.
50% ehtimalı ilə ikincisini seçin, əks halda növbəti qaydaya keçin.
Altında üçüncü seçin.
Bu sistem hər bir podun 33% ehtimalla seçilməsinə səbəb olur.
Pod 2-nin Pod 1-dən sonra seçiləcəyinə heç bir zəmanət yoxdur.
Qeyd: iptables təsadüfi paylanma ilə statistik moduldan istifadə edir. Beləliklə, balanslaşdırma alqoritmi təsadüfi seçimə əsaslanır.
İndi xidmətlərin necə işlədiyini başa düşdüyünüz üçün, daha maraqlı xidmət ssenarilərinə baxaq.
Kubernetes-də uzun ömürlü bağlantılar standart olaraq ölçülənmir
Frontenddən backendə qədər hər bir HTTP sorğusu açılır və bağlanan ayrıca TCP bağlantısı ilə xidmət göstərir.
Əgər frontend arxa hissəyə saniyədə 100 sorğu göndərirsə, o zaman 100 müxtəlif TCP bağlantısı açılır və bağlanır.
Siz bir TCP bağlantısı açmaqla və ondan sonrakı bütün HTTP sorğuları üçün istifadə etməklə sorğunun emal vaxtını və yüklənməsini azalda bilərsiniz.
HTTP protokolunda HTTP-nin canlı qalması və ya əlaqənin təkrar istifadəsi adlı bir xüsusiyyət var. Bu halda, çoxsaylı HTTP sorğuları və cavabları göndərmək və qəbul etmək üçün tək TCP bağlantısı istifadə olunur:
Bu funksiya defolt olaraq aktiv edilməyib: həm server, həm də müştəri müvafiq olaraq konfiqurasiya edilməlidir.
Quraşdırma özü sadədir və əksər proqramlaşdırma dilləri və mühitləri üçün əlçatandır.
Kubernetes xidmətində canlı saxlamaqdan istifadə etsək nə baş verir?
Fərz edək ki, həm frontend, həm də arxa hissə canlı qalmağı dəstəkləyir.
Bizdə frontendin bir nüsxəsi və arxa tərəfin üç nüsxəsi var. Frontend ilk sorğunu edir və arxa tərəfə TCP bağlantısı açır. Sorğu xidmətə çatır, təyinat ünvanı kimi arxa panellərdən biri seçilir. Backend cavab göndərir və frontend onu qəbul edir.
Cavab aldıqdan sonra TCP bağlantısının bağlandığı adi vəziyyətdən fərqli olaraq, o, artıq HTTP sorğuları üçün açıq saxlanılır.
Frontend arxa hissəyə daha çox sorğu göndərsə nə olar?
Bu sorğuları yönləndirmək üçün açıq TCP bağlantısından istifadə ediləcək, bütün sorğular ilk sorğunun getdiyi eyni backend-ə gedəcək.
İptables trafiki yenidən bölüşdürməli deyilmi?
Bu halda yox.
TCP bağlantısı yaradıldıqda, o, trafikin gedəcəyi xüsusi bir backend seçən iptables qaydalarından keçir.
Bütün sonrakı sorğular artıq açıq TCP bağlantısında olduğundan, iptables qaydaları artıq çağırılmır.
Gəlin görək necə görünür.
Birinci pod xidmətə sorğu göndərir:
Bundan sonra nə olacağını artıq bilirsiniz. Xidmət mövcud deyil, lakin sorğunu emal edəcək iptables qaydaları var:
Təyinat ünvanı kimi arxa panellərdən biri seçiləcək:
Sorğu qovluğa çatır. Bu nöqtədə, iki pods arasında davamlı TCP bağlantısı qurulacaq:
Birinci poddan istənilən sonrakı sorğu artıq qurulmuş əlaqədən keçəcək:
Nəticə daha sürətli cavab müddəti və daha yüksək ötürmə qabiliyyətidir, lakin siz arxa planı miqyaslaşdırmaq qabiliyyətini itirirsiniz.
Daimi əlaqə ilə arxa tərəfdə iki pods olsa belə, trafik həmişə onlardan birinə gedəcək.
Bu düzəldilə bilərmi?
Kubernetes davamlı əlaqələri necə tarazlaşdıracağını bilmədiyi üçün bu vəzifə sizin üzərinizə düşür.
Xidmətlər son nöqtələr adlanan IP ünvanları və portların toplusudur.
Tətbiqiniz xidmətdən son nöqtələrin siyahısını əldə edə və sorğuların onlar arasında necə bölüşdürülməsinə qərar verə bilər. Siz hər bir pod üçün davamlı əlaqə aça və round-robin istifadə edərək bu bağlantılar arasında sorğuları balanslaşdıra bilərsiniz.
Balanslaşdırmaya cavabdeh olan müştəri tərəfi kodu bu məntiqə əməl etməlidir:
Xidmətdən son nöqtələrin siyahısını əldə edin.
Hər son nöqtə üçün davamlı əlaqə açın.
Sorğu etmək lazım olduqda, açıq bağlantılardan birini istifadə edin.
Son nöqtələrin siyahısını müntəzəm olaraq yeniləyin, yenilərini yaradın və ya siyahı dəyişərsə, köhnə davamlı əlaqələri bağlayın.
Bu belə görünəcək.
Xidmətə sorğu göndərən ilk pod əvəzinə siz müştəri tərəfindəki sorğuları balanslaşdıra bilərsiniz:
Hansı podların xidmətin bir hissəsi olduğunu soruşan kod yazmalısınız:
Siyahı əldə etdikdən sonra onu müştəri tərəfində saxlayın və podlara qoşulmaq üçün ondan istifadə edin:
Siz yük balanslaşdırma alqoritminə cavabdehsiniz:
İndi sual yaranır: bu problem yalnız HTTP-nin canlı saxlanmasına aiddir?
Müştəri tərəfində yük balansı
HTTP davamlı TCP bağlantılarından istifadə edə bilən yeganə protokol deyil.
Tətbiqiniz verilənlər bazasından istifadə edirsə, onda hər dəfə sorğu vermək və ya verilənlər bazasından sənəd götürmək lazım olanda TCP bağlantısı açılmır.
Bunun əvəzinə verilənlər bazasına davamlı TCP bağlantısı açılır və istifadə olunur.
Əgər verilənlər bazanız Kubernetes-də yerləşdirilibsə və giriş xidmət kimi təmin edilibsə, əvvəlki bölmədə təsvir olunan eyni problemlərlə qarşılaşacaqsınız.
Bir verilənlər bazası replikası digərlərindən daha çox yüklənəcək. Kube-proxy və Kubernetes əlaqələri balanslaşdırmağa kömək etməyəcək. Sorğuları verilənlər bazanızla balanslaşdırmağa diqqət yetirməlisiniz.
Verilənlər bazasına qoşulmaq üçün hansı kitabxanadan istifadə etdiyinizdən asılı olaraq, bu problemi həll etmək üçün müxtəlif seçimləriniz ola bilər.
Aşağıda Node.js-dən MySQL verilənlər bazası klasterinə daxil olmaq nümunəsi verilmişdir:
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
Davamlı TCP bağlantılarından istifadə edən bir çox başqa protokollar var:
WebSockets və təhlükəsiz WebSockets
HTTP / 2
gRPC
RSockets
AMQP
Bu protokolların əksəriyyəti ilə artıq tanış olmalısınız.
Bəs bu protokollar bu qədər populyardırsa, niyə standartlaşdırılmış balanslaşdırma həlli yoxdur? Müştərinin məntiqi niyə dəyişməlidir? Doğma Kubernetes həlli varmı?
Kube-proxy və iptables Kubernetes-ə yerləşdirərkən ən ümumi istifadə hallarını əhatə etmək üçün nəzərdə tutulmuşdur. Bu rahatlıq üçündür.
REST API-ni ifşa edən veb xidmətindən istifadə edirsinizsə, şanslısınız - bu halda davamlı TCP bağlantıları istifadə edilmir, istənilən Kubernetes xidmətindən istifadə edə bilərsiniz.
Ancaq davamlı TCP bağlantılarından istifadə etməyə başladıqdan sonra, yükü arxa tərəflər arasında bərabər şəkildə necə bölüşdürəcəyinizi anlamalı olacaqsınız. Kubernetes-də bu iş üçün hazır həllər yoxdur.
Bununla belə, əlbəttə ki, kömək edə biləcək variantlar var.
İlk üç xidmət kube-proxy tərəfindən iptables qaydalarını qurmaq üçün istifadə edilən virtual IP ünvanı əsasında fəaliyyət göstərir. Lakin bütün xidmətlərin təməl əsası başsız xidmətdir.
Başsız xidmətin onunla əlaqəli heç bir IP ünvanı yoxdur və yalnız onunla əlaqəli podların (son nöqtələrin) IP ünvanlarının və portlarının siyahısını əldə etmək üçün bir mexanizm təqdim edir.
Bütün xidmətlər başsız xidmətə əsaslanır.
ClusterIP xidməti bəzi əlavələri olan başsız xidmətdir:
İdarəetmə təbəqəsi ona bir IP ünvanı təyin edir.
Kube-proxy lazımi iptables qaydalarını yaradır.
Bu yolla siz kube-proxy-yə məhəl qoymayaraq, tətbiqinizi balanslaşdırmaq üçün başsız xidmətdən əldə edilən son nöqtələrin siyahısını birbaşa istifadə edə bilərsiniz.
Bəs biz klasterdə yerləşdirilmiş bütün tətbiqlərə oxşar məntiqi necə əlavə edə bilərik?
Tətbiqiniz artıq yerləşdirilibsə, bu tapşırıq qeyri-mümkün görünə bilər. Bununla belə, alternativ variant var.
Service Mesh sizə kömək edəcək
Yəqin ki, artıq müştəri tərəfində yük balanslaşdırma strategiyasının olduqca standart olduğunu fərq etmisiniz.
Tətbiq başlayanda o:
Xidmətdən IP ünvanlarının siyahısını alır.
Bağlantı hovuzunu açır və saxlayır.
Son nöqtələri əlavə etmək və ya silməklə hovuzu vaxtaşırı yeniləyir.
Tətbiq sorğu vermək istədikdə:
Bəzi məntiqdən istifadə edərək mövcud əlaqəni seçir (məsələn, round-robin).
Müraciəti yerinə yetirir.
Bu addımlar həm WebSockets, həm gRPC, həm də AMQP bağlantıları üçün işləyir.
Siz bu məntiqi ayrı bir kitabxanaya ayırıb tətbiqlərinizdə istifadə edə bilərsiniz.
Bununla birlikdə, bunun əvəzinə Istio və ya Linkerd kimi xidmət şəbəkələrindən istifadə edə bilərsiniz.
Service Mesh tətbiqinizi aşağıdakı proseslə genişləndirir:
Avtomatik olaraq xidmət IP ünvanlarını axtarır.
WebSockets və gRPC kimi əlaqələri sınaqdan keçirir.
Sorğuları düzgün protokoldan istifadə edərək balanslaşdırır.
Service Mesh klaster daxilində trafiki idarə etməyə kömək edir, lakin o, kifayət qədər resurs tələb edir. Digər seçimlər Netflix Ribbon kimi üçüncü tərəf kitabxanalarından və ya Envoy kimi proqramlaşdırıla bilən proksilərdən istifadə etməkdir.
Balans məsələlərinə məhəl qoymasanız nə olar?
Siz yük balansından istifadə etməməyi seçə bilərsiniz və hələ də heç bir dəyişiklik hiss etməməlisiniz. Bir neçə iş ssenarisinə baxaq.
Əgər serverlərdən daha çox müştəriniz varsa, bu o qədər də böyük problem deyil.
Tutaq ki, iki serverə qoşulan beş müştəri var. Balanslaşdırma olmasa belə, hər iki server istifadə olunacaq:
Əlaqələr bərabər paylanmaya bilər: bəlkə də dörd müştəri eyni serverə qoşulur, lakin hər iki serverin istifadə olunması şansı yüksəkdir.
Daha problemli olan isə əks ssenaridir.
Əgər daha az müştəriniz və daha çox serveriniz varsa, resurslarınız kifayət qədər istifadə oluna bilər və potensial darboğaz yarana bilər.
Tutaq ki, iki müştəri və beş server var. Ən yaxşı halda, beşdən iki serverə iki daimi əlaqə olacaq.
Qalan serverlər boş olacaq:
Bu iki server müştəri sorğularını idarə edə bilmirsə, üfüqi miqyaslama kömək etməyəcək.
Nəticə
Kubernetes xidmətləri əksər standart veb tətbiqi ssenarilərində işləmək üçün nəzərdə tutulub.
Bununla belə, verilənlər bazası, gRPC və ya WebSockets kimi davamlı TCP bağlantılarından istifadə edən proqram protokolları ilə işləməyə başladıqdan sonra xidmətlər artıq uyğun deyil. Kubernetes davamlı TCP əlaqələrini balanslaşdırmaq üçün daxili mexanizmləri təmin etmir.
Bu o deməkdir ki, siz proqramları müştəri tərəfində balanslaşdırmanı nəzərə alaraq yazmalısınız.