ā€œKubernetes palielināja latentumu 10 reizesā€: kurÅ” pie tā ir vainÄ«gs?

PiezÄ«me. tulk.: Å is raksts, ko uzrakstÄ«jis Galo Navarro, kurÅ” ieņem galvenā programmatÅ«ras inženiera amatu Eiropas uzņēmumā Adevinta, ir aizraujoÅ”a un pamācoÅ”a ā€œizpēteā€ infrastruktÅ«ras darbÄ«bas jomā. Tā oriÄ£inālais nosaukums ir nedaudz paplaÅ”ināts tulkojumā iemesla dēļ, ko autors paskaidro paŔā sākumā.

ā€œKubernetes palielināja latentumu 10 reizesā€: kurÅ” pie tā ir vainÄ«gs?

PiezÄ«me no autora: Izskatās pēc Ŕīs ziņas piesaistÄ«ja daudz vairāk uzmanÄ«bas, nekā gaidÄ«ts. Joprojām saņemu dusmÄ«gus komentārus, ka raksta nosaukums ir maldinoÅ”s un daži lasÄ«tāji ir apbēdināti. Es saprotu notiekoŔā iemeslus, tāpēc, neskatoties uz risku sabojāt visu intrigu, es vēlos jums nekavējoties pastāstÄ«t, par ko ir Å”is raksts. Interesanta lieta, ko esmu redzējis, komandām migrējot uz Kubernetes, ir tas, ka ikreiz, kad rodas problēma (piemēram, palielināts latentums pēc migrācijas), pirmā lieta, kas tiek vainota, ir Kubernetes, bet tad izrādās, ka orÄ·estra vadÄ«tājs nav Ä«sti vainot. Å is raksts stāsta par vienu Ŕādu gadÄ«jumu. Tās nosaukums atkārto viena mÅ«su izstrādātāja izsaukumu (vēlāk jÅ«s redzēsiet, ka Kubernetes ar to nav nekāda sakara). Å eit jÅ«s neatradÄ«sit pārsteidzoÅ”as atklāsmes par Kubernetes, taču jÅ«s varat sagaidÄ«t pāris labas nodarbÄ«bas par sarežģītām sistēmām.

Pirms pāris nedēļām mana komanda migrēja vienu mikropakalpojumu uz pamata platformu, kas ietvēra CI/CD, uz Kubernetes balstÄ«tu izpildlaiku, metriku un citus labumus. PārcelÅ”anās bija izmēģinājuma raksturs: plānojām to ņemt par pamatu un tuvāko mēneÅ”u laikā nodot vēl aptuveni 150 pakalpojumus. Viņi visi ir atbildÄ«gi par dažu lielāko tieÅ”saistes platformu darbÄ«bu Spānijā (Infojobs, Fotocasa utt.).

Pēc tam, kad mēs izvietojām lietojumprogrammu Kubernetes un novirzÄ«jām uz to daļu trafika, mÅ«s gaidÄ«ja satraucoÅ”s pārsteigums. KavÄ“Å”anās (latents) pieprasÄ«jumu skaits Kubernetes bija 10 reizes lielāks nekā EC2. Kopumā bija nepiecieÅ”ams vai nu rast risinājumu Å”ai problēmai, vai arÄ« atteikties no mikropakalpojuma (un, iespējams, arÄ« visa projekta) migrācijas.

Kāpēc Kubernetes latentums ir tik daudz lielāks nekā EC2?

Lai atrastu vājo vietu, mēs apkopojām metriku visā pieprasÄ«juma ceļā. MÅ«su arhitektÅ«ra ir vienkārÅ”a: API vārteja (Zuul) nosÅ«ta pieprasÄ«jumus mikropakalpojumu gadÄ«jumiem EC2 vai Kubernetes. Programmā Kubernetes mēs izmantojam NGINX ieejas kontrolieri, un aizmugursistēmas ir parasti objekti, piemēram IzvietoÅ”anas ar JVM lietojumprogrammu Spring platformā.

                                  EC2
                            +---------------+
                            |  +---------+  |
                            |  |         |  |
                       +-------> BACKEND |  |
                       |    |  |         |  |
                       |    |  +---------+  |                   
                       |    +---------------+
             +------+  |
Public       |      |  |
      -------> ZUUL +--+
traffic      |      |  |              Kubernetes
             +------+  |    +-----------------------------+
                       |    |  +-------+      +---------+ |
                       |    |  |       |  xx  |         | |
                       +-------> NGINX +------> BACKEND | |
                            |  |       |  xx  |         | |
                            |  +-------+      +---------+ |
                            +-----------------------------+

Å Ä·iet, ka problēma ir saistÄ«ta ar sākotnējo latentumu aizmugursistēmā (problēmas apgabalu grafikā atzÄ«mēju kā "xx"). EC2 lietojumprogrammas atbilde aizņēma aptuveni 20 ms. Kubernetes latentums palielinājās lÄ«dz 100-200 ms.

Mēs ātri noraidÄ«jām iespējamās aizdomās turamās personas, kas bija saistÄ«tas ar izpildlaika maiņu. JVM versija paliek nemainÄ«ga. ArÄ« konteineru ievietoÅ”anas problēmām ar to nebija nekāda sakara: lietojumprogramma jau veiksmÄ«gi darbojās EC2 konteineros. Vai tiek ielādēts? Bet mēs novērojām augstu latentumu pat ar 1 pieprasÄ«jumu sekundē. Varētu atstāt novārtā arÄ« atkritumu savākÅ”anas pauzes.

Viens no mÅ«su Kubernetes administratoriem jautāja, vai lietojumprogrammai nav ārējas atkarÄ«bas, jo DNS vaicājumi iepriekÅ” bija radÄ«juÅ”i lÄ«dzÄ«gas problēmas.

1. hipotēze: DNS nosaukuma izŔķirÅ”ana

Katram pieprasÄ«jumam mÅ«su lietojumprogramma vienu lÄ«dz trÄ«s reizes piekļūst AWS Elasticsearch instancei tādā domēnā kā elastic.spain.adevinta.com. MÅ«su konteineros ir čaula, lai mēs varētu pārbaudÄ«t, vai domēna meklÄ“Å”ana patieŔām aizņem ilgu laiku.

DNS vaicājumi no konteinera:

[root@be-851c76f696-alf8z /]# while true; do dig "elastic.spain.adevinta.com" | grep time; sleep 2; done
;; Query time: 22 msec
;; Query time: 22 msec
;; Query time: 29 msec
;; Query time: 21 msec
;; Query time: 28 msec
;; Query time: 43 msec
;; Query time: 39 msec

Līdzīgi pieprasījumi no viena no EC2 gadījumiem, kurā darbojas lietojumprogramma:

bash-4.4# while true; do dig "elastic.spain.adevinta.com" | grep time; sleep 2; done
;; Query time: 77 msec
;; Query time: 0 msec
;; Query time: 0 msec
;; Query time: 0 msec
;; Query time: 0 msec

Ņemot vērā, ka uzmeklÄ“Å”ana ilga aptuveni 30 ms, kļuva skaidrs, ka DNS izŔķirtspēja, piekļūstot Elasticsearch, patieŔām veicināja latentuma palielināŔanos.

Tomēr tas bija dīvaini divu iemeslu dēļ:

  1. Mums jau ir daudz Kubernetes lietojumprogrammu, kas mijiedarbojas ar AWS resursiem, necieŔot no liela latentuma. Lai kāds būtu iemesls, tas attiecas tieŔi uz Ŕo gadījumu.
  2. Mēs zinām, ka JVM veic DNS keÅ”atmiņu atmiņā. MÅ«su attēlos TTL vērtÄ«ba ir ierakstÄ«ta $JAVA_HOME/jre/lib/security/java.security un iestatiet uz 10 sekundēm: networkaddress.cache.ttl = 10. Citiem vārdiem sakot, JVM ir jāsaglabā keÅ”atmiņā visi DNS vaicājumi 10 sekundes.

Lai apstiprinātu pirmo hipotēzi, mēs nolēmām kādu laiku pārtraukt DNS izsaukÅ”anu un pārbaudÄ«t, vai problēma ir pazudusi. Pirmkārt, mēs nolēmām pārkonfigurēt lietojumprogrammu, lai tā tieÅ”i sazinātos ar Elasticsearch pēc IP adreses, nevis ar domēna nosaukumu. Tam bÅ«tu nepiecieÅ”amas koda izmaiņas un jauna izvietoÅ”ana, tāpēc mēs vienkārÅ”i kartējām domēnu ar tā IP adresi /etc/hosts:

34.55.5.111 elastic.spain.adevinta.com

Tagad konteiners gandrÄ«z uzreiz saņēma IP. Tas radÄ«ja nelielus uzlabojumus, taču mēs bijām tikai nedaudz tuvāk paredzamajiem latentuma lÄ«meņiem. Lai gan DNS atrisināŔana prasÄ«ja ilgu laiku, patiesais iemesls mums joprojām nav izdevies.

Diagnostika caur tīklu

Mēs nolēmām analizēt trafiku no konteinera, izmantojot tcpdumplai redzētu, kas tieÅ”i notiek tÄ«klā:

[root@be-851c76f696-alf8z /]# tcpdump -leni any -w capture.pcap

Pēc tam mēs nosÅ«tÄ«jām vairākus pieprasÄ«jumus un lejupielādējām to tverÅ”anu (kubectl cp my-service:/capture.pcap capture.pcap), lai veiktu turpmāku analÄ«zi Wireshark.

DNS vaicājumos nebija nekā aizdomÄ«ga (izņemot vienu sÄ«kumu, par kuru es runāŔu vēlāk). Taču bija dažas dÄ«vainÄ«bas, kā mÅ«su dienests apstrādāja katru pieprasÄ«jumu. Tālāk ir redzams tverÅ”anas ekrānuzņēmums, kurā redzams, ka pieprasÄ«jums tiek pieņemts pirms atbildes sākÅ”anas:

ā€œKubernetes palielināja latentumu 10 reizesā€: kurÅ” pie tā ir vainÄ«gs?

Iepakojuma numuri ir parādīti pirmajā kolonnā. Skaidrības labad dažādās TCP straumes esmu kodējis ar krāsām.

Zaļā straume, kas sākas ar paketi 328, parāda, kā klients (172.17.22.150) izveidoja TCP savienojumu ar konteineru (172.17.36.147). Pēc sākotnējās rokasspiediena (328-330) atnesa iepakojumu 331 HTTP GET /v1/.. ā€” mÅ«su dienestam ienākoÅ”s pieprasÄ«jums. Viss process aizņēma 1 ms.

Pelēkā straume (no 339. paketes) parāda, ka mÅ«su pakalpojums nosÅ«tÄ«ja HTTP pieprasÄ«jumu Elasticsearch instancei (nav TCP rokasspiediena, jo tiek izmantots esoÅ”s savienojums). Tas aizņēma 18 ms.

Pagaidām viss ir kārtībā, un laiki aptuveni atbilst paredzamajiem kavējumiem (20-30 ms, mērot no klienta).

Tomēr zilā sadaļa aizņem 86 ms. Kas tajā notiek? Izmantojot paketi 333, mÅ«su pakalpojums nosÅ«tÄ«ja HTTP GET pieprasÄ«jumu uz /latest/meta-data/iam/security-credentials, un tÅ«lÄ«t pēc tā, izmantojot to paÅ”u TCP savienojumu, vēl viens GET pieprasÄ«jums /latest/meta-data/iam/security-credentials/arn:...

Mēs atklājām, ka tas atkārtojas ar katru pieprasÄ«jumu visā trasē. DNS izŔķirtspēja mÅ«su konteineros patieŔām ir nedaudz lēnāka (skaidrojums Å”ai parādÄ«bai ir diezgan interesants, bet es to saglabāŔu atseviŔķam rakstam). IzrādÄ«jās, ka ilgās kavÄ“Å”anās iemesls bija zvani uz AWS instances metadatu pakalpojumu pēc katra pieprasÄ«juma.

2. hipotēze: nevajadzīgi izsaukumi uz AWS

Abi galapunkti pieder AWS instances metadatu API. MÅ«su mikropakalpojums izmanto Å”o pakalpojumu Elasticsearch darbÄ«bas laikā. Abi zvani ir daļa no pamata autorizācijas procesa. Galapunkts, kuram tiek piekļūts pēc pirmā pieprasÄ«juma, izdod ar instanci saistÄ«to IAM lomu.

/ # curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
arn:aws:iam::<account_id>:role/some_role

Otrais pieprasījums pieprasa otrajam galapunktam pagaidu atļaujas Ŕim gadījumam:

/ # curl http://169.254.169.254/latest/meta-data/iam/security-credentials/arn:aws:iam::<account_id>:role/some_role`
{
    "Code" : "Success",
    "LastUpdated" : "2012-04-26T16:39:16Z",
    "Type" : "AWS-HMAC",
    "AccessKeyId" : "ASIAIOSFODNN7EXAMPLE",
    "SecretAccessKey" : "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
    "Token" : "token",
    "Expiration" : "2017-05-17T15:09:54Z"
}

Klients tos var izmantot Ä«su laiku un periodiski jāiegÅ«st jauni sertifikāti (pirms to iegÅ«Å”anas Expiration). Modelis ir vienkārÅ”s: droŔības apsvērumu dēļ AWS bieži rotē pagaidu atslēgas, taču klienti var tās dažas minÅ«tes saglabāt keÅ”atmiņā, lai kompensētu veiktspējas sodu, kas saistÄ«ts ar jaunu sertifikātu iegÅ«Å”anu.

AWS Java SDK vajadzētu uzņemties atbildÄ«bu par Ŕī procesa organizÄ“Å”anu, taču kaut kādu iemeslu dēļ tas nenotiek.

Pēc problēmu meklÄ“Å”anas vietnē GitHub mēs saskārāmies ar problēmu #1921. Viņa mums palÄ«dzēja noteikt virzienu, kurā ā€œraktā€ tālāk.

AWS SDK atjaunina sertifikātus, ja rodas kāds no Ŕiem nosacījumiem:

  • DerÄ«guma termiņŔ (Expiration) Iekrist EXPIRATION_THRESHOLD, kodēts lÄ«dz 15 minÅ«tēm.
  • KopÅ” pēdējā sertifikātu atjaunoÅ”anas mēģinājuma pagājis vairāk laika nekā REFRESH_THRESHOLD, kodēts 60 minÅ«tes.

Lai redzētu saņemto sertifikātu faktisko derÄ«guma termiņu, mēs izpildÄ«jām iepriekÅ” minētās cURL komandas gan no konteinera, gan no EC2 instances. No konteinera saņemtā sertifikāta derÄ«guma termiņŔ izrādÄ«jās krietni Ä«sāks: tieÅ”i 15 minÅ«tes.

Tagad viss ir kļuvis skaidrs: par pirmo pieprasÄ«jumu mÅ«su dienests saņēma pagaidu sertifikātus. Tā kā tie nebija derÄ«gi ilgāk par 15 minÅ«tēm, AWS SDK izlems tos atjaunināt pēc nākamā pieprasÄ«juma. Un tas notika ar katru pieprasÄ«jumu.

Kāpēc sertifikātu derÄ«guma termiņŔ ir kļuvis Ä«sāks?

AWS instances metadati ir paredzēti darbam ar EC2 gadÄ«jumiem, nevis ar Kubernetes gadÄ«jumiem. No otras puses, mēs negribējām mainÄ«t lietojumprogrammas saskarni. Å im nolÅ«kam mēs izmantojām KIAM - rÄ«ks, kas, izmantojot aÄ£entus katrā Kubernetes mezglā, ļauj lietotājiem (inženieriem, kas izvieto lietojumprogrammas klasterÄ«) pieŔķirt IAM lomas konteineriem podiņos tā, it kā tie bÅ«tu EC2 gadÄ«jumi. KIAM pārtver zvanus uz AWS instances metadatu pakalpojumu un apstrādā tos no keÅ”atmiņas, iepriekÅ” tos saņēmis no AWS. No pielietojuma viedokļa nekas nemainās.

KIAM piegādā pākstÄ«m Ä«stermiņa sertifikātus. Tas ir loÄ£iski, ņemot vērā, ka pāksts vidējais kalpoÅ”anas laiks ir Ä«sāks nekā EC2 eksemplāram. Sertifikātu noklusējuma derÄ«guma termiņŔ vienāds ar tām paŔām 15 minÅ«tēm.

Tā rezultātā, ja abas noklusējuma vērtÄ«bas pārklājat vienu virs otras, rodas problēma. Katrs pieteikumam iesniegtais sertifikāts beidzas pēc 15 minÅ«tēm. Tomēr AWS Java SDK piespiež atjaunot jebkuru sertifikātu, kuram lÄ«dz derÄ«guma termiņa beigām ir atlikuÅ”as mazāk nekā 15 minÅ«tes.

Rezultātā pagaidu sertifikāts ir spiests atjaunot ar katru pieprasījumu, kas ietver pāris izsaukumus uz AWS API un izraisa ievērojamu latentuma pieaugumu. AWS Java SDK mēs atradām funkcijas pieprasījums, kurā ir minēta līdzīga problēma.

Risinājums izrādÄ«jās vienkārÅ”s. Mēs vienkārÅ”i pārkonfigurējām KIAM, lai pieprasÄ«tu sertifikātus ar ilgāku derÄ«guma termiņu. Kad tas notika, pieprasÄ«jumi sāka plÅ«st bez AWS metadatu pakalpojuma lÄ«dzdalÄ«bas, un latentums samazinājās lÄ«dz pat zemākam lÄ«menim nekā EC2.

Atzinumi

Balstoties uz mÅ«su pieredzi ar migrāciju, viens no biežākajiem problēmu avotiem nav Kubernetes vai citu platformas elementu kļūdas. Tas arÄ« nenovērÅ” nekādus bÅ«tiskus trÅ«kumus mikropakalpojumos, kurus mēs pārnesam. Problēmas bieži rodas vienkārÅ”i tāpēc, ka mēs apvienojam dažādus elementus.

Mēs sajaucam kopā sarežģītas sistēmas, kuras nekad iepriekÅ” nav bijuÅ”as mijiedarbÄ«bā, sagaidot, ka tās kopā veidos vienotu, lielāku sistēmu. Diemžēl, jo vairāk elementu, jo vairāk kļūdu, jo lielāka ir entropija.

MÅ«su gadÄ«jumā lielais latentums nebija Kubernetes, KIAM, AWS Java SDK vai mÅ«su mikropakalpojuma kļūdu vai sliktu lēmumu rezultāts. Tas tika iegÅ«ts, apvienojot divus neatkarÄ«gus noklusējuma iestatÄ«jumus: vienu KIAM, otru AWS Java SDK. AtseviŔķi ņemti vērā abi parametri: aktÄ«vā sertifikātu atjaunoÅ”anas politika AWS Java SDK un sertifikātu Ä«sais derÄ«guma termiņŔ KAIM. Bet, tos saliekot kopā, rezultāti kļūst neparedzami. Diviem neatkarÄ«giem un loÄ£iskiem risinājumiem nav jābÅ«t jēgas, ja tos apvieno.

PS no tulka

Varat uzzināt vairāk par KIAM utilÄ«ta arhitektÅ«ru AWS IAM integrÄ“Å”anai ar Kubernetes vietnē Å is raksts no tā veidotājiem.

Lasiet arī mūsu emuārā:

Avots: www.habr.com

Pievieno komentāru