Tinderning Kubernetesga ko'chishi

Muallif: Kris O'Brien, muhandislik menejeri | Kris Tomas, muhandislik menejeri | Jinyong Li, dasturiy ta'minot bo'yicha katta muhandis | Muallif: Cooper Jekson, dastur muhandisi

Nima uchun?

Deyarli ikki yil oldin, Tinder o'z platformasini Kubernetesga ko'chirishga qaror qildi. Kubernetes bizga Tinder muhandisligini konteynerizatsiya va past tegib turadigan ishlanmaga, o'zgarmas joylashtirish orqali olib borish imkoniyatini berdi. Ilovalarni qurish, joylashtirish va infratuzilma kod sifatida belgilanadi.

Biz, shuningdek, miqyos va barqarorlik muammolarini hal qilishga intildik. Masshtablash juda muhim bo'lganida, biz tez-tez EC2 ning yangi namunalari Internetga kirishini kutib turardik. Bir necha daqiqadan farqli o'laroq, bir necha soniya ichida konteynerlarni rejalashtirish va xizmat ko'rsatish g'oyasi bizni qiziqtirdi.

Bu oson emas edi. Migratsiya paytida, 2019 yil boshida, biz Kubernetes klasterimizdagi muhim massaga etib keldik va trafik hajmi, klaster hajmi va DNS tufayli turli xil qiyinchiliklarga duch kelishni boshladik. Biz 200 ta xizmatni ko'chirish va Kubernetes klasterini 1000 ta tugun, 15000 ta pod va 48,000 konteynerni boshqarish bo'yicha qiziqarli vazifalarni hal qildik.

Qanday

2018 yil yanvar oyidan boshlab, biz migratsiya harakatlarining turli bosqichlarini bosib o'tdik. Biz barcha xizmatlarimizni tarqatish va Kubernetes mezbonlik qiladigan atrof-muhitga joylashtirishdan boshladik. Oktyabr oyidan boshlab, biz barcha meros xizmatimizni Kubernetesga ko'chirishni boshladik. Keyingi yilning mart oyida biz ko'chib o'tishni tugatdik va endi Tinder platformasi faqat Kubernetesda ishlaydi.

Kubernetes uchun rasmlarni qurish

Kubernetes klasterida ishlaydigan mikroservislar uchun 30 dan ortiq manbali kod omborlari mavjud. Ushbu omborxonalardagi kod turli tillarda yozilgan (masalan, Node.js, Java, Scala, Go) bir xil til uchun bir nechta ish vaqti muhiti bilan.

Tizim tizimi odatda Dockerfile va bir qator qobiq buyruqlaridan iborat bo'lgan har bir mikroservis uchun to'liq sozlanadigan "tuzilish kontekstida" ishlashga mo'ljallangan. Ularning mazmuni to'liq sozlanishi bilan birga, ushbu tuzilish kontekstlari ham standartlashtirilgan formatga muvofiq yoziladi. Tuzilgan kontekstlarni standartlashtirish bitta tizim tizimiga barcha mikroservislarni boshqarish imkoniyatini beradi.

Rasm 1-1. Builder idishi orqali standartlashtirilgan qurilish jarayoni

Ish vaqti bilan ishlaydigan muhit o'rtasidagi maksimal muvofiqlikka erishish uchun ishlab chiqish va sinov bosqichida xuddi shunday qurish jarayoni qo'llaniladi. Biz platformada barqaror muhitni yaratish uchun kafolatli yo'lni ishlab chiqishga majbur bo'lganda, bu noyob qiyinchilikni yuzaga keltirdi. Natijada barcha qurilish jarayonlari maxsus "Quruvchi" konteynerida bajariladi.

Builder konteynerini amalga oshirish bir qator ilg'or Docker texnikasini talab qildi. Ushbu Builder idishi Tinder xususiy omborxonalariga kirish uchun talab qilinganidek, mahalliy foydalanuvchi identifikatori va sirlarini (masalan, SSH kaliti, AWS hisobga olish ma'lumotlari va boshqalar) meros qilib oladi. U qurilish artefaktlarini saqlashning tabiiy usuliga ega bo'lish uchun dastlabki kodni o'z ichiga olgan mahalliy kataloglarni o'rnatadi. Ushbu yondashuv ishlashni yaxshilaydi, chunki u Builder konteyneri va mezbon mashinasi o'rtasida o'rnatilgan artefaktlarni nusxalashni yo'q qiladi. Saqlangan qurilish asarlar keyingi safar konfiguratsiyasiz qayta ishlatiladi.

Muayyan xizmatlar uchun biz kompilyator vaqtidagi muhitni ish vaqti bilan moslashtirish uchun Builder-da boshqa konteyner yaratishga majbur bo'ldik (masalan, Node.js bcrypt kutubxonasini o'rnatish platformaga tegishli ikkilik asarlar yaratadi). Kompilyatsiya vaqtiga qo'yiladigan talablar xizmatlar o'rtasida farq qilishi mumkin va yakuniy Dockerfile uchib boriladi.

Kubernetes klaster arxitekturasi va migratsiyasi

Klaster o'lchami

Biz Amazon EC2 nusxalarida avtomatlashtirilgan klasterni ta'minlash uchun kub-lardan foydalanishga qaror qildik. Erta boshida biz hamma narsani bitta umumiy tugunli hovuzda boshqarardik. Resurslardan unumli foydalanish uchun biz ish hajmini turli o'lchamdagi va har xil turlarga ajratish zarurligini tezda aniqladik. Buning sababi shundaki, unchalik katta bo'lmagan tishli podlarni birgalikda ishlatish biz uchun ko'proq kutilgan natijalarga olib keldi, chunki ular bitta tishli podalarning ko'proq sonini birlashtirishga imkon berishdi.

Biz quyidagicha joylashdik:

  • m5.4 kattalashtirish (Prometey)
  • Node.js ish yuki uchun c5.4x kattalashtirish (bitta oqimli ish yuki)
  • c5.2 Java va Go uchun kattalashtirish (ko'p oqimli ish yuki)
  • Boshqaruv tekisligi uchun kattalashtirish (3 tugun)

Migratsiya

Bizning eski infratuzilmasimizdan Kubernetesga ko'chib o'tish uchun tayyorgarlik bosqichlaridan biri mavjud xizmat-xizmat aloqasini maxsus Virtual Xususiy Bulut (VPC) ichida yaratilgan yangi Elastik Yuk Balanserlariga (ELB) yo'naltirish edi. Ushbu pastki tarmoq Kubernetes VPC-da ko'rib chiqilgan. Bu bizga xizmatlarga bog'liq buyurtmalarni alohida buyurtma qilishdan qat'i nazar modullarni bosqichma-bosqich o'tkazish imkonini berdi.

Ushbu so'nggi nuqtalar har bir yangi ELB-ga ishora qiluvchi CNAME-ga ega bo'lgan vaznli DNS yozuvlar to'plamlari yordamida yaratilgan. Kesish uchun biz yangi Kubernetes xizmatiga ishora qilib, og'irligi 0 ga teng bo'lgan yangi yozuvni qo'shdik. Keyin yozuvda "Yashash vaqti" ni (TTL) 0 ga o'rnatdik. Keyin eski va yangi og'irliklar asta-sekin moslashtirildi. oxir-oqibat 100% yangi serverda ishlaydi. Tugatish tugagandan so'ng, TTL yanada oqilona narsaga o'rnatildi.

Bizning Java modullarimiz past DNS TTLni ulug'ladilar, ammo bizning Node dasturlarimiz bunga erisha olmadilar. Bizning muhandislarimizdan biri har 60-yillarda pullarni yangilaydigan menejerga o'rash uchun ulanish pulining kodining bir qismini qayta yozdi. Bu biz uchun juda yaxshi ishladi.

O‘rganishlar

Tarmoq matolarining cheklovlari

2019 yil 8-yanvar kuni erta tongda Tinder platformasi doimiy ravishda ishdan chiqqan. Ertalab platforma kutish vaqtining o'zaro bog'liq bo'lmagan o'sishiga javoban klasterda pod va tugunlarni hisoblash amalga oshirildi. Natijada barcha tugunlarda ARP keshi tugadi.

ARP keshiga tegishli uchta Linux qiymatlari mavjud:

Kredit

gc_thresh3 - bu qattiq qopqoq. Agar siz "qo'shnilar jadvalining toshib ketishi" jurnaliga yozuvlar kirayotgan bo'lsangiz, bu ARP keshini sinxron axlat yig'ish (GC) dan keyin ham qo'shnilar yozuvini saqlash uchun etarli joy yo'qligini anglatadi. Bunday holda, yadroni paketni butunlay tashlab yuboradi.

Biz Flanelni Kubernetesdagi tarmoq matoimiz sifatida ishlatamiz. Paketlar VXLAN orqali yuboriladi. VXLAN - bu Layer 3 tarmog'idagi 2-qavat sxemasi. Layer 2 tarmoq segmentlarini kengaytirish uchun vosita bilan ta'minlash uchun MAC-manzilga kirish ma'lumotlar bazasi protokoli (MAC-in-UDP) dan foydalanadi. Fizik ma'lumotlar markazi tarmog'i orqali transport protokoli IP plyus UDP hisoblanadi.

Rasm 2-1 Flanel diagrammasi (kredit)

Rasm 2–2 VXLAN paketi (kredit)

Kubernetes-ning har bir ishchi tuguni katta / 9-chi blokdan o'zining / 24 virtual manzil maydonini ajratadi. Har bir tugun uchun bu 1 marshrut jadvaliga, 1 ARP jadvalga kirishga (flanel.1 interfeysida) va 1 ta ma'lumotlar uzatish ma'lumotlar bazasiga (FDB) kirishga olib keladi. Bular ishchi tugunni birinchi ishga tushirganda yoki har bir yangi tugun topilganda qo'shiladi.

Bunga qo'shimcha ravishda, tugundan-pod-ga (yoki pod-pod-dan) aloqa oxir-oqibat eth0 interfeysi orqali oqadi (yuqoridagi Flanel sxemasida tasvirlangan). Natijada, har bir mos keladigan tugun manbai va tugunni tayinlash uchun ARP jadvaliga qo'shimcha yozuv kiritiladi.

Bizning muhitimizda ushbu turdagi aloqa juda keng tarqalgan. Bizning Kubernetes xizmat ob'ektlari uchun ELB yaratiladi va Kubernetes har bir tugunni ELB bilan ro'yxatdan o'tkazadi. ELB hech qanday xabardor emas va tanlangan tugun paketning oxirgi maqsadi bo'lmasligi mumkin. Buning sababi, tugun paketni ELB-dan qabul qilganda, xizmat uchun uning iptable qoidalarini baholaydi va tasodifiy ravishda boshqa tugunni tanlaydi.

Chiqib ketish vaqtida klasterda jami 605 ta tugun mavjud edi. Yuqorida keltirilgan sabablarga ko'ra, bu gc_thresh3 standart qiymatini tanib olish uchun etarli edi. Bu sodir bo'lgandan so'ng, nafaqat paketlar tashlanmoqda, balki ARP jadvalida Flannel / virtual manzillarning barcha bo'sh joylari yo'q. "Pod" aloqasi va "DNS" izlash tugallanmadi. (DNS klaster ichida joylashtirilgan, ushbu maqolada keyinroq batafsilroq tushuntiriladi.)

Buni hal qilish uchun gc_thresh1, gc_thresh2 va gc_thresh3 qiymatlari ko'tariladi va yo'qolgan tarmoqlarni qayta ro'yxatdan o'tkazish uchun Flannel qayta ishga tushirilishi kerak.

Kutilmagan tarzda ishlaydigan DNS ishlayapti

Ko'chib o'tishni ta'minlash uchun biz DNS-dan trafikni shakllantirishni va xizmatimizdan merosdan Kubernetesgacha bo'lgan qadamlarni qisqartirishni osonlashtirdik. Biz bog'liq Route53 RecordSets-ga nisbatan past TTL qiymatlarini o'rnatdik. Eskirgan infratuzilmani EC2 nusxalarida ishga tushirganda, bizning aniq konfiguratsiya Amazon DNS-ga ishora qildi. Biz buni odatiy hol deb bildik va bizning xizmatlarimiz va Amazon xizmatlari (masalan, DynamoDB) uchun nisbatan past TTLning narxi deyarli sezilmay qoldi.

Kubernetesga tobora ko'proq xizmatlarni olib borganimizda, biz soniyada 250 000 so'rovlarga javob beradigan DNS xizmatini ishga tushirdik. Ilovalarimiz oralig'ida intervalgacha va ta'sirchan DNS qidirish vaqti tugadi. Bu juda sozlash harakatiga va DNS provayderining CoreDNS joylashishiga o'tishiga qaramay, bir vaqtning o'zida 120 yadro iste'mol qiladigan 1000 podkastga etdi.

Boshqa mumkin bo'lgan sabablar va echimlarni o'rganayotganda, biz Linux paketlarini filtrlash netfilteriga ta'sir qiladigan poyga holatini tavsiflovchi maqolani topdik. Biz ko'rgan DNS vaqtlari va Flannel interfeysida kiritilgan_fail hisoblagichi maqolaning topilmalariga mos tushdi.

Muammo Manba va Destinasyon Tarmoq manzili tarjimasi (SNAT va DNAT) va keyinchalik ulanish jadvaliga kiritish paytida yuz beradi. Jamiyat tomonidan muhokama qilingan va echimlardan biri DNS-ni ishchi tuguniga o'tkazish edi. Ushbu holatda:

  • SNAT kerak emas, chunki trafik mahalliy tugun ichida qoladi. Uni Eth0 interfeysi orqali uzatish shart emas.
  • DNAT kerak emas, chunki maqsad IP-tugun tugun uchun mahalliy va tasodifiy tanlangan podval uchun qoidalar emas.

Ushbu yondashuv bilan oldinga siljishga qaror qildik. CoreDNS Kubernetesda DaemonSet sifatida joylashtirildi va biz har bir podning ravn.configa tugunning mahalliy DNS serverini kubelet - klaster-dns buyruq bayrog'ini sozlash orqali kiritdik. Muammoni hal qilish DNS vaqtini uzish uchun samarali bo'ldi.

Biroq, biz hali ham tushirilgan paketlarni va Flannel interfeysining insert_failed hisoblagichini ko'rmoqdamiz. Yuqoridagi muammolardan keyin ham saqlanib qoladi, chunki biz DNS trafigi uchun SNAT va / yoki DNAT-dan qochdik. Musobaqa holati boshqa transport turlari uchun ham saqlanib qoladi. Yaxshiyamki, bizning paketlarimizning aksariyati TCP hisoblanadi va agar vaziyat yuzaga kelsa, paketlar muvaffaqiyatli ravishda qayta yuboriladi. Trafikning barcha turlari uchun uzoq muddatli tuzatish bu biz haligacha muhokama qilayotgan narsadir.

Yaxshi yuklarni muvozanatlash uchun elchi yordamida

Biz orqaga qaytadigan xizmatimizni Kubernetesga ko'chirganimizda, podalar bo'ylab muvozanatsiz yuklarni boshdan kechira boshladik. Biz HTTP Keepalive tufayli ELB ulanishlari har bir prokladkaning birinchi tayyor podkastlariga yopishganligini aniqladik, shuning uchun ko'p trafik mavjud podalarning ozgina qismi orqali oqardi. Biz birinchi urinishlarni engillashtirish usullaridan biri bu eng yomon huquqbuzarlar uchun 100% MaxSurge-ni yangi joylashtirishlarda qo'llash edi. Bu ba'zi bir kattaroq joylashtirishlar bilan samarali va barqaror emas uzoq muddatli.

Biz ishlatgan yana bir yumshatish - bu og'ir xizmatlarga nisbatan joylashtirilgan podslar ko'proq xonalarga ega bo'lishi uchun tanqidiy xizmatlarga resurs talablarini sun'iy ravishda to'ldirish edi. Resurs chiqindilari va bizning tugun dasturlarimiz bitta tishli bo'lib, 1 yadroga samarali yopilganligi sababli bu uzoq muddatli istiqbolda ishlamaydi. Yagona aniq echim yuklarni yaxshi muvozanatlashdan foydalanish edi.

Biz ichkarida elchini baholash uchun qidirgan edik. Bu bizga juda cheklangan tarzda joylashtirish va darhol foyda olish imkoniyatini berdi. Envoy - bu katta xizmatga yo'naltirilgan arxitektura uchun mo'ljallangan, yuqori samarali Layer 7 proksi. Avtomatik qayta urinishlar, kontaktlarning zanglashiga olib borish va global stavkalarni cheklashni o'z ichiga olgan yuklarni muvozanatlashning ilg'or uslublarini joriy etishga qodir.

Biz ishlab chiqqan konfiguratsiya bitta kontur va klasterga ega bo'lgan har bir podaning yonida mahalliy konteyner portiga urish uchun Elchi vazifasini bajaradigan yo'lak bo'lishi kerak edi. Potentsial kaskadni minimallashtirish va portlash radiusini ozgina ushlab turish uchun biz har bir xizmat uchun har bir mavjudlik zonasida (AZ) bitta joylashtiruvchi Envoy podkastlaridan foydalandik. Bular bizning muhandislarimizdan birining xizmatni kashf etishning kichik mexanizmiga zarba berdi, shunda ular ushbu xizmat uchun har bir AZ-da pods ro'yxatini qaytarib berdilar.

Oldin xizmat ko'rsatuvchi elchilar ushbu xizmatni kashf etish mexanizmini bitta yuqoriga ko'tariladigan klaster va marshrut yordamida qo'lladilar. Biz oqilona tanaffuslarni sozladik, barcha o'chirish moslamalarini yaxshiladik, so'ngra vaqtinchalik nosozliklar va muammosiz o'rnatishda yordam berish uchun minimal qayta urinishni o'rnatdik. Biz ushbu har bir elchi xizmatini TCP ELB yordamida oldik. Hatto bizning asosiy proksi qatlamimizdan saqlovchi, ba'zi bir Elchilar podkastlariga o'rnatilgan bo'lsa ham, ular yukni eng yaxshi darajada bajara olishadi va minimal_request orqali orqa tomonga muvozanatlasha oladilar.

Joylashtirish uchun biz dasturda ham, yonbosh ustunida ham PreStop kancasidan foydalandik. Bu yonboshdagi sog'liqni tekshirish tekshiruvi deb nomlangan ushbu kanca, kichik uyqu bilan bir qatorda, infraqizil ulanishlarni tugatish va quritishga bir oz vaqt berish uchun.

Bizning tez harakatlanishimizning sabablaridan biri oddiy Prometey sozlamalari bilan osongina birlashtira oladigan boy ko'rsatkichlar tufayli edi. Bu bizga konfiguratsiyani sozlash va trafikni qisqartirishda nima sodir bo'lganligini aniq ko'rishimizga imkon berdi.

Natija darhol va ravshan edi. Biz eng muvozanatsiz xizmatlardan boshladik va hozirda u bizning klasterimizdagi o'n ikkita eng muhim xizmatlar oldida ishlaydi. Bu yil biz yanada kengroq xizmat kashfiyoti, kontaktlarning zanglashiga olib borish, tashqi vositalarni aniqlash, narxlarni cheklash va kuzatish bilan to'liq xizmatga o'tishni rejalashtirmoqdamiz.

3-1-rasm. Xizmatni elchi orqali ajratish paytida bitta xizmatning CPU konvergatsiyasi

Oxir oqibat

Ushbu o'rganishlar va qo'shimcha tadqiqotlar orqali biz katta kubernetes klasterlarini loyihalashtirish, joylashtirish va boshqarish usullarini yaxshi biladigan kuchli ichki infratuzilmani yaratdik. Tinderning butun muhandislik tashkiloti hozirda Kubernetes-da konteynerlarni qanday joylashtirish va ularni qanday joylashtirish bo'yicha bilim va tajribaga ega.

Eski infratuzilmamizda, qo'shimcha miqyos talab etilganda, biz ko'pincha EC2 yangi nusxalarini Internetga kirishini kutish bilan bir necha daqiqalarni boshdan kechirdik. Hozir konteynerlar bir necha daqiqadan farqli o'laroq, soniyalar ichida trafikni rejalashtirmoqdalar va xizmat ko'rsatmoqdalar. Bitta konteynerni bitta EC2 nusxasida rejalashtirish gorizontal zichlikni yaxshilaydi. Natijada, EC2-da 2019 yilda oldingi yilga nisbatan sezilarli darajada tejashni rejalashtirmoqdamiz.

Taxminan ikki yil o'tdi, ammo biz 2019 yil mart oyida ko'chib o'tishni tugatdik. Tinder platformasi faqat 200 ta xizmat, 1000 ta tugun, 15000 ta pod va 48,000 ishlaydigan konteynerlardan iborat Kubernetes klasterida ishlaydi. Infratuzilma endi bizning operatsion guruhlarimiz uchun saqlab qolinadigan vazifa emas. Buning o'rniga, tashkilotning barcha muhandislari ushbu javobgarlikni o'z zimmalariga oladilar va ularning ilovalari qanday qilib kod sifatida tuzilganligi va joylashtirilganligini nazorat qilishadi.