Hamıya salam! Mənim adım Oleq Sidorenkov, mən DomClick-də infrastruktur komandasının rəhbəri kimi işləyirəm. Biz üç ildən artıqdır ki, Cube-dan satış üçün istifadə edirik və bu müddət ərzində onunla çox müxtəlif maraqlı anlar yaşadıq. Bu gün sizə düzgün yanaşma ilə klasteriniz üçün vanil Kubernetesdən daha çox performansı necə sıxa biləcəyinizi söyləyəcəyəm. Davamlı getməyə hazır olun!
Siz hamınız yaxşı bilirsiniz ki, Kubernetes konteyner orkestrasiyası üçün genişləndirilə bilən açıq mənbə sistemidir; yaxşı, və ya bir server mühitində mikroservislərinizin həyat dövrünü idarə edərək sehr edən 5 binar. Bundan əlavə, bu, müxtəlif tapşırıqlar üçün maksimum fərdiləşdirmə üçün Lego konstruktoru kimi yığıla bilən kifayət qədər çevik bir vasitədir.
Və hər şey yaxşı görünür: odun qutusuna odun kimi klasterə atın və kədərlənməyin. Ancaq ətraf mühitin tərəfdarısınızsa, o zaman fikirləşəcəksiniz: “Mən necə sobada od saxlayım və meşəyə peşman ola bilərəm?”. Başqa sözlə, infrastrukturun yaxşılaşdırılması və xərclərin azaldılması yollarını necə tapmaq olar.
1. Komanda və proqram resurslarını izləyin
Ən bayağı, lakin təsirli üsullardan biri tələblərin/limitlərin tətbiqidir. Tətbiqləri ad boşluqları və ad boşluqlarını inkişaf qrupları ilə ayırın. Prosessor vaxtı, yaddaş, efemer yaddaş istehlakı üçün dəyərlər yerləşdirməzdən əvvəl tətbiqi təyin edin.
Təcrübə ilə belə bir nəticəyə gəldik: məhdudiyyətlərdən gələn sorğuları iki dəfədən çox şişirtməyə dəyməz. Klaster ölçüsü sorğular əsasında hesablanır və tətbiqi resursların fərqinə, məsələn, 5-10 dəfə təyin etsəniz, o zaman qovşaqlarınızla doldurulduqda və birdən bir yük aldıqda onunla nə olacağını təsəvvür edin. Yaxşı heç nə yoxdur. Ən azı, tənzimləmə və maksimum olaraq, işçi ilə vidalaşın və podlar hərəkət etməyə başladıqdan sonra qalan qovşaqlarda tsiklik yük alın.
Bundan əlavə, köməyi ilə limitranges başlanğıcda konteyner üçün resurs dəyərlərini təyin edə bilərsiniz - minimum, maksimum və standart:
➜ ~ kubectl describe limitranges --namespace ops
Name: limit-range
Namespace: ops
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu 50m 10 100m 100m 2
Container ephemeral-storage 12Mi 8Gi 128Mi 4Gi -
Container memory 64Mi 40Gi 128Mi 128Mi 2
Bir komanda klasterin bütün resurslarını götürə bilməməsi üçün ad sahəsi resurslarını məhdudlaşdırmağı unutmayın:
Təsvirdən göründüyü kimi resourcequotas, əgər ops əmri daha 10 cpu istehlak edəcək podları yerləşdirmək istəsə, planlaşdırıcı bunu etməyə icazə verməyəcək və xəta verəcək:
Bənzər bir problemi həll etmək üçün bir alət yaza bilərsiniz, məsələn, kimi bu, komanda resurslarının vəziyyətini saxlaya və qəbul edə bilər.
2. Ən yaxşı fayl saxlama yerini seçin
Burada davamlı həcmlər və Kubernetes işçi qovşaqlarının disk alt sistemi mövzusuna toxunmaq istərdim. Ümid edirəm ki, istehsalda heç kim HDD-də "Cube" istifadə etmir, lakin bəzən hətta adi bir SSD artıq kifayət etmir. Belə bir problemlə qarşılaşdıq ki, loglar giriş/çıxış əməliyyatları ilə diski öldürürdü və burada həll yolları çox deyil:
Yüksək performanslı SSD-lərdən istifadə edin və ya NVMe-yə keçin (əgər siz öz aparatınızı idarə edirsinizsə).
Yuxarıdakı ekran görüntüsü, access_logs girişi aktiv olduqda (~12k log/san) disklə nginx-ingress-controller altında baş verənləri göstərir. Belə bir vəziyyət, əlbəttə ki, bu qovşaqdakı bütün tətbiqlərin deqradasiyasına səbəb ola bilər.
PV-yə gəlincə, təəssüf ki, mən hər şeyi sınamamışam. növlər Davamlı həcmlər. Sizə uyğun olan ən yaxşı variantdan istifadə edin. Ölkəmizdə tarixən baş verib ki, xidmətlərin kiçik bir hissəsi RWX həcmlərinə ehtiyac duyur və çoxdan bu iş üçün NFS yaddaşından istifadə etməyə başladılar. Ucuz və ... kifayət qədər. Əlbəttə, biz onunla bok yedik - sağlam ol, amma onu necə kökləməyi öyrəndik və başı artıq ağrımır. Mümkünsə, S3 obyekt yaddaşına keçin.
3. Optimallaşdırılmış Şəkillər Yaradın
Kubernetes onları daha sürətli əldə edə və daha səmərəli icra edə bilməsi üçün konteyner üçün optimallaşdırılmış şəkillərdən istifadə etmək yaxşıdır.
Optimallaşdırma o deməkdir ki, şəkillər:
yalnız bir proqram ehtiva edir və ya yalnız bir funksiyanı yerinə yetirir;
kiçik ölçülü, çünki böyük şəkillər şəbəkə üzərindən daha pis ötürülür;
Kubernetesin dayanma vaxtı vəziyyətində tədbir görmək üçün istifadə edə biləcəyi sağlamlıq və hazırlıq son nöqtələrinə sahib olun;
konfiqurasiya xətalarına daha davamlı olan konteyner dostu əməliyyat sistemlərindən (məsələn, Alpine və ya CoreOS) istifadə edin;
çoxmərhələli quruluşlardan istifadə edin ki, siz müşayiət olunan mənbələri deyil, yalnız tərtib edilmiş proqramları yerləşdirə biləsiniz.
Şəkilləri tez bir zamanda yoxlamağa və optimallaşdırmağa imkan verən bir çox alət və xidmətlər var. Onları həmişə yeni və təhlükəsiz saxlamaq vacibdir. Nəticədə əldə edirsiniz:
Bütün klasterdə şəbəkə yükünün azaldılması.
Konteynerin işə salınma vaxtı azaldı.
Bütün Docker reyestrinizin daha kiçik ölçüsü.
4. DNS keşindən istifadə edin
Yüksək yüklərdən danışırıqsa, klasterin DNS sistemini tənzimləmədən həyat olduqca pisdir. Bir vaxtlar Kubernetes tərtibatçıları kube-dns həllini dəstəkləyirdilər. O, ölkəmizdə də tətbiq olundu, lakin bu proqram təminatı xüsusilə uyğunlaşmadı və tələb olunan performansı vermədi, baxmayaraq ki, vəzifə sadədir. Sonra keçdiyimiz və kədərini bilmədiyimiz korednlər meydana çıxdı, sonradan K8-lərdə standart DNS xidməti oldu. Bir anda DNS sisteminə 40 min rps-ə qədər böyüdük və bu həll də kifayət etmədi. Ancaq şanslı bir şansla Nodelocaldns çıxdı, aka node local cache, aka NodeLocal DNSCache.
Niyə istifadə edirik? Linux nüvəsində bir səhv var ki, UDP üzərindən conntrack NAT vasitəsilə çoxsaylı girişlər konntrack cədvəllərinə yazmaq üçün yarış vəziyyətinə gətirib çıxarır və NAT vasitəsilə trafikin bir hissəsi itirilir (Xidmət vasitəsilə hər səfər NAT-dır). Nodelocaldns bu problemi NAT-dan qurtularaq və yuxarı axın DNS-ə TCP bağlantısını təkmilləşdirməklə, həmçinin yuxarı axın DNS sorğularını yerli olaraq keşləməklə həll edir (qısa 5 saniyəlik mənfi keş də daxil olmaqla).
5. Podları üfüqi və şaquli olaraq avtomatik ölçün
Əminliklə deyə bilərsiniz ki, bütün mikroservisləriniz yükün iki-üç dəfə artmasına hazırdır? Tətbiqlərinizə resursları necə düzgün bölüşdürmək olar? Bir neçə podun iş yükündən artıq işləməsini saxlamaq lazımsız ola bilər və onların arxa-arxaya saxlanması xidmətə gedən trafikin qəfil artması ilə əlaqədar iş vaxtı riskini artırır. Qızıl orta kimi xidmətlər vurma sehrinə nail olmağa kömək edir Horizontal Pod Autoscaler и Şaquli Pod Autoscaler.
VPA faktiki istifadəyə əsaslanaraq podda konteynerlərinizin tələblərini/limitlərini avtomatik olaraq artırmağa imkan verir. Necə faydalı ola bilər? Əgər nədənsə üfüqi olaraq genişləndirilə bilməyən Podlarınız varsa (bu, tamamilə etibarlı deyil), onda onun resurslarını dəyişdirmək üçün VPA-ya etibar etməyə cəhd edə bilərsiniz. Onun xüsusiyyəti metrik serverdən gələn tarixi və cari məlumatlara əsaslanan tövsiyə sistemidir, ona görə də sorğuları/məhdudiyyətləri avtomatik olaraq dəyişmək istəmirsinizsə, sadəcə konteynerləriniz üçün tövsiyə olunan resurslara nəzarət edə və CPU və yaddaşa qənaət etmək üçün parametrləri optimallaşdıra bilərsiniz. klasterdə.
Kubernetesdəki planlaşdırıcı həmişə sorğulara əsaslanır. Oraya hansı dəyəri qoysanız, planlaşdırıcı ona əsaslanaraq uyğun bir node axtaracaq. Limit dəyəri kublet tərəfindən podun nə vaxt boğulacağını və ya öldürüləcəyini bilmək üçün lazımdır. Yeganə vacib parametr sorğuların dəyəri olduğundan, VPA onunla işləyəcək. Tətbiqinizi şaquli olaraq miqyaslandırdığınız zaman, hansı sorğuların olması lazım olduğunu müəyyənləşdirirsiniz. Bəs o zaman limitlərlə nə baş verəcək? Bu parametr də mütənasib şəkildə ölçüləcək.
Yuxarıda qeyd edildiyi kimi, bu, manifestdəki sorğular/limitlər nisbətinə əsaslanan mütənasib miqyasdır:
CPU: 200m → 300m: nisbət 1:1.75;
Yaddaş: 250Mi → 500Mi: 1:2 nisbəti.
Gəlincə HPA, onda iş mexanizmi daha şəffaf olur. Prosessor və yaddaş kimi ölçülər üçün həddlər təyin edilir və bütün replikaların orta qiyməti həddi aşırsa, dəyər həddən aşağı düşənə qədər və ya replikaların maksimum sayına çatana qədər proqram +1 pod ilə miqyaslanır.
CPU və Yaddaş kimi adi ölçülərə əlavə olaraq, siz xüsusi Prometheus metriklərinizdə hədlər təyin edə və onlarla işləyə bilərsiniz, əgər bunun tətbiqinizi nə vaxt miqyaslandıracağını müəyyənləşdirməyin ən doğru yolu olduğunu düşünürsünüzsə. Tətbiq müəyyən edilmiş metrik hədddən aşağı sabitləşdikdən sonra HPA, Podları minimum replika sayına qədər və ya yük həddi qarşılayana qədər kiçildməyə başlayacaq.
6. Node Affinity və Pod Affinity Haqqında Unutmayın
Bütün qovşaqlar eyni aparatda işləmir və bütün podların hesablama tələb edən proqramları işə salması lazım deyil. Kubernetes istifadə edərək qovşaqların və podların ixtisasını təyin etməyə imkan verir Düyün yaxınlığı и Pod Yaxınlığı.
Hesablama intensivliyi olan əməliyyatlar üçün uyğun qovşaqlarınız varsa, maksimum səmərəlilik üçün tətbiqləri müvafiq qovşaqlara bağlamaq daha yaxşıdır. Bunu etmək üçün istifadə edin nodeSelector node etiketi ilə.
Tutaq ki, sizin iki qovşaqınız var: biri ilə CPUType=HIGHFREQ və çoxlu sayda sürətli nüvələr, digəri ilə MemoryType=HIGHMEMORY daha çox yaddaş və daha sürətli performans. Ən asan yol bir qovşaq yerləşdirməsini təyin etməkdir HIGHFREQbölməsinə əlavə etməklə spec belə bir seçici:
…
nodeSelector:
CPUType: HIGHFREQ
Bunu etmək üçün daha bahalı və xüsusi bir yol istifadə etməkdir nodeAffinity sahədə affinity bölmə spec. İki seçim var:
requiredDuringSchedulingIgnoredDuringExecution: sərt parametr (planlayıcı yalnız xüsusi qovşaqlarda podları yerləşdirəcək (və başqa heç bir yerdə));
preferredDuringSchedulingIgnoredDuringExecution: yumşaq parametr (planlayıcı xüsusi qovşaqlara yerləşdirməyə çalışacaq və uğursuz olarsa, növbəti mövcud qovşaqda yerləşdirməyə çalışacaq).
Siz node etiketlərini idarə etmək üçün xüsusi sintaksisi təyin edə bilərsiniz, məsələn, In, NotIn, Exists, DoesNotExist, Gt və ya Lt. Bununla belə, yadda saxlayın ki, etiketlərin uzun siyahılarındakı mürəkkəb üsullar kritik vəziyyətlərdə qərar qəbul etməyi ləngidir. Başqa sözlə, həddindən artıq mürəkkəbləşdirməyin.
Yuxarıda qeyd edildiyi kimi, Kubernetes sizə cari podların bağlanmasını təyin etməyə imkan verir. Yəni, müəyyən podların eyni əlçatanlıq zonasında (buludlar üçün uyğun) və ya qovşaqlarda digər podlarla birlikdə işləməsini təmin edə bilərsiniz.
В podAffinity margins affinity bölmə spec vəziyyətində olduğu kimi eyni sahələr mövcuddur nodeAffinity: requiredDuringSchedulingIgnoredDuringExecutionи preferredDuringSchedulingIgnoredDuringExecution. Yeganə fərq ondadır matchExpressions podları artıq həmin etiketlə pod işlədən node ilə bağlayacaq.
Daha çox Kubernetes bir sahə təklif edir podAntiAffinity, bu, əksinə, bir podu xüsusi podlarla bir düyünlə bağlamır.
İfadələr haqqında nodeAffinity eyni məsləhət verilə bilər: qaydaları sadə və məntiqli saxlamağa çalışın, pod spesifikasiyasını mürəkkəb qaydalar dəsti ilə həddən artıq yükləməyə çalışmayın. Klasterin şərtlərinə uyğun gəlməyən, planlaşdırıcıya əlavə yük verən və ümumi performansı aşağılayan bir qayda yaratmaq çox asandır.
7. Ləkələr və Tolerantlıqlar
Planlayıcını idarə etməyin başqa bir yolu var. Əgər yüzlərlə qovşaq və minlərlə mikroxidmətdən ibarət böyük klasteriniz varsa, müəyyən qovşaqların müəyyən qovşaqlar tərəfindən yerləşdirilməsinin qarşısını almaq çox çətindir.
Ləkə mexanizmi - qadağan qaydaları - buna kömək edir. Məsələn, müəyyən ssenarilərdə müəyyən qovşaqların podların işləməsinin qarşısını ala bilərsiniz. Müəyyən bir node üçün ləkə tətbiq etmək üçün seçimdən istifadə edin taint kubectl-də. Açar və dəyəri göstərin və sonra kimi ləkələyin NoSchedule və ya NoExecute:
Ləkə mexanizminin üç əsas təsiri dəstəklədiyini də qeyd etmək lazımdır: NoSchedule, NoExecute и PreferNoSchedule.
NoSchedulepod spesifikasiyasında müvafiq giriş olana qədər o deməkdir ki tolerations, o, qovşaqda yerləşdirilə bilməz (bu nümunədə node10).
PreferNoSchedule - sadələşdirilmiş versiya NoSchedule. Bu halda, planlaşdırıcı uyğun girişi olmayan podları ayırmamağa çalışacaq. tolerations node başına, lakin bu çətin hədd deyil. Klasterdə heç bir resurs yoxdursa, podlar bu node üzərində yerləşdirilməyə başlayacaq.
NoExecute- bu təsir uyğun girişi olmayan podların dərhal boşaldılmasına səbəb olur tolerations.
Maraqlıdır ki, bu davranış dözümlülük mexanizmi ilə ləğv edilə bilər. Bu, "qadağan olunmuş" bir qovşaq olduqda rahatdır və ona yalnız infrastruktur xidmətləri yerləşdirmək lazımdır. Bunu necə etmək olar? Yalnız uyğun tolerantlıq olan podlara icazə verin.
Bu o demək deyil ki, növbəti təkrar yerləşdirmə zamanı pod məhz bu qovşağı vuracaq, bu Node Affinity mexanizmi deyil və nodeSelector. Ancaq bir neçə xüsusiyyəti birləşdirərək, çox çevik planlaşdırıcı quraşdırmasına nail ola bilərsiniz.
8. Pod Yerləşdirmə Prioritetini təyin edin
Yalnız pod-to-node bağlamalarını konfiqurasiya etdiyinizə görə, bütün podlar eyni prioritetlə işlənməlidir. Məsələn, bəzi Podları digərlərindən əvvəl yerləşdirmək istəyə bilərsiniz.
Kubernetes Pod Priority və Preemption təyin etmək üçün müxtəlif yollar təklif edir. Parametr bir neçə hissədən ibarətdir: obyekt PriorityClassvə sahə təsvirləri priorityClassNamepod spesifikasiyasında. Məsələni nəzərdən keçirək:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 99999
globalDefault: false
description: "This priority class should be used for very important pods only"
Biz yaradırıq PriorityClass, ona ad, təsvir və dəyər verin.Daha yüksək value, prioritet nə qədər yüksəkdir. Dəyər 32-dan kiçik və ya ona bərabər olan hər hansı 1 bitlik tam ədəd ola bilər. Daha yüksək qiymətlər kritik kritik sistem podları üçün qorunur, adətən onları qabaqcadan seçmək mümkün deyil.Çıxarma yalnız yüksək prioritet podun dönmək üçün yeri olmadığı halda baş verəcək, o zaman müəyyən bir qovşaqdan bəzi podlar evakuasiya ediləcək. Bu mexanizm sizin üçün çox sərtdirsə, o zaman seçimi əlavə edə bilərsiniz preemptionPolicy: Never, və sonra heç bir üstünlük olmayacaq, pod növbədə birinci olacaq və planlaşdırıcının bunun üçün pulsuz resurslar tapmasını gözləyin.
Sonra, adı təyin etdiyimiz bir pod yaradırıq priorityClassName:
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
priorityClassName: high-priority
İstədiyiniz qədər prioritet siniflər yarada bilərsiniz, baxmayaraq ki, bununla məşğul olmamaq tövsiyə olunur (məsələn, özünüzü aşağı, orta və yüksək prioritetlərlə məhdudlaşdırın).
Beləliklə, lazım gələrsə, nginx-ingress-controller, coredns və s. kimi kritik xidmətlərin tətbiqinin səmərəliliyini artıra bilərsiniz.
9. ETCD klasterinizi optimallaşdırın
ETCD-ni bütün klasterin beyni adlandırmaq olar. Bu verilənlər bazasının işini yüksək səviyyədə saxlamaq çox vacibdir, çünki "Kub" da əməliyyatların sürəti ondan asılıdır. Kifayət qədər standart və eyni zamanda yaxşı bir həll kube-apiserver üçün minimum gecikmə üçün master qovşaqlarda ETCD klasterini saxlamaq olardı. Bu mümkün deyilsə, ETCD-ni iştirakçılar arasında yaxşı bant genişliyi ilə mümkün qədər yaxın yerləşdirin. ETCD-dən neçə qovşağın çoxluğa zərər vermədən düşə biləcəyinə də diqqət yetirin.
Nəzərə alın ki, klasterdə iştirakçıların sayında həddindən artıq artım performans hesabına qüsurlara dözümlülüyünü artıra bilər, hər şey insafda olmalıdır.
Xidmətin qurulması haqqında danışırıqsa, bir neçə tövsiyə var:
Klasterin ölçüsünə əsaslanaraq yaxşı aparatlara sahib olun (oxuya bilərsiniz burada).
Bir cüt DC və ya şəbəkəniz arasında klaster yaymısınızsa və disklər arzuolunan çox şey buraxırsa, bir neçə parametri dəyişdirin (oxuya bilərsiniz). burada).
Nəticə
Bu məqalə komandamızın riayət etməyə çalışdığı məqamları təsvir edir. Bu, addım-addım hərəkətlərin təsviri deyil, klasterin yükünü optimallaşdırmaq üçün faydalı ola biləcək seçimlərdir. Aydındır ki, hər bir klaster özünəməxsus şəkildə unikaldır və tənzimləmə həlləri çox fərqli ola bilər, ona görə də sizdən rəy almaq maraqlı olardı: Kubernetes klasterinizi necə izləyirsiniz, onun işini necə yaxşılaşdırırsınız. Təcrübənizi şərhlərdə paylaşın, bunu bilmək maraqlı olacaq.