MÀrk. tÔlge.: See artikkel, mille autor on Galo Navarro, kes töötab peamise tarkvarainsenerina Euroopa ettevÔttes Adevinta, on pÔnev ja Ôpetlik "uurimus" infrastruktuuri kasutamise valdkonnas. Originaaltitlit on tÔlkes veidi muudetud, nagu autor selgitab artikli alguses.

Autorilt mĂ€rkus: Tundub, et see avaldus palju rohkem tĂ€helepanu kui oodatud. Ma saan siiani vihaseid kommentaare selle kohta, et artikli pealkiri on eksitav ja et mĂ”ned lugejad on kurvad. Ma mĂ”istan juhtunust tingitud pĂ”hjuseid, seetĂ”ttu tahan, vaatamata riskile kogu intriig loomata, kohe rÀÀkida, millest see artikkel rÀÀgib. Kui meeskonnad ĂŒleviivad Kubernetes'esse, jĂ€lgin ma huvitavat asja: iga kord, kui tekib probleem (nt viivituste suurenemine pĂ€rast migreerimist), sĂŒĂŒdistatakse kohe Kubernetes't, kuid hiljem selgub, et orkestreerija ei ole ĂŒldiselt sĂŒĂŒdi. See artikkel kĂ€sitleb ĂŒhte sellist juhtumit. Selle pealkiri kordab ĂŒhte meie arendajate hĂŒĂŒdu (hiljem nĂ€ete, et Kubernetes ei ole siin absoluutselt sĂŒĂŒdi). Te ei leia sealt ootamatuid Ă€ratundmisi Kubernetes'est, kuid vĂ”ite oodata paar head Ă”ppimist keeruliste sĂŒsteemide kohta.
Paari nĂ€dala eest töötas minu tiim ĂŒhe mikroteenuse migratsiooniga peamine platvorm, mis sisaldab CI/CD-d, Kubernetes-pĂ”hist töökeskkonda, mÔÔdikuid ja muid kasulikke omadusi. Kolimine oli katseperioodil: plaanisime seda kasutada aluseks ja viia lĂ€hikuudel ĂŒle veel umbes 150 teenust. KĂ”ik need teenused vastutavad mĂ”nede suurimate veebiplatvormide, nagu Infojobs, Fotocasa ja teised, toimimise eest.
PĂ€rast seda, kui rakendus Kubernetesis kĂ€ivitati ja liiklus sellele suunati, ootas meid murettekitav ĂŒllatus. Kuberentes olevate pĂ€ringute viivitus oli 10 korda kĂ”rgem kui EC2-s. (latency) KokkuvĂ”ttes oli vajalik kas selle probleemi lahenduse leidmine vĂ”i mikroteenuse migratsioonist loobumine (vĂ”i vĂ”imalusel kogu projekti lĂ”petamine).
Miks on Kubernetesis viivitus nii palju kÔrgem kui EC2-s?
Selle kitsaskoha leidmiseks kogusime mÔÔdikud kogu pÀringu teele. Meie arhitektuur on lihtne: API-lÀbisÔitja (Zuul) edastab pÀringud mikroteenuse eksemplaridele EC2-s vÔi Kubernetesis. Kubernetesis kasutame NGINX Ingress Controllereid ja tagaplaanid on tavalised objektid, millel on JVM-rakendus Springi platvormil.
EC2
+---------------+
| +---------+ |
| | | |
+-------> BACKEND | |
| | | | |
| | +---------+ |
| +---------------+
+------+ |
Public | | |
-------> ZUUL +--+
traffic | | | Kubernetes
+------+ | +-----------------------------+
| | +-------+ +---------+ |
| | | | xx | | |
+-------> NGINX +------> BACKEND | |
| | | xx | | |
| +-------+ +---------+ |
+-----------------------------+Tundus, et probleem oli seotud algfaasi viivitusega backendis (mĂ€rgin kahtlase koha joonisel kui "xx"). EC2-s vĂ”ttis rakenduse vastus umbes 20 ms. Kuberneteses suurenes viivitus 100â200 ms-ni.
KĂŒsimuse sealt mitte Ă”nnestunud kahtlusaluste hulgast vĂ€listasime kiiresti, mis olid seotud keskkonna muutumisega. JVM-i versioon jĂ€i muutumatuks. Ka konteineriseerimise probleemid ei olnud asjaosalised: rakendus toimis juba EC2-s konteinerites edukalt. Koormus? Kuid isegi 1 pĂ€ringu sekundis puhul oli meil mĂ€rkimisvÀÀrsed viivitused. PrĂŒgikoristuspausidega oli samuti vĂ”imalik kĂ”rvale hiilida.
Ăks meie Kubernetes'i administraatoritest kĂŒsis, kas rakendusel on vĂ€liseid sĂ”ltuvusi, kuna minevikus on DNS-i pĂ€ringud pĂ”hjustanud sarnaseid probleeme.
HĂŒpotees 1: DNS-i nimede lahendamine
Iga pÀringu korral pöördub meie rakendus AWS Elasticsearch'i eksemplari poole kuni kolm korda domeenis, mis nÀeb vÀlja nagu elastic.spain.adevinta.com. Konteinerite sees on meil , seega saame kontrollida, kas domeeni otsingu ajal tÔepoolest kulub palju aega.
DNS-i pÀringud konteinerist:
[root@be-851c76f696-alf8z \]# while true; do dig "elastic.spain.adevinta.com" | grep time; sleep 2; done
;; KĂŒsi aeg: 22 msec
;; KĂŒsi aeg: 22 msec
;; KĂŒsi aeg: 29 msec
;; KĂŒsi aeg: 21 msec
;; KĂŒsi aeg: 28 msec
;; KĂŒsi aeg: 43 msec
;; KĂŒsi aeg: 39 msecSarnased pĂ€ringud ĂŒhest EC2 eksemplarist, kus rakendus töötab:
bash-4.4# while true; do dig "elastic.spain.adevinta.com" | grep time; sleep 2; done
;; KĂŒsi aeg: 77 msec
;; KĂŒsi aeg: 0 msec
;; KĂŒsi aeg: 0 msec
;; KĂŒsi aeg: 0 msec
;; KĂŒsi aeg: 0 msecArvestades, et otsing vĂ”tab aega umbes 30 ms, sai selgeks, et DNS-i lahendus Elasticsearch'iga suhtlemisel tĂ”epoolest panustab latentsuse suurenemisse.
Kuid see oli kummaline kahel pÔhjusel:
- Meil on juba palju rakendusi Kuberneteses, mis suhtlevad AWSi ressurssidega, kuid ei kannata suure latentsuse all. Mis iganes pÔhjus see ka poleks, on see konkreetselt seotud antud juhtumiga.
- Teame, et JVM teostab DNS-i in-memory vahemÀlu. Meie piltides on TTL vÀÀrtus mÀÀratud
$JAVA_HOME/jre/lib/security/java.securityja see on seatud 10 sekundiks:networkaddress.cache.ttl = 10. TeisisÔnu, JVM peab vahemÀlu kÔik DNS-i pÀringud 10 sekundi jooksul.
Esimese hĂŒpoteesi kinnitamiseks otsustasime ajutiselt loobuda DNS-i pĂ€ringutest ja vaadata, kas probleem kaob. Esmalt otsustasime kohandada rakendust, et see suhtleks Elasticsearchiga otse IP-aadressi kaudu, mitte domeeninime kaudu. See oleks nĂ”udnud koodi muutmist ja uut juurutamist, seega sidusime domeeni selle IP-aadressiga /etc/hosts:
34.55.5.111 elastic.spain.adevinta.comNĂŒĂŒd sai konteiner IP-aadressi peaaegu koheselt. See tĂ”i kaasa teatava paranemise, kuid me lĂ€henesime vaid veidi oodatud latentsuse tasemele. Kuigi DNS-i lahendamine vĂ”ttis aega, varjas tĂ”eline pĂ”hjus endiselt meie nĂ€gemise alt.
Diagnostika vÔrgu abil
Otsustasime analĂŒĂŒsida konteinerist tulevat liiklust tcpdump, et jĂ€lgida, mis tĂ€pselt toimub vĂ”rgus:
[root@be-851c76f696-alf8z /]# tcpdump -leni any -w capture.pcap SeejĂ€rel saatsime vĂ€lja mĂ”ned pĂ€ringud ja allalaadisin nende salvestuse (kubectl cp my-service:/capture.pcap capture.pcap) edasiseks analĂŒĂŒsiks .
DNS-pĂ€ringutes ei olnud midagi kahtlast (vĂ€lja arvatud ĂŒks vĂ€ikeste asja, millest rÀÀgin hiljem). Kuid meie teenuse kĂ€sitlemisel igas pĂ€ringus ilmnesid teatud kummalised asjad. Allpool on captura ekraanipilt, mis nĂ€itab pĂ€ringu vastuvĂ”tmist enne vastuse algust:

Pakettide numbrid on toodud esimeses veerus. Selguse huvides olen erinevad TCP-vood vÀrvidega eristanud.
Roheline voog, mis algab 328. paketist, nĂ€itab, kuidas klient (172.17.22.150) lĂ”i TCP-seose konteineriga (172.17.36.147). PĂ€rast esmast kĂ€epigistust (328-330) tĂ”i pakett 331 HTTP GET /v1/.. â sisenemise pĂ€ring meie teenusele. Kogu protsess vĂ”ttis aega 1 ms.
Hall voog (paketist 339) nĂ€itab, et meie teenus saatis HTTP-pĂ€ringu Elasticsearchi eksemplarile (TCP-kĂ€epigistus puudub, kuna kasutatakse juba olemasolevat ĂŒhendust). Selleks kulus 18 ms.
Praegu on kĂ”ik korras ja ajad vastavad enam-vĂ€hem oodatud viivitustele (20â30 ms kliendi mÔÔtmiste pĂ”hjal).
Kuid sinine sektsioon vĂ”tab 86 ms. Mis seal toimub? Paketi 333 korral saatis meie teenus HTTP GET-pĂ€ringu aadressile /latest/meta-data/iam/security-credentials, ja kohe pĂ€rast seda, sama TCP-ĂŒhenduse kaudu, veel ĂŒks GET-pĂ€ring aadressile /latest/meta-data/iam/security-credentials/arn:...
Oleme tuvastanud, et see kordub iga pÀringu puhul kogu jÀlgimises. DNS-i lahendamine on tÔepoolest meie konteinerites veidi aeglasem (selle fenomeni seletus on vÀga huvitav, kuid ma hoian selle eraldi artikli jaoks). Selgus, et suurte viivituste pÔhjuseks on AWS Instance Metadata teenusele tehtavad pÀringud iga pÀringu puhul.
HĂŒpotees 2: liigsed pĂ€ringud AWS-ile
MÔlemad lÔpp-punktid kuuluvad . Meie mikroteenus kasutab seda teenust Elasticsearchiga töötamisel. MÔlemad kutsed on osa pÔhivolituste protsessist. Esimese pÀringu korral toimub pöördumine lÔpp-punkti, mis vÀljastab instantsiga seotud IAM-rolli.
/ # curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
arn:aws:iam::<account_id>:role/some_roleTeine pÀring pöördub teise lÔpp-punkti poole, et saada ajutisi volitusi antud instantsi jaoks:
/ # 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"
} Kliendil on vĂ”imalus neid kasutada lĂŒhikese aja jooksul ja ta peab aeg-ajalt saama uusi sertifikaate (kuni nende Aegumine). Mudel on lihtne: AWS korraldab turvakaalutlustel sagedast ajutiste vĂ”tmete vahetust, kuid kliendid saavad neid mitu minutit vahemĂ€llu talletada, tasakaalustades uute sertifikaatide saamisega seotud jĂ”udluse langust.
AWS Java SDK peab selle protsessi korraldamise endale vÔtma, kuid mingil pÔhjusel seda ei juhtu.
Otsides GitHub'i probleemide seast, sattusime probleemile . See aitas meil mÀÀratleda suuna, kuhu edasi "kaevata".
AWS SDK vĂ€rskendab sertifikaate, kui toimub ĂŒks jĂ€rgmistest tingimustest:
- Nende kehtivusaja lÔpp (
Aegumine) satubEXPIRATION_THRESHOLD, mis on koodis rangelt seadistatud 15 minutiks. - Olenemata viimasest katsest sertifikaate vÀrskendada, on möödunud rohkem aega kui
REFRESH_THRESHOLD, mis on 'hardcode' vahel 60 minuti jooksul.
Kuna nĂ€ha sertifikaatide tegelikku kehtivusaega, sooritasime ĂŒlaltoodud cURL-kĂ€sud konteinerist ja EC2 instantsist. Konteinerist saadud sertifikaadi kehtivusaeg oli palju lĂŒhem: tĂ€pselt 15 minutit.
NĂŒĂŒd on kĂ”ik selge: esimese pĂ€ringu puhul sai meie teenus ajutisi sertifikaate. Kuna nende kehtivusaeg ei ĂŒletanud 15 minutit, otsustas AWS SDK jĂ€rgmisel pĂ€ringul need uuendada. Ja see juhtus iga pĂ€ringu puhul.
Miks sertifikaatide kehtivusaeg lĂŒhenes?
AWS Instance Metadata teenus on mĂ”eldud EC2 instantside jaoks, mitte Kubernetesâega. Teisest kĂŒljest ei tahtnud me rakenduste liidese muutmist. Selleks kasutasime â tööriista, mis kasutab agentide abil igal Kubernetesâi sĂ”lmes vĂ”imaldab kasutajatel (inseneridel, kes rakendusi klastris deployivad) mÀÀrata IAM-rolle konteineritele podâides justkui need oleksid EC2 instantsid. KIAM pĂŒĂŒab kinni kutsed AWS Instance Metadata teenusele ja töötleb neid oma vahemĂ€lust, saades need eelnevalt AWS-ilt. Rakenduse vaatenurgast ei muutu midagi.
KIAM pakub lĂŒhiajalisi sertifikaate pod'idele. See on mĂ”istlik, arvestades, et pod'i keskmine eluiga on lĂŒhem kui EC2 instantsi oma. Vaikimisi on sertifikaatide kehtivusaeg .
. Kui need kaks vaikimisi vÀÀrtust ĂŒksteise peale kanda, tekib probleem. Iga rakendusele antud sertifikaat aegub 15 minuti pĂ€rast. Samal ajal sunnib AWS Java SDK igat sertifikaati vĂ€rskendama, kui selle kehtivusest on jÀÀnud vĂ€hem kui 15 minutit.
SeetÔttu vÀrskendatakse ajutist sertifikaati iga pÀringu korral, mis toob kaasa paar API kÔnet AWS-ile ja suurendab mÀrkimisvÀÀrselt viivitust. AWS Java SDK-s avastasime , kus mainitakse sarnast probleemi.
Lahendus osutus lihtsaks. Lihtsalt seadistasime KIAM-i nii, et see kĂŒsib sertifikaate pikema kehtivusajaga. PĂ€rast seda möödusid pĂ€ringud ilma AWS Metadata teenuse osaluseta ja viivitus langes isegi madalamale tasemele kui EC2-s.
JĂ€reldused
Meie migratsioonikogemuse pĂ”hjal on öeldav, et ĂŒks sagedasemaid probleemide allikaid ei ole vigu Kuberneteses ega muudes platvormi elementides. Samuti ei ole see seotud mikroteenuste pĂ”hjalike puudustega, mida me ĂŒle kanname. Probleemid tekivad sageli lihtsalt seetĂ”ttu, et ĂŒhendame omavahel erinevaid komponente.
Segame kokku keerulisi sĂŒsteeme, mis pole kunagi varem omavahel suhelnud, oodates, et koos nad moodustavad ĂŒhe suurema sĂŒsteemi. Kahjuks, mida rohkem komponente, seda rohkem on ruumi vigade tekkeks ja seda suurem on entropia.
Meie puhul ei olnud kĂ”rge latentsus pĂ”hjustatud vigadest ega halbadest lahendustest Kuberneteses, KIAMis, AWS Java SDK-s ega meie mikroteenuses. See tulenes kahest sĂ”ltumatust vaikimisi parameetrist: ĂŒhest KIAMis, teisest AWS Java SDK-s. Ăksikult on mĂ”lemad parameetrid mĂ”istlikud: nii aktiivne sertifikaatide uuendamise poliitika AWS Java SDK-s kui ka lĂŒhikese kehtivusajaga sertifikaadid KIAM-is. Kuid kui need kokku panna, muutuvad tulemused ettearvamatuks. Kaks sĂ”ltumatut ja loogilist lahendust ei pruugi kokkuvĂ”ttes mĂ”istlikud olla.
P.S. tÔlkija mÀrkused
AWS IAM integreerimise KIAM utiliidi arhitektuuri kohta saate lÀhemalt lugeda selle loojatelt.
Ja meie blogist lugege ka:
- «»;
- «»;
- «»;
- «».
Allikas: habr.com
