Cerințe pentru dezvoltarea unei aplicații în Kubernetes

Astăzi intenționez să vorbesc despre cum să scrieți aplicații și care sunt cerințele pentru ca aplicația dvs. să funcționeze bine în Kubernetes. Pentru ca aplicația să nu aibă bătăi de cap, astfel încât să nu fii nevoit să inventezi și să construiești nicio „cărășeală” în jurul ei - și totul funcționează așa cum și-a propus Kubernetes.

Această prelegere face parte din „Slurm Night School pe Kubernetes" Puteți vizualiza prelegerile teoretice deschise ale Școlii Serale pe Youtube, grupate într-o listă de redare. Pentru cei care preferă textul decât video, am pregătit acest articol.

Numele meu este Pavel Selivanov, momentan sunt inginer lider DevOps la Mail.ru Cloud Solutions, facem cloud, facem management kubernetes și așa mai departe. Sarcinile mele includ acum asistență în dezvoltare, lansarea acestor nori, lansarea aplicațiilor pe care le scriem și dezvoltarea directă a instrumentelor pe care le oferim utilizatorilor noștri.

Cerințe pentru dezvoltarea unei aplicații în Kubernetes

Am făcut DevOps, cred că în ultimii, probabil, trei ani. Dar, în principiu, fac ceea ce face DevOps de aproximativ cinci ani. Înainte de asta, eram mai mult implicat în chestii de administrare. Am început să lucrez cu Kubernetes cu mult timp în urmă - probabil că au trecut aproximativ patru ani de când am început să lucrez cu el.

În general, am început când Kubernetes era versiunea 1.3, probabil, și poate 1.2 - când era încă la început. Acum nu mai este la început - și este evident că există o cerere uriașă pe piață pentru ingineri care ar dori să poată face Kubernetes. Și companiile au o cerere foarte mare pentru astfel de oameni. Prin urmare, de fapt, această prelegere a apărut.

Dacă vorbim conform planului despre ceea ce voi vorbi, așa arată, între paranteze scrie (TL;DR) - „prea lung; nu citi”. Prezentarea mea de astăzi va consta din liste nesfârșite.

Cerințe pentru dezvoltarea unei aplicații în Kubernetes

De fapt, mie însumi nu-mi plac astfel de prezentări atunci când sunt făcute, dar acesta este un subiect atât de mare încât, atunci când pregăteam această prezentare, pur și simplu nu mi-am dat seama cum să organizez altfel aceste informații.

Pentru că, în mare, această informație este „ctrl+c, ctrl+v”, de la, printre altele, Wiki-ul nostru din secțiunea DevOps, unde am scris cerințe pentru dezvoltatori: „băieți, ca să vă lansăm aplicația în Kubernetes, ar trebui să fie așa.”

De aceea, prezentarea s-a dovedit a fi o listă atât de mare. Îmi pare rău. Voi încerca să spun cât mai multe ca să nu fie plictisitor dacă se poate.

Ce ne vom uita acum:

  • acestea sunt, în primul rând, jurnalele (jurnalele aplicațiilor?), ce să faci cu ele în Kubernetes, ce să faci cu ele, ce ar trebui să fie;
  • ce să faci cu configurațiile în Kubernetes, care sunt cele mai bune și mai proaste moduri de a configura o aplicație pentru Kubernetes;
  • Să vorbim despre ce sunt verificările de accesibilitate în general, cum ar trebui să arate;
  • să vorbim despre ce este o închidere grațioasă;
  • să vorbim din nou despre resurse;
  • Să atingem încă o dată subiectul stocării datelor;
  • iar la final vă voi spune care este termenul acestei misterioase aplicații native în cloud. Cloudnativeness, ca adjectiv al acestui termen.

Bușteni

Vă sugerez să începeți cu jurnalele - cu unde trebuie să fie introduse aceste jurnale în Kubernetes. Acum ați lansat o aplicație în Kubernetes. Potrivit clasicilor, aplicațiile anterior scriau întotdeauna jurnalele undeva într-un fișier. Aplicațiile proaste au scris jurnalele într-un fișier din directorul principal al dezvoltatorului care a lansat aplicația. Aplicațiile bune au scris jurnalele într-un fișier undeva în /var/log.

Cerințe pentru dezvoltarea unei aplicații în Kubernetes

În consecință, în continuare, administratorii buni aveau câteva lucruri configurate în infrastructurile lor pe care aceste jurnaluri le puteau roti - același rsyslog, care se uită la aceste jurnale și când li se întâmplă ceva, sunt multe, creează copii de rezervă, pune jurnalele acolo. , șterge fișierele vechi, mai mult de o săptămână, șase luni și altele. În teorie, ar trebui să avem prevederi astfel încât, pur și simplu pentru că aplicația scrie log-uri, spațiul de pe serverele de producție (servere de luptă?) să nu se epuizeze. Și, în consecință, întreaga producție nu s-a oprit din cauza buștenilor.

Când ne mutăm în lumea Kubernetes și rulăm același lucru acolo, primul lucru la care poți acorda atenție este faptul că oamenii, așa cum au scris jurnalele într-un fișier, continuă să le scrie.

Se pare că, dacă vorbim despre Kubernetes, locul potrivit pentru a scrie jurnalele undeva dintr-un container docker este pur și simplu să le scrieți din aplicație în așa-numitul Stdout/Stderr, adică fluxurile de ieșire standard ale sistemului de operare, ieșirea de eroare standard. Acesta este cel mai corect, cel mai simplu și cel mai logic mod de a pune jurnalele în principiu în Docker și în special în Kubernetis. Deoarece dacă aplicația dvs. scrie jurnalele în Stdout/Stderr, atunci depinde de Docker și de suplimentul Kubernetes să decidă ce să facă cu aceste jurnale. Docker își va construi în mod implicit fișierele speciale în format JSON.

Aici apare întrebarea, ce vei face în continuare cu aceste jurnale? Cea mai ușoară cale este clară, avem capacitatea de a face kubectl logs și uită-te la acești bușteni ale acestor „păstăi”. Dar, probabil, aceasta nu este o opțiune foarte bună - trebuie făcut altceva cu jurnalele.

Deocamdată, să vorbim în același timp, deoarece am atins subiectul jurnalelor, despre așa ceva cum ar trebui să arate jurnalele. Adică, acest lucru nu se aplică direct Kubernetes, dar când începem să ne gândim ce să facem cu jurnalele, ar fi bine să ne gândim și la asta.

Avem nevoie de un fel de instrument, într-un mod amiabil, care să ia aceste jurnale pe care dockerul nostru le pune în fișierele sale și să le trimită undeva. În general, lansăm de obicei un fel de agent în interiorul Kubernetes sub forma unui DaemonSet - un colector de jurnal, căruia i se spune pur și simplu unde se află jurnalele pe care le colectează Docker. Și acest agent de colectare pur și simplu le ia, poate chiar le analizează cumva pe parcurs, poate le îmbogățește cu niște meta-informații suplimentare și, în cele din urmă, le trimite spre stocare undeva. Variațiile sunt deja posibile acolo. Cel mai comun este probabil Elasticsearch, unde puteți stoca jurnalele și le puteți prelua convenabil de acolo. Apoi, folosind o solicitare, folosind Kibana, de exemplu, construiți grafice pe baza lor, construiți alerte pe baza lor și așa mai departe.

Cea mai importantă idee, vreau să o repet din nou, este că în Docker, în special în Kubernetes, stocarea jurnalelor într-un fișier este o idee foarte proastă.

Pentru că, în primul rând, este dificil să introduceți jurnalele în interiorul containerului într-un fișier. Mai întâi trebuie să intri în container, să lucrezi acolo și apoi să te uiți la jurnalele. Următorul punct este că, dacă aveți jurnale într-un fișier, atunci containerele au de obicei un mediu minimalist și nu există utilități care sunt de obicei necesare pentru lucrul normal cu jurnalele. Îngropați-le, priviți-le, deschideți-le într-un editor de text. Următorul moment este când avem loguri într-un fișier în interiorul unui container, dacă acest container este șters, înțelegeți, jurnalele vor muri odată cu el. În consecință, orice repornire a containerului înseamnă că nu mai există jurnale. Din nou, opțiune proastă.

Și ultimul aspect este că în interiorul containerelor aveți de obicei aplicația dvs. și atât - este de obicei singurul proces care rulează. Nu se vorbește deloc despre vreun proces care ar roti fișierele cu jurnalele tale. De îndată ce jurnalele încep să fie scrise într-un fișier, asta înseamnă că, scuzați-mă, vom începe să pierdem serverul de producție. Pentru că, în primul rând, sunt greu de găsit, nimeni nu le urmărește, plus nimeni nu le controlează - în consecință, fișierul crește la nesfârșit până când spațiul de pe server se epuizează pur și simplu. Prin urmare, spun din nou că autentificarea în Docker, în special în Kubernetes, la un fișier este o idee proastă.

Următorul punct, aici vreau să vorbesc din nou despre acest lucru - deoarece atingem subiectul jurnalelor, ar fi bine să vorbim despre cum ar trebui să arate jurnalele pentru a face convenabil să lucrezi cu ele. După cum am spus, subiectul nu este direct legat de Kubernetes, dar se leagă foarte bine de subiectul DevOps. Pe tema culturii de dezvoltare și a prieteniei dintre aceste două departamente diferite - Dev și Ops, astfel încât toată lumea să fie confortabilă.

Aceasta înseamnă că, în mod ideal, astăzi, jurnalele ar trebui scrise în format JSON. Dacă aveți o aplicație proprie de neînțeles, care scrie jurnalele în formate de neînțeles pentru că introduceți un fel de tipărire sau ceva de genul ăsta, atunci este timpul să căutați pe Google un fel de framework, un fel de wrapper care vă permite să implementați logarea normală; activați acolo parametrii de înregistrare în JSON, deoarece JSON este un format simplu, analizarea acestuia este simplă.

Dacă JSON-ul dvs. nu funcționează conform unor criterii, nimeni nu știe ce, atunci cel puțin scrieți jurnalele într-un format care poate fi analizat. Aici, mai degrabă, merită să vă gândiți la faptul că, de exemplu, dacă rulați o grămadă de containere sau doar procesați cu nginx și fiecare are propriile setări de înregistrare, atunci probabil că va fi foarte incomod pentru dvs. analizați-le. Deoarece pentru fiecare instanță nouă nginx trebuie să vă scrieți propriul parser, deoarece ele scriu jurnalele diferit. Din nou, probabil a meritat să ne gândim să vă asigurați că toate aceste instanțe nginx au aceeași configurație de înregistrare și au scris toate jurnalele în mod absolut uniform. Același lucru este valabil pentru absolut toate aplicațiile.

În cele din urmă, vreau să adaug și combustibil la foc care, în mod ideal, ar trebui evitate jurnalele în format cu mai multe linii. Iată chestia, dacă ați lucrat vreodată cu colectori de jurnale, atunci cel mai probabil ați văzut ce vă promit aceștia, că pot lucra cu jurnalele cu mai multe linii, știu cum să le colecteze și așa mai departe. De fapt, în opinia mea, nici un singur colector de astăzi nu poate colecta jurnalele cu mai multe linii în mod normal, complet și fără erori. Într-un mod uman, astfel încât să fie convenabil și fără erori.

Cerințe pentru dezvoltarea unei aplicații în Kubernetes

Dar urmărirea stivei este întotdeauna jurnalele cu mai multe linii și cum să le evitați. Întrebarea aici este că un jurnal este o înregistrare a unui eveniment, iar stactrace nu este de fapt un jurnal. Dacă colectăm jurnalele și le punem undeva în Elasticsearch și apoi desenăm grafice din ele, construim niște rapoarte despre activitatea utilizatorilor pe site-ul dvs., atunci când obțineți o urmă de stivă, înseamnă că se întâmplă ceva neașteptat în aplicația dvs. Și are sens să încărcați automat o urmă de stivă undeva într-un sistem care le poate urmări.

Acesta este un software (același Sentry) care este creat special pentru a funcționa cu urmărirea stivei. Poate crea imediat sarcini automate, le poate atribui cuiva, poate alerta când apar stacttraces, grupează aceste stacttraces după un singur tip și așa mai departe. În principiu, nu prea are sens să vorbim despre stactraces atunci când vorbim despre jurnalele, deoarece acestea sunt, până la urmă, lucruri diferite cu scopuri diferite.

configurație

În continuare, vorbim despre configurarea în Kubernetes: ce să faceți cu ea și cum ar trebui să fie configurate aplicațiile din Kubernetes. În general, de obicei spun că Docker nu este despre containere. Toată lumea știe că Docker este despre containere, chiar și cei care nu au lucrat prea mult cu Docker. Repet, Docker nu este despre containere.

Docker, în opinia mea, este despre standarde. Și există standarde pentru practic orice: standarde pentru construirea aplicației dvs., standarde pentru instalarea aplicației dvs.

Cerințe pentru dezvoltarea unei aplicații în Kubernetes

Și acest lucru - l-am folosit înainte, tocmai a devenit deosebit de popular odată cu apariția containerelor - acest lucru se numește variabile ENV (de mediu), adică variabile de mediu care sunt în sistemul dvs. de operare. Aceasta este, în general, o modalitate ideală de a vă configura aplicația, deoarece dacă aveți aplicații în JAVA, Python, Go, Perl, Doamne ferește, și toți pot citi variabilele de gazdă a bazei de date, utilizatorul bazei de date, parola bazei de date, atunci este ideal. Aveți aplicații în patru limbi diferite configurate în planul bazei de date în același mod. Nu mai există configurații diferite.

Totul poate fi configurat folosind variabile ENV. Când vorbim despre Kubernetes, există o modalitate excelentă de a declara variabilele ENV chiar în Deployment. În consecință, dacă vorbim despre date secrete, atunci putem împinge imediat datele secrete din variabilele ENV (parole la baze de date etc.) într-un secret, să creăm un cluster secret și să indicăm în descrierea ENV din Deployment că nu declarăm direct valoarea acestei variabile și valoarea acestei variabile de parolă a bazei de date vor fi citite din secret. Acesta este comportamentul standard Kubernetes. Și aceasta este cea mai ideală opțiune pentru a vă configura aplicațiile. Doar la nivel de cod, din nou acest lucru se aplică dezvoltatorilor. Dacă sunteți DevOps, puteți întreba: „Băieți, vă rugăm să vă învățați aplicația să citească variabilele de mediu. Și toți vom fi fericiți.”

Dacă toată lumea din companie citește aceleași variabile de mediu numite, atunci este grozav. Ca să nu se întâmple ca unii să aştepte baza de date postgres, alţii să aştepte numele bazei de date, alţii să aştepte altceva, alţii să aştepte un dbn de vreun fel, astfel încât, în consecinţă, să existe uniformitate.

Problema vine atunci când aveți atât de multe variabile de mediu încât doar deschideți Deployment - și există cinci sute de linii de variabile de mediu. În acest caz, pur și simplu ați depășit variabilele de mediu - și nu mai trebuie să vă torturați. În acest caz, ar fi logic să începeți să utilizați configurațiile. Adică, antrenează-ți aplicația să folosească configurațiile.

Singura întrebare este că configurațiile nu sunt ceea ce crezi. Config.pi nu este o configurație convenabilă de utilizat. Sau unele configurații în formatul dvs., alternativ talentate - nici aceasta nu este configurația la care mă refer.

Ceea ce vorbesc este configurarea în formate acceptabile, adică de departe cel mai popular standard este standardul .yaml. Este clar cum să-l citești, este ușor de citit de om, este clar cum să-l citești din aplicație.

În consecință, pe lângă YAML, puteți, de asemenea, să utilizați, de exemplu, JSON, analizarea este aproximativ la fel de convenabilă ca și YAML în ceea ce privește citirea configurației aplicației de acolo. Este vizibil mai incomod pentru oameni să citească. Puteți încerca formatul, a la ini. Este destul de convenabil de citit, din punct de vedere uman, dar poate fi incomod să îl procesezi automat, în sensul că, dacă vrei vreodată să-ți generezi propriile configurații, formatul ini poate fi deja incomod de generat.

Dar, în orice caz, indiferent de formatul pe care îl alegeți, ideea este că din punct de vedere Kubernetes este foarte convenabil. Puteți pune întreaga configurație în Kubernetes, în ConfigMap. Și apoi luați această configmap și cereți-o să fie montată în interiorul podului dvs. într-un director specific, unde aplicația dvs. va citi configurația din această configurație ca și cum ar fi doar un fișier. Aceasta, de fapt, este ceea ce este bine să faci atunci când ai o mulțime de opțiuni de configurare în aplicația ta. Sau este doar un fel de structură complexă, există cuibărit.

Dacă aveți o configurație, atunci puteți foarte bine să vă învățați aplicația, de exemplu, să urmăriți automat modificările din fișierul în care este montată configurația și, de asemenea, să vă reîncărcați automat aplicația atunci când configurațiile se schimbă. Aceasta ar fi, în general, o opțiune ideală.

Din nou, am vorbit deja despre asta - informațiile secrete nu sunt în configurația, informațiile secrete nu sunt în variabile, informațiile secrete nu sunt în secrete. De acolo, conectează aceste informații secrete cu diplomația. De obicei stocăm toate descrierile obiectelor Kubernetes, implementărilor, configmaps-urilor, serviciilor în git. În consecință, introducerea parolei în baza de date în git, chiar dacă este git-ul tău, pe care îl ai intern în companie, este o idee proastă. Pentru că, cel puțin, git își amintește totul și pur și simplu ștergerea parolelor de acolo nu este atât de ușoară.

Control medical

Următorul punct este chestia asta numită verificarea sănătății. În general, o verificare a stării de sănătate este pur și simplu să verifice dacă aplicația dvs. funcționează. În același timp, cel mai adesea vorbim despre anumite aplicații web, pentru care, în consecință, din punct de vedere al verificării sănătății (este mai bine să nu traducem aici și mai departe) aceasta va fi o adresă URL specială, pe care o procesează ca un standard, de obicei o fac /health.

Atunci când accesăm această adresă URL, în consecință, aplicația noastră spune fie „da, bine, totul este în regulă pentru mine, 200” sau „nu, totul nu este în regulă cu mine, vreo 500”. În consecință, dacă aplicația noastră nu este http, nu este o aplicație web, acum vorbim despre un fel de demon, ne putem da seama cum să facem verificări de sănătate. Adică nu este necesar, dacă aplicația nu este http, atunci totul funcționează fără un control de sănătate și acest lucru nu se poate face în niciun fel. Puteți actualiza periodic unele informații din fișier, puteți veni cu o comandă specială pentru demonul dvs., cum ar fi, daemon status, care va spune „da, totul este bine, demonul funcționează, este viu”.

Pentru ce este? Primul și cel mai evident lucru este probabil motivul pentru care este nevoie de o verificare a stării de sănătate - pentru a înțelege că aplicația funcționează. Vreau să spun, este doar o prostie, când este până acum, pare că funcționează, așa că poți fi sigur că funcționează. Și se dovedește că aplicația rulează, containerul rulează, instanța funcționează, totul este în regulă - și atunci utilizatorii au tăiat deja toate numerele de telefon de la suport tehnic și spun „ce ești..., tu am adormit, nimic nu merge.”

O verificare a stării de sănătate este doar o astfel de modalitate de a vedea din punctul de vedere al utilizatorului că funcționează. Una dintre metode. Să o punem așa. Din punctul de vedere al Kubernetes, aceasta este și o modalitate de a înțelege când pornește aplicația, deoarece înțelegem că există o diferență între momentul în care containerul a fost lansat, creat și pornit și când a fost lansată aplicația direct în acest container. Pentru că dacă luăm o aplicație Java medie și încercăm să o lansăm în dock, atunci timp de patruzeci de secunde, sau chiar un minut, sau chiar zece, poate începe foarte bine. În acest caz, puteți măcar să bateți în porturile sale, nu va răspunde acolo, adică nu este încă pregătit să primească trafic.

Din nou, cu ajutorul unei verificări de sănătate și cu ajutorul faptului că ne întoarcem aici, putem înțelege în Kubernetes că nu numai containerul a crescut în aplicație, dar aplicația în sine a pornit, ea răspunde deja la verificarea sănătății, ceea ce înseamnă că putem trimite trafic acolo.

Cerințe pentru dezvoltarea unei aplicații în Kubernetes

Ceea ce vorbesc acum se numește teste de pregătire/live în Kubernetes, în consecință, testele noastre de pregătire sunt responsabile pentru disponibilitatea aplicației în echilibrare. Adică, dacă în aplicație se efectuează teste de pregătire, atunci totul este ok, traficul clientului merge către aplicație. Dacă testele de pregătire nu sunt efectuate, atunci aplicația pur și simplu nu participă, această instanță anume nu participă la echilibrare, este eliminată de la echilibrare și traficul clientului nu circulă. În consecință, testele Liveness în Kubernetes sunt necesare, astfel încât, dacă aplicația se blochează, poate fi repornită. Dacă testul de viață nu funcționează pentru o aplicație care este declarată în Kubernetes, atunci aplicația nu este doar eliminată de la echilibrare, ci este repornită.

Și iată un punct important pe care aș dori să-l menționez: din punct de vedere practic, testul de pregătire este de obicei folosit mai des și este mai des necesar decât testul de viață. Adică, pur și simplu declararea fără gânduri atât a testelor de pregătire, cât și a testelor de viață, pentru că Kubernetes poate face asta și haideți să folosim tot ce poate face, nu este o idee foarte bună. O să explic de ce. Pentru că punctul numărul doi în testare este că ar fi o idee bună să verificați serviciul de bază în controalele dumneavoastră de sănătate. Asta înseamnă că dacă ai o aplicație web care oferă unele informații, care la rândul lor, în mod firesc, trebuie să ia de undeva. Într-o bază de date, de exemplu. Ei bine, salvează informațiile care vin în acest API REST în aceeași bază de date. Apoi, în consecință, dacă verificarea dvs. de sănătate răspunde la fel ca slashhealth contactat, aplicația spune „200, bine, totul este în regulă” și, în același timp, baza de date a aplicației dvs. este inaccesibilă, iar aplicația de verificare a stării de sănătate spune „200, bine, totul este în regulă. ” – Acesta este un control de sănătate prost. Nu așa ar trebui să funcționeze.

Adică, aplicația ta, atunci când îi vine o solicitare /health, nu răspunde doar „200, ok”, mai întâi merge, de exemplu, la baza de date, încearcă să se conecteze la ea, face ceva foarte simplu acolo, cum ar fi selectați unul, doar verifică dacă există o conexiune în baza de date și puteți interoga baza de date. Dacă toate acestea au avut succes, atunci răspunsul este „200, ok”. Dacă nu are succes, spune că există o eroare, baza de date este indisponibilă.

Prin urmare, în acest sens, revin din nou la testele de pregătire/Vietate – de ce cel mai probabil aveți nevoie de un test de pregătire, dar un test de viață este în discuție. Pentru că dacă descrii controalele de sănătate exact așa cum tocmai am spus, atunci se va dovedi că nu este disponibil în partea de instanțăв или со всех instanceîntr-o bază de date, de exemplu. Când ați declarat un test de pregătire, controalele noastre de sănătate au început să eșueze și, în consecință, toate aplicațiile din care baza de date nu este accesibilă, pur și simplu sunt oprite de la echilibrare și, de fapt, „se blochează” doar într-o stare neglijată și așteaptă ca bazele lor de date să fie muncă.

Dacă am declarat un test de viabilitate, atunci imaginați-vă că baza noastră de date s-a spart, iar în Kubernetes jumătate din tot începe să repornească, deoarece testul de viață eșuează. Aceasta înseamnă că trebuie să reporniți. Nu este deloc ceea ce îți dorești, chiar am avut experiență personală în practică. Aveam o aplicație de chat care a fost scrisă în JS și introdusă într-o bază de date Mongo. Și problema a fost că la începutul lucrării mele cu Kubernetes am descris gradul de pregătire, vitalitatea testelor pe principiul că Kubernetes o poate face, așa că îl vom folosi. În consecință, la un moment dat, Mongo a devenit puțin „plictisitor” și eșantionul a început să eșueze. În consecință, conform testului de ploaie, păstăile au început să „ucide”.

După cum înțelegeți, atunci când sunt „omorâți”, acesta este un chat, adică există o mulțime de conexiuni de la clienți care se agăță de el. De asemenea, sunt „omorâți” - nu, nu clienți, doar conexiuni - nu toți în același timp, și datorită faptului că nu sunt uciși în același timp, unii mai devreme, alții mai târziu, nu încep la același timp timp. În plus, aleatoriu standard, nu putem prezice cu precizie de milisecunde ora de pornire a aplicației de fiecare dată, așa că o fac o singură instanță la un moment dat. Un infospot se ridică, se adaugă la echilibrare, toți clienții vin acolo, nu poate suporta o asemenea încărcătură, pentru că este singur și, aproximativ, sunt o duzină care lucrează acolo și cade. Următorul se ridică, toată sarcina este asupra lui, cade și el. Ei bine, aceste căderi continuă să cadă în cascadă. În cele din urmă, cum a fost rezolvat acest lucru - a trebuit doar să oprim strict traficul utilizatorilor către această aplicație, să lăsăm toate instanțele să se ridice și apoi să începem tot traficul utilizatorilor simultan, astfel încât să fie deja distribuit între toate cele zece instanțe.

Dacă nu ar fi fost anunțat acest test de viață, care ar forța totul să repornească, aplicația s-ar fi descurcat bine. Dar totul, de la echilibrare, este dezactivat pentru noi, deoarece bazele de date sunt inaccesibile și toți utilizatorii au „căzut”. Apoi, când această bază de date devine disponibilă, totul este inclus în echilibrare, dar aplicațiile nu trebuie să înceapă din nou și nu este nevoie să pierdeți timp și resurse în acest sens. Toate sunt deja aici, sunt pregătite pentru trafic, așa că traficul se deschide, totul este în regulă - aplicația este la locul său, totul continuă să funcționeze.

Prin urmare, testele de pregătire și de viață sunt diferite, chiar și mai mult, teoretic puteți face diferite controale de sănătate, un tip de raze, un tip liv, de exemplu, și să verificați diferite lucruri. În timpul testelor de pregătire, verificați-vă backend-urile. Și la un test de viață, de exemplu, nu verificați din punctul de vedere că testul de viață este în general doar o aplicație care răspunde, dacă este capabilă să răspundă deloc.

Pentru că testul de viață, în general, este atunci când suntem „blocați”. A început o buclă nesfârșită sau altceva - și nu mai sunt procesate cereri. Prin urmare, are sens să le separăm chiar și să implementăm o logică diferită în ele.

Referitor la ce trebuie sa raspunzi cand faci un test, cand faci controale de sanatate. Este doar o durere. Cei care sunt familiarizați cu asta probabil vor râde - dar serios, am văzut în viața mea servicii care răspund „200” în XNUMX% din cazuri. Adică cine are succes. Dar, în același timp, în corpul răspunsului scriu „o astfel de eroare”.

Adică, starea răspunsului vine la tine - totul are succes. Dar, în același timp, trebuie să analizați corpul, deoarece corpul spune „îmi pare rău, cererea s-a încheiat cu o eroare” și aceasta este doar realitatea. Am văzut asta în viața reală.

Și pentru ca unii oameni să nu li se pară amuzant, iar alții să fie foarte dureros, merită totuși să respectați o regulă simplă. În controalele de sănătate și, în principiu, atunci când lucrați cu aplicații web.

Dacă totul a mers bine, atunci răspundeți cu răspunsul a două sute. În principiu, orice răspuns de două sutemi ți se va potrivi. Dacă citești foarte bine ragsy și știi că unele stări de răspuns sunt diferite de altele, răspunde cu cele potrivite: 204, 5, 10, 15, orice. Dacă nu este foarte bun, atunci doar „două zero zero”. Dacă totul merge prost și controlul de sănătate nu răspunde, atunci răspundeți cu orice cinci sutimi. Din nou, dacă înțelegeți cum să răspundeți, cât de diferite stări de răspuns diferă unele de altele. Dacă nu înțelegeți, atunci 502 este opțiunea dvs. de a răspunde la controalele de sănătate dacă ceva nu merge bine.

Acesta este un alt punct, vreau să revin puțin despre verificarea serviciilor de bază. Dacă începeți, de exemplu, să verificați toate serviciile de bază care stau în spatele aplicației dvs. - totul în general. Ceea ce obținem din punctul de vedere al arhitecturii de microservicii, avem un astfel de concept ca „cuplarea scăzută” - adică atunci când serviciile dvs. sunt minime dependente unele de altele. Dacă unul dintre ele eșuează, toate celelalte fără această funcționalitate vor continua să funcționeze. Unele dintre funcționalități pur și simplu nu funcționează. În consecință, dacă legați toate controalele de sănătate unul de celălalt, atunci veți sfârși cu un singur lucru care eșuează în infrastructură și, pentru că a căzut, toate controalele de sănătate ale tuturor serviciilor încep și ele să eșueze - și există mai multă infrastructură în general pentru întreaga arhitectură de microservicii nr. Totul s-a întunecat acolo.

Prin urmare, vreau să repet acest lucru din nou că trebuie să verificați serviciile de bază, acelea fără de care aplicația dvs. în sută la sută din cazuri nu își poate face treaba. Adică, este logic că dacă ai un API REST prin care utilizatorul salvează în baza de date sau preia din baza de date, atunci în absența unei baze de date, nu poți garanta lucrul cu utilizatorii tăi.

Dar dacă utilizatorii dvs., atunci când îi scoateți din baza de date, sunt îmbogățiți suplimentar cu alte metadate, dintr-un alt backend, pe care le introduceți înainte de a trimite un răspuns către frontend - și acest backend nu este disponibil, aceasta înseamnă că vă oferiți răspunde fără nicio parte a metadatelor.

În continuare, avem și una dintre problemele dureroase la lansarea aplicațiilor.

De fapt, acest lucru nu se aplică doar Kubernetes în general, sa întâmplat că cultura unui fel de dezvoltare în masă și DevOps în special au început să se răspândească în același timp cu Kubernetes. Prin urmare, în general, se dovedește că trebuie să închideți cu grație aplicația fără Kubernetes. Chiar și înainte de Kubernetes, oamenii făceau asta, dar odată cu apariția Kubernetes, am început să vorbim despre asta în masă.

Oprire grațioasă

În general, ce este Graceful Shutdown și de ce este necesar? Este vorba despre atunci când aplicația dvs. se blochează dintr-un motiv oarecare, trebuie să faceți app stop - sau primești, de exemplu, un semnal de la sistemul de operare, aplicația ta trebuie să-l înțeleagă și să facă ceva în privința asta. Cel mai rău scenariu, desigur, este atunci când aplicația dvs. primește un SIGTERM și este de genul „SIGTERM, să rămânem, să lucrăm, să nu faceți nimic”. Aceasta este o opțiune de-a dreptul proastă.

Cerințe pentru dezvoltarea unei aplicații în Kubernetes

O opțiune aproape la fel de proastă este atunci când aplicația dvs. primește un SIGTERM și este ca „au spus segterm, asta înseamnă că terminăm, nu am văzut, nu știu nicio solicitare de utilizator, nu știu ce fel de solicitările la care lucrez acum, au spus SIGTERM, asta înseamnă că terminăm " Aceasta este, de asemenea, o opțiune proastă.

Care varianta este buna? Primul punct este de a lua în considerare finalizarea operațiunilor. O opțiune bună este ca serverul dvs. să țină cont de ceea ce face dacă primește un SIGTERM.

SIGTERM este o oprire uşoară, este special concepută, poate fi interceptată la nivel de cod, poate fi procesată, să spunem că acum, stai, mai întâi vom termina munca pe care o avem, apoi vom ieşi.

Din perspectiva Kubernetes, așa arată. Când îi spunem unui pod care rulează în clusterul Kubernetes, „te rugăm să oprești, pleci” sau suntem reporniți sau apare o actualizare când Kubernetes recreează podurile, Kubernetes trimite același mesaj SIGTERM către pod, așteaptă ceva timp, și , acesta este timpul în care așteaptă, este și configurat, există un parametru atât de special în diplome și se numește Graceful ShutdownTimeout. După cum înțelegeți, nu se numește așa degeaba și nu degeaba vorbim despre asta acum.

Acolo putem spune în mod specific cât timp trebuie să așteptăm între momentul în care trimitem SIGTERM la aplicație și când înțelegem că aplicația pare să fi înnebunit pentru ceva sau este „blocat” și nu se va termina - și trebuie să trimite-l SIGKILL, adică să-și finalizeze munca. Adică, în consecință, avem un fel de demon care rulează, el procesează operațiuni. Înțelegem că, în medie, operațiunile noastre la care lucrează demonul nu durează mai mult de 30 de secunde o dată. În consecință, când sosește SIGTERM, înțelegem că demonul nostru poate, cel mult, să termine la 30 de secunde după SIGTERM. Îl scriem, de exemplu, 45 de secunde pentru orice eventualitate și spunem că SIGTERM. După aceea așteptăm 45 de secunde. În teorie, în acest timp demonul ar fi trebuit să-și termine munca și să se încheie singur. Dar dacă dintr-o dată nu s-a putut, înseamnă că cel mai probabil este blocat - nu ne mai procesează cererile în mod normal. Și în 45 de secunde poți, de fapt, să-l închizi în siguranță.

Și aici, de fapt, chiar și 2 aspecte pot fi luate în considerare. În primul rând, înțelegeți că dacă ați primit o solicitare, ați început să lucrați cu ea cumva și nu ați dat un răspuns utilizatorului, dar ați primit SIGTERM, de exemplu. Este logic să o rafinați și să dați un răspuns utilizatorului. Acesta este punctul numărul unu în acest sens. Punctul numărul doi aici este că, dacă vă scrieți propria aplicație, în general, construiți arhitectura în așa fel încât să primiți o solicitare pentru aplicația dvs., apoi începeți să lucrați, începeți să descărcați fișiere de undeva, să descărcați o bază de date și altele. Acea. În general, utilizatorul dvs., solicitarea dvs. se blochează timp de o jumătate de oră și așteaptă să îi răspundeți - apoi, cel mai probabil, trebuie să lucrați la arhitectură. Adică, ține cont chiar și de bunul simț că, dacă operațiunile tale sunt scurte, atunci are sens să ignori SIGTERM și să-l modifici. Dacă operațiunile dumneavoastră sunt lungi, atunci nu are sens să ignorați SIGTERM în acest caz. Este logic să reproiectăm arhitectura pentru a evita operațiuni atât de lungi. Pentru ca utilizatorii să nu rămână în jur și să aștepte. Nu știu, faceți un fel de websocket acolo, faceți cârlige inverse pe care serverul dvs. le va trimite deja clientului, orice altceva, dar nu forțați utilizatorul să blocheze o jumătate de oră și așteptați doar o sesiune până când veți raspunde-i. Pentru că este imprevizibil unde s-ar putea rupe.

Când aplicația dvs. se încheie, ar trebui să furnizați un cod de ieșire adecvat. Adică, dacă aplicației tale i s-a cerut să se închidă, să se oprească și s-a putut opri în mod normal, atunci nu trebuie să returnezi un fel de cod de ieșire 1,5,255 și așa mai departe. Orice lucru care nu este cod zero, cel puțin în sistemele Linux, sunt sigur de acest lucru, este considerat nereușit. Adică, se consideră că cererea dumneavoastră în acest caz s-a încheiat cu o eroare. În consecință, într-un mod amiabil, dacă cererea dvs. a fost finalizată fără eroare, spuneți 0 la ieșire. Dacă aplicația dvs. eșuează dintr-un motiv oarecare, spuneți non-0 în rezultat. Și puteți lucra cu aceste informații.

Și ultima variantă. Este rău când utilizatorul dvs. trimite o solicitare și se blochează timp de o jumătate de oră în timp ce o procesați. Dar, în general, aș dori să spun și despre ce merită în general din partea clientului. Nu contează dacă aveți o aplicație mobilă, front-end etc. Este necesar să țineți cont de faptul că, în general, sesiunea utilizatorului poate fi încheiată, orice se poate întâmpla. O solicitare poate fi trimisă, de exemplu, subprocesată și nici un răspuns returnat. Frontend-ul sau aplicația dvs. mobilă - orice frontend în general, să o spunem așa - ar trebui să țină cont de acest lucru. Dacă lucrați cu websocket-uri, aceasta este, în general, cea mai mare durere pe care am avut-o vreodată.

Când dezvoltatorii unor chat-uri obișnuite nu știu asta, se pare că websocket-ul se poate rupe. Pentru ei, când se întâmplă ceva la proxy, doar schimbăm configurația și face o reîncărcare. Desigur, toate sesiunile de lungă durată sunt rupte în acest caz. Dezvoltatorii vin în fugă la noi și ne spun: „Băieți, ce faceți, chat-ul s-a întrerupt pentru toți clienții noștri!” Le spunem: „Ce faceți? Clienții dvs. nu se pot reconecta? Ei spun: „Nu, avem nevoie ca sesiunile să nu fie rupte”. Pe scurt, aceasta este de fapt o prostie. Partea clientului trebuie luată în considerare. Mai ales, după cum spun, cu sesiuni de lungă durată, cum ar fi websocket-urile, se poate rupe și, neobservat de utilizator, trebuie să poți reinstala astfel de sesiuni. Și atunci totul este perfect.

Ресурсы

De fapt, aici vă voi spune doar o poveste clară. Din nou din viața reală. Cel mai rău lucru pe care l-am auzit vreodată despre resurse.

Resurse în acest caz, mă refer la un fel de solicitări, limite pe care le puteți pune pe pod-uri din clusterele dvs. Kubernetes. Cel mai amuzant lucru pe care l-am auzit de la un dezvoltator... Unul dintre colegii mei dezvoltatori de la un loc de muncă anterior a spus odată: „Aplicația mea nu va începe în cluster”. M-am uitat să văd că nu începe, dar fie nu se încadra în resurse, fie stabiliseră limite foarte mici. Pe scurt, aplicația nu poate porni din cauza resurselor. Eu spun: „Nu va începe din cauza resurselor, tu decizi de cât ai nevoie și stabilești o valoare adecvată.” El spune: „Ce fel de resurse?” Am început să-i explic că trebuie stabilite Kubernetes, limite la cereri și bla, bla, bla. Bărbatul a ascultat cinci minute, a dat din cap și a spus: „Am venit aici să lucrez ca dezvoltator, nu vreau să știu nimic despre nicio resursă. Am venit aici să scriu cod și atât.” Este trist. Acesta este un concept foarte trist din punctul de vedere al dezvoltatorului. Mai ales în lumea modernă, ca să spunem așa, a devopilor progresivi.

De ce sunt necesare resurse? Există 2 tipuri de resurse în Kubernetes. Unele se numesc cereri, altele se numesc limite. Prin resurse vom înțelege că, practic, există întotdeauna doar două restricții de bază. Adică, limitele de timp ale CPU și limitele RAM pentru un container care rulează în Kubernetes.

O limită plasează o limită superioară a modului în care o resursă poate fi utilizată în aplicația dvs. Adică, în consecință, dacă spui 1 GB RAM în limite, atunci aplicația ta nu va putea folosi mai mult de 1 GB RAM. Și dacă brusc vrea și încearcă să facă acest lucru, atunci un proces numit oom killer, fără memorie, adică va veni și va ucide aplicația - adică va reporni pur și simplu. Aplicațiile nu vor reporni pe baza procesorului. În ceea ce privește CPU, dacă o aplicație încearcă să folosească mult, mai mult decât este specificat în limite, procesorul va fi pur și simplu selectat cu strictețe. Acest lucru nu duce la reporniri. Aceasta este limita - aceasta este limita superioară.

Și există o cerere. O solicitare este modul în care Kubernetes înțelege modul în care nodurile din clusterul dvs. Kubernetes sunt populate cu aplicații. Adică, o solicitare este un fel de commit al aplicației dvs. Spune ce vreau să folosesc: „Aș dori să rezervi atât de mult CPU și atât de multă memorie pentru mine.” O analogie atât de simplă. Dacă avem un nod care are, nu știu, 8 procesoare în total. Și ajunge acolo un pod, ale cărui solicitări spun 1 CPU, ceea ce înseamnă că nodul mai are 7 CPU-uri. Adică, în consecință, de îndată ce 8 poduri ajung la acest nod, fiecare dintre ele având 1 CPU în cererile lor, nodul, ca și cum din punctul de vedere al Kubernetes, a rămas fără CPU și mai multe pod-uri cu cereri nu pot fi lansat pe acest nod. Dacă toate nodurile rămân fără CPU, atunci Kubernetes va începe să spună că nu există noduri potrivite în cluster pentru a rula pod-urile, deoarece procesorul s-a epuizat.

De ce sunt necesare cereri și de ce fără solicitări, cred că nu este nevoie să lansăm nimic în Kubernetes? Să ne imaginăm o situație ipotetică. Îți lansezi aplicația fără solicitări, Kubernetes nu știe cât de mult ai, la ce noduri o poți împinge. Ei bine, el împinge, împinge, împinge pe noduri. La un moment dat, veți începe să obțineți trafic către aplicația dvs. Și una dintre aplicații începe brusc să folosească resurse până la limitele pe care le are conform limitelor. Se pare că mai există o aplicație în apropiere și are nevoie și de resurse. Nodul începe de fapt să rămână fizic fără resurse, de exemplu, OP. Nodul începe de fapt să rămână fizic fără resurse, de exemplu, memoria cu acces aleatoriu (RAM). Când un nod rămâne fără putere, în primul rând docker-ul nu va mai răspunde, apoi cubetul, apoi sistemul de operare. Pur și simplu vor deveni inconștienți și TOTUL va înceta cu siguranță să funcționeze pentru tine. Adică, acest lucru va duce la blocarea nodului și va trebui să-l reporniți. Pe scurt, situația nu este prea bună.

Și când aveți solicitări, limitele nu sunt foarte diferite, cel puțin nu de multe ori mai mult decât limitele sau solicitările, atunci puteți avea o umplere atât de normală și rațională a aplicațiilor în nodurile clusterelor Kubernetes. În același timp, Kubernetes este aproximativ conștient de cât de mult din ceea ce pune unde, cât de mult din ceea ce este folosit unde. Adică este doar un astfel de moment. Este important să-l înțelegi. Și este important să controlați că acest lucru este indicat.

Stocare a datelor

Următorul nostru punct este despre stocarea datelor. Ce să faci cu ele și, în general, ce să faci cu persistența în Kubernetes?

Cred, din nou, în interiorul nostru Scoala de seara, a existat un subiect despre baza de date din Kubernetes. Și mie mi se pare că știu aproximativ ce ți-au spus colegii tăi când au fost întrebați: „Este posibil să rulezi o bază de date în Kubernetes?” Din anumite motive, mi se pare că colegii dumneavoastră ar fi trebuit să vă spună că dacă vă puneți întrebarea dacă este posibil să rulați o bază de date în Kubernetes, atunci este imposibil.

Logica aici este simplă. Pentru orice eventualitate, vă voi explica încă o dată, dacă sunteți un tip cu adevărat cool care poate construi un sistem destul de tolerant la erori de stocare în rețea distribuită, înțelegeți cum să potriviți o bază de date în acest caz, cum ar trebui să funcționeze cloud native în containere într-o bază de date în general. Cel mai probabil, nu aveți nicio întrebare despre cum să-l rulați. Dacă aveți o astfel de întrebare și doriți să vă asigurați că totul se desfășoară și rămâne până la moarte în producție și nu cade niciodată, atunci acest lucru nu se întâmplă. Sunteți garantat să vă împușcați în picior cu această abordare. Prin urmare, este mai bine să nu o facă.

Ce ar trebui să facem cu datele pe care aplicația noastră ar dori să le stocheze, unele imagini pe care utilizatorii le încarcă, unele lucruri pe care aplicația noastră le generează în timpul funcționării, la pornire, de exemplu? Ce să faci cu ei în Kubernetes?

În general, în mod ideal, da, desigur, Kubernetes este foarte bine conceput și a fost în general conceput inițial pentru aplicații fără stat. Adică pentru acele aplicații care nu stochează deloc informații. Acest lucru este ideal.

Dar, desigur, opțiunea ideală nu există întotdeauna. Şi ce dacă? Primul și cel mai simplu punct este să luați un fel de S3, doar nu unul făcut în casă, ceea ce nu este clar cum funcționează, ci de la un furnizor. Un furnizor bun, normal - și învață-ți aplicația să folosească S3. Adică, atunci când utilizatorul dvs. dorește să încarce un fișier, spuneți „aici, vă rog, încărcați-l pe S3”. Când dorește să-l primească, spune: „Iată un link către S3 înapoi și ia-l de aici.” Acest lucru este ideal.

Dacă dintr-o dată din anumite motive această opțiune ideală nu este potrivită, aveți o aplicație pe care nu ați scris-o, nu o dezvoltați sau este un fel de moștenire teribilă, nu poate folosi protocolul S3, dar trebuie să funcționeze cu directoare locale în foldere locale. Luați ceva mai mult sau mai puțin simplu, implementați Kubernetes. Adică să-l îngrădești imediat pe Ceph pentru niște sarcini minime, mi se pare o idee proastă. Pentru că Ceph, desigur, este bun și la modă. Dar dacă nu înțelegi cu adevărat ce faci, atunci odată ce ai pus ceva pe Ceph, poți foarte ușor și pur și simplu să nu-l mai scoți niciodată de acolo. Pentru că, după cum știți, Ceph stochează datele în clusterul său în formă binară, și nu sub formă de fișiere simple. Prin urmare, dacă dintr-o dată clusterul Ceph se defectează, atunci există o probabilitate completă și mare să nu vă mai obțineți niciodată datele de acolo.

Vom avea un curs despre Ceph, poți familiarizați-vă cu programul și trimiteți o cerere.

Prin urmare, este mai bine să faceți ceva simplu, cum ar fi un server NFS. Kubernetes poate lucra cu ele, puteți monta un director sub un server NFS - aplicația dvs. este la fel ca un director local. În același timp, desigur, trebuie să înțelegeți că, din nou, trebuie să faceți ceva cu NFS-ul dvs., trebuie să înțelegeți că uneori poate deveni inaccesibil și să vă gândiți la întrebarea ce veți face în acest caz. Poate ar trebui să fie făcută o copie de rezervă undeva pe o mașină separată.

Următorul punct despre care am vorbit este ce trebuie să faceți dacă aplicația dvs. generează unele fișiere în timpul funcționării. De exemplu, atunci când pornește, generează un fișier static, care se bazează pe unele informații pe care aplicația le primește doar în momentul lansării. Ce moment! Dacă nu există prea multe astfel de date, atunci nu trebuie să vă deranjați deloc, instalați această aplicație pentru dvs. și lucrați. Singura întrebare aici este ce, uite. Foarte des, tot felul de sisteme vechi, cum ar fi WordPress și așa mai departe, în special cu unele pluginuri inteligente modificate, dezvoltatori PHP inteligenți, ei știu adesea cum să facă astfel încât să genereze un fel de fișier pentru ei înșiși. În consecință, unul generează un fișier, al doilea generează un al doilea fișier. Sunt diferite. Echilibrarea are loc în clusterul Kubernetes al clienților pur și simplu întâmplător. În consecință, se dovedește că ei nu știu cum să lucreze împreună, de exemplu. Unul oferă o informație, celălalt oferă utilizatorului o altă informație. Acesta este ceva ce trebuie evitat. Adică, în Kubernetes, tot ceea ce lansați este garantat că va putea funcționa în mai multe instanțe. Pentru că Kubernetes este un lucru în mișcare. În consecință, poate muta orice, oricând dorește, fără să întrebe pe nimeni. Prin urmare, trebuie să te bazezi pe asta. Tot ce este lansat într-o singură instanță va eșua mai devreme sau mai târziu. Cu cât ai mai multe rezervări, cu atât mai bine. Dar din nou, zic, dacă aveți câteva astfel de fișiere, atunci le puteți pune chiar sub tine, cântăresc o cantitate mică. Dacă sunt puțin mai multe, probabil că nu ar trebui să le împingeți în interiorul recipientului.

Aș sfătui că există un lucru atât de minunat în Kubernetes, puteți folosi volumul. În special, există un volum de tip empty dir. Adică, Kubernetes va crea automat un director în directoarele sale de servicii de pe serverul de unde ați început. Și ți-l va da ca să-l poți folosi. Există un singur punct important. Adică, datele dumneavoastră nu vor fi stocate în interiorul containerului, ci mai degrabă pe gazda pe care rulați. Mai mult, Kubernetes poate controla astfel de dir-uri goale în configurație normală și este capabil să controleze dimensiunea lor maximă și să nu permită depășirea acesteia. Singurul aspect este că ceea ce ați scris în directorul gol nu se pierde în timpul repornirii podului. Adică, dacă podul tău cade din greșeală și se ridică din nou, informațiile din directorul gol nu vor merge nicăieri. Îl poate folosi din nou la un nou început - și asta e bine. Dacă podul tău pleacă de undeva, atunci în mod natural va pleca fără date. Adică, de îndată ce pod-ul din nodul în care a fost lansat cu directorul gol dispare, directorul gol este șters.

Ce altceva este bun la directorul gol? De exemplu, poate fi folosit ca cache. Să ne imaginăm că aplicația noastră generează ceva din mers, îl oferă utilizatorilor și o face mult timp. Prin urmare, aplicația, de exemplu, o generează și o dă utilizatorilor și, în același timp, o stochează undeva, astfel încât data viitoare când utilizatorul vine pentru același lucru, va fi mai rapid să o dea imediat generată. Directorul gol poate fi solicitat lui Kubernetes să creeze în memorie. Și astfel, cache-urile dvs. pot funcționa în general la viteza fulgerului - în ceea ce privește viteza de acces la disc. Adică ai un director gol în memorie, în SO este stocat în memorie, dar pentru tine, pentru utilizatorul din interiorul podului, arată ca doar un director local. Nu aveți nevoie de aplicație pentru a preda în mod special vreo magie. Doar luați și puneți direct fișierul într-un director, dar, de fapt, în memoria sistemului de operare. Aceasta este, de asemenea, o caracteristică foarte convenabilă în ceea ce privește Kubernetes.

Ce probleme are Minio? Principala problemă cu Minio este că, pentru ca acest lucru să funcționeze, trebuie să ruleze undeva și trebuie să existe un fel de sistem de fișiere, adică stocare. Și aici întâlnim aceleași probleme pe care le are Ceph. Adică, Minio trebuie să-și stocheze fișierele undeva. Este pur și simplu o interfață HTTP pentru fișierele dvs. Mai mult decât atât, funcționalitatea este în mod clar mai slabă decât cea a lui S3 de la Amazon. Anterior, nu a putut autoriza corect utilizatorul. Acum, din câte știu eu, poate deja să creeze găleți cu diferite autorizații, dar din nou, mi se pare că principala problemă este, ca să spun așa, sistemul de stocare de bază la minimum.

Cum afectează directorul gol din memorie limitele? Nu afectează în niciun fel limitele. Se află în memoria gazdei și nu în memoria containerului tău. Adică, containerul dvs. nu vede directorul gol din memorie ca parte a memoriei ocupate. Gazda vede asta. În consecință, da, din punctul de vedere al kubernetes, atunci când începeți să utilizați acest lucru, ar fi bine să înțelegeți că vă dedicați o parte din memorie directorului gol. Și, în consecință, înțelegeți că memoria se poate epuiza nu numai din cauza aplicațiilor, ci și pentru că cineva scrie în aceste directoare goale.

Cloudnativitatea

Iar subiectul secundar final este ce este Cloudnative. De ce este nevoie? Cloudnativeness și așa mai departe.

Adică acele aplicații care sunt capabile și scrise pentru a funcționa într-o infrastructură cloud modernă. Dar, de fapt, Cloudnative are un alt astfel de aspect. Că aceasta nu este doar o aplicație care ține cont de toate cerințele unei infrastructuri moderne de cloud, dar știe și cum să lucreze cu această infrastructură modernă de cloud, profită de avantajele și dezavantajele faptului că funcționează în acești cloud. Nu treceți peste bord și lucrați în nor, ci profitați de beneficiile lucrului în cloud.

Cerințe pentru dezvoltarea unei aplicații în Kubernetes

Să luăm Kubernetes drept exemplu. Aplicația dvs. rulează în Kubernetes. Aplicația dvs. poate oricând, sau mai degrabă administratorii aplicației dvs., pot oricând să creeze un cont de serviciu. Adică, un cont pentru autorizare în Kubernetes însuși pe serverul său. Adăugați câteva drepturi de care avem nevoie acolo. Și puteți accesa Kubernetes din aplicația dvs. Ce poți face așa? De exemplu, de la aplicație, primiți date despre locul în care sunt situate celelalte aplicații ale dvs., alte instanțe similare și împreună cumva grupați deasupra Kubernetes, dacă există o astfel de nevoie.

Din nou, am avut literalmente un caz recent. Avem un controlor care monitorizează coada. Și când unele sarcini noi apar în această coadă, aceasta se duce la Kubernetes - iar în interiorul Kubernetes creează un nou pod. Oferă acestui pod o sarcină nouă și, în cadrul acestui pod, podul îndeplinește sarcina, trimite un răspuns controlerului însuși, iar controlerul face apoi ceva cu aceste informații. De exemplu, adaugă o bază de date. Adică, din nou, acesta este un plus al faptului că aplicația noastră rulează în Kubernetes. Putem folosi însăși funcționalitatea încorporată Kubernetes pentru a ne extinde cumva și a face funcționalitatea aplicației noastre mai convenabilă. Adică, nu ascunde un fel de magie despre cum să lansezi o aplicație, cum să lansezi un lucrător. În Kubernetes, pur și simplu trimiteți o solicitare în aplicație dacă aplicația este scrisă în Python.

Același lucru este valabil și dacă trecem dincolo de Kubernetes. Avem Kubernetes-ul nostru rulând undeva - este bine dacă este într-un fel de nor. Din nou, putem folosi și chiar ar trebui, cred, să folosim capacitățile cloud-ului însuși acolo unde rulăm. Din lucrurile elementare pe care ni le oferă norul. Echilibrarea, adică putem crea balansoare cloud și le putem folosi. Acesta este un avantaj direct al ceea ce putem folosi. Pentru că, în primul rând, echilibrarea în cloud ne îndepărtează în mod prostește responsabilitatea pentru modul în care funcționează, cum este configurat. În plus, este foarte convenabil, deoarece Kubernetes obișnuit se poate integra cu nori.

Același lucru este valabil și pentru scalare. Kubernetes obișnuit se poate integra cu furnizorii de cloud. Știe să înțeleagă că, dacă clusterul rămâne fără noduri, adică spațiul nodului s-a epuizat, atunci trebuie să adăugați - Kubernetes însuși va adăuga noduri noi la clusterul dvs. și va începe să lanseze pod-uri pe ele. Adică, când vine încărcătura, numărul vetrelor începe să crească. Când nodurile din cluster se epuizează pentru aceste poduri, Kubernetes lansează noi noduri și, în consecință, numărul de poduri poate crește în continuare. Și este foarte convenabil. Aceasta este o oportunitate directă de a scala clusterul din mers. Nu foarte rapid, în sensul că nu este o secundă, este mai degrabă un minut pentru a adăuga noi noduri.

Dar din experiența mea, din nou, este cel mai tare lucru pe care l-am văzut vreodată. Când clusterul Cloudnative a crescut în funcție de ora din zi. A fost un serviciu de backend care a fost folosit de oamenii din back-office. Adică vin la muncă la ora 9 dimineața, încep să se conecteze la sistem și, în consecință, clusterul Cloudnative, unde funcționează totul, începe să se umfle, lansând noi poduri, astfel încât toți cei care vin la muncă să poată lucra cu aplicația. Când pleacă de la serviciu la 8:6 sau la 30:XNUMX, clusterele Kubernetes observă că nimeni nu mai folosește aplicația și încep să se restrângă. Economii de până la XNUMX% sunt garantate. Funcționa în Amazon la acea vreme, nu exista nimeni în Rusia care să o facă atât de bine.

Vă spun clar, economiile sunt de 30% pur și simplu pentru că folosim Kubernetes și profităm de capacitățile cloud-ului. Acum acest lucru se poate face în Rusia. Nu voi face publicitate nimănui, desigur, dar să spunem doar că există furnizori care pot face acest lucru, oferindu-l imediat din cutie cu un buton.

Există un ultim punct asupra căruia aș dori, de asemenea, să vă atrag atenția. Pentru ca aplicația dvs., infrastructura dvs. să fie Cloudnative, este logic să începeți în sfârșit să adaptați abordarea numită Infrastructură ca cod. Adică, aceasta înseamnă că aplicația dvs., sau mai degrabă infrastructura dvs., este necesară exact în același mod ca și cod Descrieți aplicația dvs., logica dvs. de afaceri sub formă de cod. Și lucrați cu el ca cod, adică testați-l, lansați-l, stocați-l în git, aplicați-i CICD.

Și tocmai asta vă permite, în primul rând, să aveți întotdeauna controlul asupra infrastructurii dvs., să înțelegeți întotdeauna în ce stare se află. În al doilea rând, evitați operațiunile manuale care provoacă erori. În al treilea rând, evitați pur și simplu ceea ce se numește turnover, când trebuie să efectuați în mod constant aceleași sarcini manuale. În al patrulea rând, vă permite să vă recuperați mult mai rapid în cazul unui eșec. În Rusia, de fiecare dată când vorbesc despre asta, există întotdeauna un număr mare de oameni care spun: „Da, este clar, dar aveți abordări, pe scurt, nu este nevoie să remediați nimic”. Dar e adevărat. Dacă ceva este stricat în infrastructura ta, atunci din punctul de vedere al abordării Cloudnative și din punctul de vedere al infrastructurii ca cod, mai degrabă decât să-l reparăm, să mergi la server, să descoperi ce este stricat și să-l repari, este mai ușor. pentru a șterge serverul și a-l crea din nou. Și voi avea toate acestea restaurate.

Toate aceste probleme sunt discutate mai detaliat la Cursuri video Kubernetes: Junior, Basic, Mega. Urmând link-ul vă puteți familiariza cu programul și condițiile. Lucrul convenabil este că poți stăpâni Kubernetes studiind de acasă sau de la serviciu 1-2 ore pe zi.

Sursa: www.habr.com

Adauga un comentariu