Comparația corectă a aplicației, înlocuirii și corecțiilor Kubernetes

Kubernetes are mai multe opțiuni pentru actualizarea resurselor: aplicați, editați, corectați și înlocuiți. Există confuzie cu privire la ceea ce face fiecare și când să le folosească. Să ne dăm seama.

Comparația corectă a aplicației, înlocuirii și corecțiilor Kubernetes

Dacă cauta pe Google se află expresia „kubernetes apply vs replace”. răspuns la StackOverflow, ceea ce nu este corect. La cautare „kubernetes apply vs patch” primul link este documentația pentru kubectl patch, care nu include comparația apply и patch. Acest articol va analiza diferitele opțiuni, precum și utilizarea corectă a fiecăreia.

În timpul ciclului de viață al unei resurse Kubernetes (serviciu, implementare, intrare etc.), uneori trebuie să modificați, să adăugați sau să eliminați unele proprietăți ale acestei resurse. De exemplu, adăugați o notă, măriți sau micșorați numărul de replici.

CLI Kubernetes

Dacă lucrați deja cu clustere Kubernetes prin intermediul CLI, sunteți deja familiarizat apply и edit. Echipă apply citește specificația resursei din fișier și face un „upsert” către clusterul Kubernetes, de exemplu. creează resursa dacă nu există și o actualizează dacă există. Echipă edit citește o resursă prin API, apoi scrie specificația resursei într-un fișier local, care este apoi deschis într-un editor de text. După ce editați și salvați fișierul, kubectl va trimite înapoi modificările făcute prin API, care va aplica cu atenție aceste modificări resursei.

Nu toată lumea cunoaște comenzile patch и replace. Echipă patch vă permite să modificați o parte a specificației unei resurse, oferind doar partea modificată pe linia de comandă. Echipă replace functioneaza la fel ca edit, dar totul trebuie făcut manual: trebuie să descărcați versiunea curentă a specificației resursei, de exemplu, folosind kubectl get -o yaml, editați-l, apoi utilizați replace pentru a actualiza o resursă conform unei specificații modificate. Echipă replace nu va funcționa dacă au apărut modificări între citirea și înlocuirea resursei.

API Kubernetes

Probabil că sunteți familiarizat cu metodele CoreV1().Pods().Update(), replaceNamespacedService sau patch_namespaced_deployment, dacă lucrați cu clustere prin biblioteca client pentru API-ul Kubernetes folosind un limbaj de programare. Biblioteca gestionează aceste metode prin solicitări HTTP folosind metodele PUT и PATCH... Unde update и replace utilizare PUTȘi patch, oricât de banal ar fi, folosește PATCH.

Ar trebui remarcat faptul că kubectl funcționează și cu clustere prin API. Cu alte cuvinte, kubectleste un înveliș în partea de sus a bibliotecii client pentru limbajul Go, care oferă în mare măsură capacitatea de a furniza subcomenzi într-o formă mai compactă și mai lizibilă, în plus față de capabilitățile standard API. De exemplu, după cum poate ați observat deja, metoda apply nu a fost menționat mai sus în paragraful anterior. În prezent (mai 2020, aproximativ traducător) toată logica kubectl apply, adică crearea de resurse inexistente și actualizarea celor existente, funcționează în întregime pe partea de cod kubectl. Se fac eforturi despre transferul logic apply în partea API, dar este încă în versiune beta. Voi scrie mai detaliat mai jos.

Patch implicit

Cel mai bine folosit patch, dacă doriți să actualizați resursa. Acesta este modul în care ambele biblioteci client funcționează pe deasupra API-ului Kubernetes și kubectl (nu este surprinzător, deoarece este un înveliș pentru biblioteca client, aproximativ traducător).

Lucrați strategic

Toate echipele kubectl apply, edit и patch utilizați metoda PATCH în solicitările HTTP pentru a actualiza o resursă existentă. Dacă vă aprofundați în implementarea comenzilor mai detaliat, atunci toate folosesc abordarea patch-uri strategic-merge pentru a actualiza resurse, deși comanda patch poate folosi alte abordări (mai multe despre asta mai jos). Abordarea de corecție prin îmbinare strategică încearcă să „să facă corect” prin îmbinarea specificației furnizate cu specificația existentă. Mai precis, încearcă să combine atât obiectele, cât și matricele, ceea ce înseamnă că modificările tind să fie aditive. De exemplu, rularea comenzii patch cu o nouă variabilă de mediu în specificația containerului pod, face ca acea variabilă de mediu să fie adăugată la variabilele de mediu existente, în loc să le suprascrie. Pentru a elimina folosind această abordare, trebuie să forțați valoarea parametrului să fie nulă în specificația furnizată. Care dintre echipe kubectl Este cel mai bine să îl utilizați pentru actualizare?

Dacă vă creați și gestionați resursele folosind kubectl apply, atunci când actualizați este mai bine să utilizați întotdeauna kubectl applyLa kubectl ar putea gestiona configurația și urmări corect modificările solicitate de la aplicație la aplicație. Utilizați întotdeauna avantaj apply este că ține evidența unei specificații aplicate anterior, permițându-i să știe când proprietățile specificației și elementele matricei sunt eliminate în mod explicit. Acest lucru vă permite să utilizați apply pentru a elimina proprietăți și elemente de matrice, în timp ce o îmbinare strategică normală nu va funcționa. Echipe edit и patch nu actualizați notele că kubectl apply folosește pentru a-și urmări modificările, deci orice modificări care sunt urmărite și făcute prin API-ul Kubernetes, dar făcute prin comenzi edit и patch, invizibil pentru comenzile ulterioare applycare este apply nu le elimină chiar dacă nu apar în specificația de intrare pt apply (Documentația spune că edit и patch efectuați actualizări la notele utilizate apply, dar în practică - nu).

Dacă nu utilizați comanda apply, poate fi folosit ca editȘi patch, alegând comanda care se potrivește cel mai bine modificării efectuate. Când adăugați și modificați proprietățile BOM, ambele abordări sunt aproximativ aceleași. Când ștergeți proprietăți de specificație sau elemente de matrice edit se comportă ca o lansare unică apply, inclusiv urmărirea cum a fost specificația înainte și după ce a fost editată, astfel încât să puteți elimina în mod explicit proprietățile și elementele matricei dintr-o resursă. Trebuie să setați în mod explicit valoarea proprietății la null în specificația pentru patchpentru a-l elimina din resursă. Eliminarea unui element de matrice folosind corecțiile strategic-merge este mai complexă, deoarece necesită utilizarea directivelor de îmbinare. Vedeți mai jos alte abordări de actualizare pentru alternative mai viabile.

Pentru a implementa metode de actualizare în biblioteca client care se comportă similar comenzilor de mai sus kubectl, ar trebui să fie stabilit în cereri content-type в application/strategic-merge-patch+json. Dacă doriți să eliminați proprietăți dintr-o specificație, trebuie să setați în mod explicit valorile lor la nul într-un mod similar kubectl patch. Dacă trebuie să eliminați elemente de matrice, ar trebui să includeți directive de îmbinare în specificația de actualizare sau să utilizați o abordare diferită a actualizărilor.

Alte abordări ale actualizărilor

Kubernetes acceptă alte două abordări de actualizare: Patch-ul de îmbinare JSON и Patch JSON. Abordarea corecțiilor de îmbinare JSON ia ca intrare o specificație parțială Kubernetes și acceptă îmbinarea obiectelor similară cu abordarea de corecție a îmbinării strategice. Diferența dintre cele două este că acceptă doar înlocuirea matricei, inclusiv matricea containerului din specificația podului. Aceasta înseamnă că atunci când utilizați un patch de îmbinare JSON, trebuie să furnizați specificații complete pentru toate containerele în cazul în care orice proprietate a oricărui container se modifică. Deci, această abordare este utilă pentru eliminarea elementelor dintr-o matrice dintr-un BOM. Pe linia de comandă puteți selecta patch-ul de îmbinare JSON folosind kubectl patch --type=merge. Când lucrați cu API-ul Kubernetes, ar trebui să utilizați metoda de solicitare PATCH si instalare content-type в application/merge-patch+json.

Abordarea patch-ului JSON, în loc să ofere o specificație parțială a unei resurse, folosește furnizarea modificărilor pe care doriți să le faceți resursei ca o matrice, în care fiecare element al matricei reprezintă o descriere a modificării aduse resursei. Această abordare este o modalitate mai flexibilă și mai puternică de a exprima modificările efectuate, dar cu prețul listării modificărilor efectuate într-un format separat, non-Kubernetes, mai degrabă decât trimiterea unei specificații parțiale a resurselor. ÎN kubectl puteți selecta patch-ul JSON folosind kubectl patch --type=json. Când utilizați API-ul Kubernetes, această abordare funcționează folosind metoda de solicitare PATCH si instalare content-type в application/json-patch+json.

Avem nevoie de încredere - folosiți înlocuiți

În unele cazuri, trebuie să vă asigurați că nu se fac modificări unei resurse între momentul citirii resursei și momentul actualizării acesteia. Cu alte cuvinte, ar trebui să vă asigurați că toate modificările vor fi atomic. În acest caz, pentru a actualiza resursele pe care ar trebui să le utilizați replace. De exemplu, dacă aveți un ConfigMap cu un contor care este actualizat de mai multe surse, ar trebui să vă asigurați că două surse nu actualizează contorul în același timp, ceea ce duce la pierderea actualizării. Pentru a demonstra, imaginați-vă o secvență de evenimente folosind abordarea patch:

  • A și B obțin starea curentă a resursei din API
  • Fiecare actualizează local specificația prin creșterea contorului cu unul și, de asemenea, adăugând „A” sau, respectiv, „B” la nota „actualizată de”
  • Și actualizează resursa puțin mai repede
  • B actualizează resursa

Ca urmare, actualizarea A este pierdută. Ultima operatie patch câștigă, contorul este incrementat cu unu în loc de doi, iar valoarea notei „actualizate de” se termină cu „B” și nu conține „A”. Să comparăm cele de mai sus cu ceea ce se întâmplă atunci când actualizările se fac folosind abordarea replace:

  • A și B obțin starea curentă a resursei din API
  • Fiecare actualizează local specificația prin creșterea contorului cu unul și, de asemenea, adăugând „A” sau, respectiv, „B” la nota „actualizată de”
  • Și actualizează resursa puțin mai repede
  • B încearcă să actualizeze resursa, dar actualizarea este respinsă de API deoarece versiunea resursei este în specificație replace nu se potrivește cu versiunea curentă a resursei din Kubernetes, deoarece versiunea resursei a fost mărită de operația de înlocuire a lui A.

În cazul de mai sus, B va trebui să preia din nou resursa, să facă modificări în noua stare și să încerce din nou replace. Acest lucru va face ca contorul să fie incrementat cu două și nota „actualizată de” să includă „AB” la sfârșit.

Exemplul de mai sus implică faptul că atunci când se execută replace Întreaga resursă este complet înlocuită. Specificația folosită pentru replace, nu trebuie să fie parțial sau în părți ca în apply, dar complet, inclusiv adaosul resourceVersion în metadatele specificației. Dacă nu ați activat resourceVersion sau versiunea pe care o furnizați nu este actuală, înlocuirea va fi respinsă. Deci cea mai bună abordare de utilizat este replace – citiți resursa, actualizați-o și înlocuiți-o imediat. Folosind kubectl, ar putea arăta astfel:

$ kubectl get deployment my-deployment -o json 
    | jq '.spec.template.spec.containers[0].env[1].value = "new value"' 
    | kubectl replace -f -

Este de remarcat faptul că următoarele două comenzi, executate secvenţial, se vor executa cu succes, deoarece deployment.yaml nu contine proprietate .metadata.resourceVersion

$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml

Acest lucru ar părea să contrazică ceea ce s-a spus mai sus, adică. „adăugând resourceVersion în metadatele specificației." Este greșit să spui asta? Nu, nu este, pentru că dacă kubectl observă că nu ai specificat resourceVersion, o va citi din resursă și o va adăuga la specificația specificată de dvs. și abia apoi o va executa replace. Deoarece acest lucru este potențial periculos dacă te bazezi pe atomicitate, magia funcționează în întregime în lateral kubectl, nu ar trebui să vă bazați pe el atunci când utilizați biblioteci client care funcționează cu API. În acest caz, va trebui să citiți specificația curentă a resursei, să o actualizați și apoi să executați PUT cerere.

Nu puteți face un patch - noi facem o înlocuire

Uneori trebuie să faceți unele modificări care nu pot fi gestionate de API. În aceste cazuri, puteți forța înlocuirea resursei prin ștergerea și recrearea acesteia. Acest lucru se face folosind kubectl replace --force. Rularea comenzii elimină imediat resursele și apoi le recreează din specificația furnizată. Nu există un handler de „înlocuire forțată” în API și, pentru a face acest lucru prin API, trebuie să efectuați două operațiuni. Mai întâi trebuie să ștergeți resursa setând-o gracePeriodSeconds la zero (0) și propagationPolicy în „Background” și apoi re-creați această resursă cu specificația dorită.

Avertisment: Această abordare este potențial periculoasă și poate duce la o stare nedefinită.

Aplicați pe partea de server

După cum am menționat mai sus, dezvoltatorii Kubernetes lucrează la implementarea logicii apply de kubectl în API-ul Kubernetes. Logici apply disponibil în Kubernetes 1.18 prin kubectl apply --server-side sau prin API folosind metoda PATCH с content-type application/apply-patch+YAML.

Notă: JSON este și YAML valid, așa că puteți trimite specificația ca JSON chiar dacă content-type voință application/apply-patch+yaml.

Pe langa aceasta logica kubectl devine disponibil pentru toată lumea prin API, apply pe partea de server, ține evidența cine este responsabil pentru câmpurile din specificație, permițând astfel acces multiplu securizat pentru editarea fără conflicte. Cu alte cuvinte, dacă apply pe partea de server va deveni mai răspândită, va apărea o interfață universală de gestionare a resurselor securizate pentru diferiți clienți, de exemplu, kubectl, Pulumi sau Terraform, GitOps, precum și scripturi auto-scrise folosind biblioteci client.

Rezultatele

Sper că această scurtă prezentare generală a diferitelor modalități de actualizare a resurselor în clustere v-a fost de ajutor. Este bine să știți că nu este doar aplicați versus înlocuiți, este posibil să actualizați o resursă utilizând aplicați, editați, corectați sau înlocuiți. La urma urmei, în principiu, fiecare abordare are propriul său domeniu de aplicare. Pentru modificări atomice, este de preferat înlocuirea, în caz contrar, ar trebui să utilizați patch-ul de îmbinare strategică prin aplicare. Cel puțin, mă aștept să înțelegeți că nu puteți avea încredere în Google sau StackOerflow atunci când căutați „kubernetes apply vs replace”. Cel puțin până când acest articol înlocuiește răspunsul actual.

Comparația corectă a aplicației, înlocuirii și corecțiilor Kubernetes

Sursa: www.habr.com

Adauga un comentariu