Post Mortem privind inaccesibilitatea Quay.io

Nota traducătorului.: la începutul lunii august, Red Hat a anunțat public despre soluțiile pentru problemele de disponibilitate care au apărut în lunile anterioare pentru utilizatorii serviciului său. Quay.io (în esență, acesta este un registru pentru imagini de containere, primit de companie odată cu achiziționarea CoreOS). Indiferent de interesul dumneavoastră față de acest serviciu, calea pe care inginerii SRE ai companiei au parcurs-o pentru a diagnostica și a rezolva cauzele întreruperii este instructivă.

Post Mortem privind inaccesibilitatea Quay.io

Pe 19 mai, devreme în dimineață (ora de vară a timpului de est al Americii de Nord, EDT), serviciul quay.io a căzut. Incidentul a afectat atât utilizatorii quay.io, cât și proiectele Open Source care folosesc quay.io ca platformă pentru construirea și distribuirea software-ului. Red Hat valorifică încrederea atât a uneia, cât și a celeilalte părți.

Echipa de ingineri SRE a intervenit imediat și a încercat să stabilizeze serviciul Quay cât mai repede posibil. Cu toate acestea, în timp ce aceștia lucrau, clienții nu au putut să împingă noi imagini și doar ocazional reușeau să descarce cele existente. Dintr-o cauză necunoscută, baza de date quay.io se bloca după scalarea serviciului la capacitate maximă.

«Ce s-a schimbat?» — aceasta este prima întrebare pe care se obișnuiește să o pună în astfel de cazuri. Am observat că, cu puțin timp înainte de problemă, clusterul OpenShift Dedicated (pe care rulează quay.io) a început să se actualizeze la versiunea 4.3.19. Deoarece quay.io funcționează pe Red Hat OpenShift Dedicated (OSD), actualizările regulate erau o operațiune obișnuită și niciodată nu au cauzat probleme. Mai mult, în ultimele șase luni, am actualizat de mai multe ori clusterele Quay fără vreo întrerupere în serviciu.

În timp ce încercam să restabilim funcționarea serviciului, alți ingineri au început să pregătească un nou cluster OSD cu o versiune anterioară a software-ului, pentru a putea desfășura totul pe acesta, în caz de necesitate.

Analiza cauzelor principale

Simptomul principal al defectării a fost o avalanșă de zeci de mii de conexiuni la baza de date, din cauza căreia instanța MySQL a devenit practic ineficientă. Din acest motiv, a fost greu să diagnostice problema. Am impus o restricție asupra numărului maxim de conexiuni din partea clienților pentru a ajuta echipa SRE să evalueze problema. Nu am observat trafic neobișnuit către baza de date: de fapt, majoritatea cererilor erau pentru citire, iar doar câteva pentru scriere.

Am încercat, de asemenea, să identificăm un model în traficul bazei de date care ar putea provoca această avalanșă. Totuși, nu am reușit să găsim nicio regularitate în jurnale. Așteptând finalizarea noului cluster cu OSD 4.3.18, am continuat încercările de a lansa pod-urile quay.io. De fiecare dată când cluster-ul ajungea la capacitate maximă, baza de date se bloca. Aceasta însemna că era necesar să repornim instanța RDS, pe lângă toate pod-urile quay.io.

Până seara, am stabilizat serviciul în modul de citire și am dezactivat maximum funcțiilor nesemnificative (de exemplu, colectarea deșeurilor în spațiul de nume) pentru a reduce încărcătura pe baza de date. Blocajele s-au oprit, dar cauza nu a fost găsită. Noul cluster OSD a fost gata și am mutat serviciul, am conectat traficul și am continuat monitorizarea.

Quay.io a funcționat stabil pe noul cluster OSD, așa că ne-am întors la jurnalele bazei de date, dar nu am reușit să descoperim o corelație care să explice blocajele. Inginerii OpenShift au colaborat cu noi, încercând să înțeleagă dacă modificările din Red Hat OpenShift 4.3.19 ar fi putut cauză problemelor cu Quay. Totuși, nu s-a descoperit nimic și problema nu a putut fi reproducă în condiții de laborator.

Al doilea eșec

Pe 28 mai, puțin înainte de prânz EDT, quay.io a căzut din nou cu aceleași simptome: funcționarea bazei de date era blocată. Și din nou, ne-am concentrat toate forțele pe investigare. În primul rând, trebuia să restabilim funcționarea serviciului. Totuși, de data aceasta, repornirea RDS și relansarea pod-urilor quay.io nu au dus nicăieri: o altă avalanșă de conexiuni a inundat baza de date. Dar de ce?Quay este scris în Python, iar fiecare pod funcționează ca un singur container monolitic. În mediul de execuție al containerului, sunt executate simultan multe sarcini paralele. Folosim biblioteca

gevent pentru a gestiona cererile web. Când Quay primește o cerere (prin API-ul nostru, sau prin API-ul Docker), i se alocă un worker gevent. De obicei, acest worker trebuie să se conecteze la baza de date. După primul eșec, am descoperit că worker-ii gevent se conectau la baza de date, folosind setările implicite. sub gunicorn pentru procesarea cererilor web. Atunci când Quay primește o cerere (prin API-ul nostru sau prin API-ul Docker), i se alocă un worker gevent. De obicei, acest worker trebuie să se conecteze la baza de date. După prima cădere, am descoperit că worker-ii gevent se conectau la baza de date folosind setările implicite.

Având în vedere numărul semnificativ de poduri Quay și mii de cereri primite pe secundă, un număr mare de conexiuni la baza de date ar fi putut, teoretic, să supraîncărce instanța MySQL. Prin monitorizare, s-a constatat că Quay procesează, în medie, 5.000 de cereri pe secundă. Aproximativ același număr era și al conexiunilor la baza de date. 5.000 de conexiuni se încadrau confortabil în capacitățile instanței noastre RDS (ceea ce nu se poate spune despre zecile de mii). Dintr-un motiv oarecare, au avut loc creșteri neașteptate ale numărului de conexiuni, însă nu am observat vreo corelație cu cererile de intrare.

De data aceasta, am decis ferm să găsim și să eliminăm sursa problemei, și nu să ne limităm la o repornire. În codul sursă Quay au fost efectuate modificări pentru a limita numărul de conexiuni la baza de date pentru fiecare worker gevent. Acest număr a devenit un parametru în configurație: a devenit posibil să-l schimbăm „în mișcare”, fără a construi o nouă imagine a containerului. Pentru a afla ce număr de conexiuni poate fi gestionat efectiv, au fost efectuate mai multe teste cu un mediu de staging, în care s-au setat diferite valori pentru a observa cum afectează aceste scenarii de testare a încărcării. În cele din urmă, s-a descoperit că Quay începe să returneze erori 502 când numărul de conexiuni depășește 10.000.

Imediat am desfășurat această nouă versiune în producție și am început să monitorizăm graficul conexiunilor la baza de date. În trecut, baza s-a blocat după aproximativ 20 de minute. După 30 de minute fără probleme, am început să avem speranță, iar după o oră — încredere. Am restabilit traficul de scriere pe site și am început analiza postmortem.

Reușind să evităm problema care cauzase blocarea, nu am reușit să îi aflăm cauzele reale. S-a confirmat că aceasta nu este legată de nicio modificare în OpenShift 4.3.19, deoarece același lucru s-a întâmplat și pe versiunea 4.3.18, care anterior funcționa cu Quay fără nicio problemă.

În cluster se ascundea evident ceva mai mult.

O analiză detaliată

Quay.io a folosit setările implicite pentru conectarea la baza de date timp de șase ani, fără nicio problemă. Ce s-a schimbat? Este evident că, pe parcursul acestei perioade, traficul pe quay.io a crescut constant. În cazul nostru, părea că s-a atins un anumit prag, care a acționat ca un declanșator pentru o avalanșă de conexiuni. Am continuat să analizăm jurnalele bazei de date după a doua cădere, dar nu am găsit nicio corelație sau relație evidentă.

Între timp, echipa SRE s-a ocupat de îmbunătățirea observabilității cererilor în Quay și a sănătății generale a serviciului. Au fost desfășurate noi metrici și tablouri de bord, arătând care părți ale Quay sunt cele mai solicitate de clienți.

Quay.io a funcționat bine până pe 9 iunie. În dimineața (ora EDT), am fost din nou martorii unei creșteri semnificative a numărului de conexiuni la baza de date. De data aceasta nu a avut loc nicio întrerupere, deoarece o nouă setare limita numărul acestora și nu permitea depășirea capacității de procesare MySQL. Totuși, timp de aproximativ o jumătate de oră, mulți utilizatori au raportat o funcționare lentă a quay.io. Am adunat rapid toate datele posibile, folosind instrumentele de monitorizare adăugate. O corelație a apărut brusc.

Înainte de saltul numărului de conexiuni, un număr mare de cereri a fost îndreptat către API-ul App Registry. App Registry este o funcție puțin cunoscută a quay.io. Aceasta permite stocarea unor produse, precum graficele Helm și containerele cu metadate bogate. Cei mai mulți utilizatori ai quay.io nu utilizează această funcție; cu toate acestea, este folosită activ de Red Hat OpenShift. OperatorHub din cadrul OpenShift stochează toți operatorii în App Registry. Acești operatori formează baza pentru ecosistemul de sarcini de lucru OpenShift și modelul operațional (în cadrul operațiunilor "zilei a doua", Day 2) orientat către parteneri.

Fiecare cluster OpenShift 4 utilizează operatori din încorporatul OperatorHub pentru a publica catalogul operatorilor disponibili pentru instalare și pentru a oferi actualizări pentru cei deja instalați. Odată cu creșterea popularității OpenShift 4, numărul clusterelor pe acesta a crescut la nivel global. Fiecare dintre aceste clustere încarcă conținutul operatorilor pentru a lansa OperatorHub-ul încorporat, folosind App Registry din quay.io ca backend. Căutând sursa problemei, am trecut cu vederea faptul că, odată cu creșterea treptată a popularității OpenShift, a crescut și încărcarea pe una dintre funcțiile rar utilizate quay.io..

Am efectuat o analiză a traficului cererilor din App Registry și ne-am uitat în codul registrului. Immediate au apărut defecte care au dus la formarea neoptimizată a cererilor către baza de date. La o încărcare mică, acestea nu cauzau probleme, dar pe măsură ce creștea încărcarea, deveneau surse de probleme. App Registry avea două endpoint-uri problematice, care răspundeau slab la creșterea încărcării: primul returna lista tuturor pachetelor din depozit, iar al doilea returna toate blob-urile pentru un pachet.

Eliminarea cauzelor

În toată săptămâna următoare, ne-am concentrat pe optimizarea codului App Registry și a mediului său. Am rescris interogările SQL evident ineficiente, am eliminat apelurile de comandă inutile, tar (acestea erau efectuate la fiecare extragere a blob-urilor), am adăugat cache acolo unde a fost posibil. Apoi, am efectuat teste extensive de performanță și am comparat viteza de lucru a App Registry înainte și după modificări.

Cererea API, care altădată dura până la o jumătate de minut, acum se realizează în milisecunde.În săptămâna următoare, am implementat modificările în producție, iar de atunci quay.io funcționează stabil. În această perioadă, au fost observate câteva vârfuri bruște de trafic pe endpoint-ul App Registry, dar îmbunătățirile realizate au prevenit întreruperile în funcționarea bazei de date.

Ce am învățat?

Este clar că orice serviciu încearcă să evite timpii de nefuncționare. În cazul nostru, credem că întreruperile recente au ajutat quay.io să devină mai bun. Am învățat câteva lecții esențiale pe care dorim să le împărtășim:

  1. Informațiile despre cine și cum folosește serviciul tău nu sunt niciodată de prisos.Deoarece Quay „a funcționat pur și simplu”, nu am avut niciodată nevoie să ne pierdem timpul cu optimizarea traficului și gestionarea încărcării. Toate acestea au creat o senzație falsă de siguranță, că serviciul poate scala nelimitat.
  2. Când serviciul cade, restaurarea acestuia devine prioritatea principală.. Deoarece Quay a continuat să sufere de o bază de date blocată în timpul primei defecțiuni, procedurile noastre standard nu au avut efectul scontat și nu am reușit să restaurăm serviciul cu ajutorul lor. Acest lucru a dus la o situație în care a fost necesar să pierdem timp analizează și colectând date în speranța de a găsi cauza principală — în loc să ne concentrăm toate eforturile pe restabilirea funcționalității.
  3. Evaluați impactul fiecărei funcții a serviciului. Clienții au folosit rar App Registry, așa că nu a fost o prioritate pentru echipa noastră. Când anumite funcții ale produsului sunt aproape neutilizate, bug-urile lor «apar» rar și dezvoltatorii încetează să urmărească codul. Este ușor să devii victima unei iluzii că așa trebuie să fie — până când, dintr-o dată, această funcție ajunge în centrul unui incident major.

Ce urmează?

Munca pentru asigurarea stabilității serviciului nu se oprește niciodată și ne îmbunătățim constant serviciul. Volumul de trafic pe quay.io continuă să crească și suntem conștienți că trebuie să facem tot posibilul pentru a justifica încrederea clienților. De aceea, lucrăm în prezent la următoarele sarcini:

  1. Implementarea replicilor de baze de date doar pentru citire, pentru a ajuta serviciul să gestioneze traficul corespunzător în cazul în care apar probleme cu instanța principală RDS.
  2. Actualizarea instanței RDS. Versiunea actuală în sine nu este o problemă. Mai degrabă, dorim pur și simplu să eliminăm urma falsă (pe care am urmărit-o în timpul defecțiunii); menținerea software-ului la zi va elimina un alt factor în cazul unor deconectări viitoare.
  3. Cache suplimentar în întregul cluster. Continuăm să căutăm domenii în care cache-ul poate reduce sarcina pe baza de date.
  4. Adăugarea unui firewall pentru aplicații web (WAF) pentru a vedea cine și de ce se conectează la quay.io.
  5. Începând cu următoarea versiune, grupele Red Hat OpenShift vor renunța la App Registry în favoarea catalogilor operatorilor (Operator Catalogs), bazate pe imagini de containere disponibile pe quay.io.
  6. O înlocuire pe termen lung pentru App Registry ar putea fi suportul pentru specificațiile artefactelor Open Container Initiative (OCI). Aceasta este în prezent implementată ca funcționalitate nativă Quay și va fi disponibilă pentru utilizatori atunci când specificația în sine va fi finalizată.

Toate cele de mai sus fac parte din investițiile continue ale Red Hat în quay.io, pe măsură ce trecem de la o echipă mică „în stil de startup” la o platformă matură, gestionată de SRE. Știm că mulți dintre clienții noștri depind de quay.io în activitățile lor zilnice (inclusiv Red Hat!) și ne străduim să fim cât mai transparenți cu privire la întreruperile recente și la eforturile continue de a ne îmbunătăți.

P.S. de la traducător

Citiți și în blogul nostru:

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster