Kubernetes Apply, Replace dhe Patch - një krahasim i saktë

Për Kubernetes ka disa mundësi për të përditësuar burimet: apply, edit, patch dhe replace. Ka konfuzion se çfarë bën secili prej tyre dhe kur të aplikohen. Le të sqarojmë.

Kubernetes Apply, Replace dhe Patch - një krahasim i saktë

Nëse të kërkosh në Google fraza "kubernetes apply vs replace", gjendet përgjigja në StackOverflow, e cila nuk është e saktë. Kur kërkon "kubernetes apply vs patch" lidhja e parë — dokumentacioni i kubectl patch, i cili nuk përfshin krahasim apliko dhe patch. Në këtë artikull do të shqyrtohen opsionet e ndryshme, si dhe përdorimi i saktë i secilit prej tyre.

Gjatë ciklit të jetës së një burimi Kubernetes (shërbimi, deployment, ingress, etj.) ndonjëherë është e nevojshme të ndryshosh, shtosh ose heqësh disa característica të këtij burimi. Për shembull, të shtosh një shënim, të rrisësh ose të zvogëlosh numrin e replikave.

Kubernetes CLI

Nëse tashmë po punoni me grupe Kubernetes përmes CLI, atëherë jeni tashmë të njohur me apliko dhe edito. Komanda apliko lexon specifikimin e burimit nga një skedar dhe kryen "upsert" në grupin Kubernetes, pra krijon burimin nëse nuk ekziston, dhe e përditëson atë nëse ekziston. Komanda edito lexon burimin përmes API, pastaj shkruan specifikimin e burimit në një skedar lokal, i cili pastaj hapet në një redaktues teksti. Pas përfundimit të redaktimit dhe ruajtjes së skedarit, kubectl do të kthejë ndryshimet e bëra përmes API-së, i cili me kujdes do t'i aplikoje këto ndryshime në burim.

Nuk e dinë të gjithë komandat patch dhe zëvendëso. Komanda patch lejon të ndryshoni një pjesë të specifikimit të burimit, duke ofruar vetëm pjesën e ndryshuar në komandën e linjës. Komanda zëvendëso punon ashtu siç bën edito, por gjithçka duhet të bëhet manualisht: duhet të shkarkoni versionin aktual të specifikimit të burimit, për shembull duke përdorur kubectl get -o yaml, ta redaktoni atë, pastaj të përdorni zëvendëso për të përditësuar burimin sipas specifikimit të ndryshuar. Komanda zëvendëso nuk do të funksionojë, nëse ka pasur ndonjë ndryshim midis leximit dhe zëvendësimit të burimit.

Kubernetes API

Më së shumti jeni të njohur me metodat CoreV1().Pods().Update(), replaceNamespacedService ose patch_namespaced_deployment, nëse punoni me klasterë përmes bibliotekës klient për API Kubernetes duke përdorur një gjuhë programuese të caktuar. Biblioteka i trajton këto metoda duke përdorur kërkesa për protokollin HTTP, duke përdorur metodat PUT dhe PATCH. Në këtë mënyrë update dhe zëvendëso në kompaninë Hecla Mining, e cila nxjerr argjend dhe metale të tjera të çmuara. Kompjuteri është instaluar në një stacion në Alaska, ku përdoret për të vlerësuar parametrat e mineralit dhe për të printuar etiketat për mostra. Me rastin e kësaj, një printer po aq i vjetër po përgjigjet për etiketa. Është interesante, se shtatë vjet më parë, njëri nga inxhinierët e Hecla Mining në një postim në Reddit vuri në dukje se "ai nuk ka nevojë të luajë serinë PUT, dhe patch, siç do të ishte e zakonshme, përdor PATCH.

Duhet të theksohet se kubectl po ashtu punon me klasterët përmes API. Në një fjalë, kubectl– është një mbulesë mbi bibliotekën e klientit për gjuhën Go, që ofron në masë të madhe mundësinë për të ofruar nënkomanda në një formë më kompakte dhe të lexueshme përveç mundësive standart të API-së. Për shembull, siç e keni vënë re, metoda apliko nuk u përmend më sipër në paragrafët e mëparshëm. Aktualisht (maj 2020, shënim i përkthyesit) e gjithë logjika kubectl aplikoni, do thotë krijimi i burimeve që nuk ekzistojnë dhe përditësimi i atyre ekzistuese, funksionon plotësisht në anën e kodit kubectl. Po bëhen përpjekje për të transferuar logjikën apliko në anën e API-së, por këtë ende në fazën e testimit beta. Më shumë do ta shpjegoj më poshtë.

Patch-i në parazgjedhje

Më mirë është ta aplikoni patch, nëse dëshironi të përditësoni burimin. Kështu funksionojnë si bibliotekat e klientit mbi API-në Kubernetes, ashtu edhe kubectl (nuk është e habitshme, pasi ai është një mbulesë e bibliotekës së klientit, shënim i përkthyesit).

Të punosh strategjikisht

Të gjitha komandat kubectl apliko, edito dhe patch përdorin metodën PATCH në kërkesat HTTP për të përditësuar një burim ekzistues. Nëse shqyrtojmë me hollësi implementimin e komandave, atëherë të gjitha përdorin qasjen strategic-merge patching për përditësimin e burimeve, megjithëse komanda patch mund të përdorë edhe qasje të tjera (më shumë rreth kësaj më poshtë). Qasja strategic-merge patching përpiqet t"i bëjë gjërat siç duhet" gjatë bashkimit të specifikimeve të ofruara me specifikimet ekzistuese. Më konkretisht, ajo përpiqet të bashkojë si objekte ashtu edhe shuma, që do të thotë se ndryshimet zakonisht janë aditive. Për shembull, ekzekutimi i komandës patch me një variabël të ri ambienti në specifikimin e kontejnerit pod, çon në atë që ky variabël ambienti shtohet te variablat ekzistues të ambientit, e jo të zëvendësojë ato. Për të hequr me këtë qasje, duhet të vendosni forcërisht vlerën e parametrave në null në specifikimin e ofruar. Cilat prej komandave kubectl janë më të mirat për t'u përdorur për përditësimin?

Nëse krijoni dhe menaxhoni burimet tuaja me kubectl aplikoni, në përditësim është më mirë gjithmonë të përdorni kubectl aplikoni, në mënyrë që kubectl mund të menaxhonte konfigurimin dhe të ndiqte në mënyrë të saktë ndryshimet e kërkuara nga aplikimi në aplikim. Avantazhi i përdorimit gjithmonë apliko ndodhet se ai ndjek specifikimin e zbatuar më parë, duke i lejuar atij të dijë kur pronat e specifikimit dhe elementet e array-t hiqen shprehimisht. Kjo lejon përdorimin e apliko për të hequr pronat dhe elementet e array-t, ndërsa shkalla e zakonshme e përzierjes nuk do funksionojë. Komandat edito dhe patch nuk përditësojnë shënimet që kubectl aplikoni aplikon për të ndjekur ndryshimet e tij, prandaj çdo ndryshim që ndiqet dhe bëhet përmes API Kubernetes, por që është bërë përmes komandave edito dhe patch, nuk janë të dukshme për komandat e mëvonshme apliko, që do të thotë apliko nuk i heq ato, edhe nëse ato nuk shfaqen në specifikimin hyrës për apliko (Në dokumentacion thuhet se edito dhe patch bëjnë përditësime të shënimeve të përdorura apliko, por në praktikë – jo).

Nëse nuk po përdorni komandën apliko, mund të përdorni si edito, ashtu edhe patch, duke zgjedhur atë komandë që i përshtatet më së miri ndryshimit që bëhet. Kur shtoni dhe ndryshoni pronat e specifikimit, të dy qasjet janë afërsisht të njëjta. Kur hiqni pronat e specifikimit ose elementet e array-t edito silet si një ekzekutim i vetëm apliko, përfshirë ndjekjen e specifikimeve para dhe pas redaktimit, prandaj është e mundur të hiqen qartë pronat dhe elementet e arrës nga burimi. Duhet të vendoset qartë vlera e pronës në null në specifikim për patch, për ta hequr atë nga burimi. Heqja e një elementi të arrës duke përdorur patching me strategji të bashkimit është më komplekse, pasi kërkon përdorimin e drejtimeve të bashkimit. Shihni qasje të tjera për azhurnim më poshtë për të zgjedhur alternativa më të përshtatshme.

Për të zbatuar në bibliotekën e klientit metodat e azhurnimit, që veprojnë në mënyrë të ngjashme me komandat e mësipërme kubectl, duhet të specifikoni në kërkesa content-typeapplication/strategic-merge-patch+json. Nëse dëshironi të hiqni pronat në specifikim, ju duhen vendosur qartë vlerat e tyre në null, ngjashëm me kubectl patch. Nëse nevojiten heqjet e elementeve të arrës, ju duhet të përfshini drejtime bashkimi në specifikimin e azhurnimit ose të përdorni një qasje tjetër për azhurnimet.

Qasje të tjera për azhurnime

Në Kubernetes mbështeten dy qasje të tjera për azhurnime: JSON merge patch dhe JSON patch. Qasja JSON merge patch pranon një specifikim të pjesshëm Kubernetes si hyrje dhe mbështet bashkimin e objekteve në mënyrë të ngjashme me qasjen strategic-merge patching. Dallimi midis tyre është se ai mbështet vetëm zëvendësimin e masivave, duke përfshirë masivin e konteinerëve në specifikimin e pod. Kjo do të thotë se, kur përdorni JSON merge patch, ju duhet të ofroni specifikimet e plota për të gjithë konteinerët në rast të ndryshimit të ndonjë pronësie të ndonjë konteineri. Kështu, ky qasje është e dobishme për të hequr elementët nga një masiv në specifikim. Në komandën e vijës, mund të zgjidhni JSON merge patch duke përdorur kubectl patch --type=merge. Kur punoni me API-në Kubernetes, duhet të përdorni metodën e kërkesës PATCH dhe instalimin content-typeapplication/merge-patch+json.

Qasja JSON patch, në vend që të ofrojë një spesifikim të pjesshëm të burimit, përdor ofrimin e ndryshimeve që dëshironi të bëni në burim, në formën e një varg, ku çdo element i vargut përfaqëson një përshkrim të ndryshimit që po bëhet në burim. Kjo qasje është më fleksibël dhe më e fuqishme për të shprehur ndryshimet që po bëhen, por me koston që lista e ndryshimeve të bëra është në një format tjetër, jo Kubernetes, përveç se dërgesës së një specifikimi të pjesshëm të burimit. Në kubectl ju mund të zgjidhni JSON patch, duke përdorur kubectl patch --type=json. Kur përdoret API Kubernetes, kjo qasje funksionon duke përdorur metodën e kërkesës PATCH dhe instalimin content-typeapplication/json-patch+json.

Keni nevojë për siguri — përdorim replace

Në disa raste, nevojitet siguria që burimi të mos modifikohet midis kohës së leximit të burimit dhe përditësimit të tij. Në terma të tjerë, duhet të sigurohemi që të gjitha ndryshimet të jenë atomike. Në këtë rast, për të përditësuar burimet, është më mirë të përdoret zëvendëso. Për shembull, nëse ka një ConfigMap me një numërator që përditësohet nga disa burime, duhet të sigurohemi që dy burime të mos përditësojnë numëratorin në të njëjtën kohë, gjë që do të çonte në humbjen e përditësimit. Për ta demonstruar, imagjinoni një sekuencë ngjarjesh duke përdorur qasjen patch:

  • A dhe B marrin gjendjen aktuale të burimit nga API
  • Secili prej tyre përditëson specifikimin lokal, duke e rritur numëratorin me një njësi, si dhe duke shtuar "A" ose "B" përkatësisht në shënimin "updated-by"
  • A pak më shpejt përditëson burimin
  • B përditëson burimin

Si rezultat, përditësimi i A është humbur. Operacioni i fundit patch fiton, numëratori rritet me një njësi në vend të dyve, dhe vlera e shënimit "updated-by" përfundon me "B" dhe nuk përmban "A". Le t'i krahasojmë këto me atë që ndodh kur përditësimet kryhen duke përdorur qasjen zëvendëso:

  • A dhe B marrin gjendjen aktuale të burimit nga API
  • Secili prej tyre përditëson specifikimin lokal, duke e rritur numëratorin me një njësi, si dhe duke shtuar "A" ose "B" përkatësisht në shënimin "updated-by"
  • A pak më shpejt përditëson burimin
  • B përpiqet të përditësojë burimin, por përditësimi refuzohet nga API, sepse versioni i burimit në specifikim zëvendëso nuk përputhet me versionin aktual të burimit në Kubernetes, pasi versioni i burimit u rrit gjatë operacionit të ndryshimit nga ana e A.

Në rastin e sipërm, B do të duhet të nxjerrë përsëri burimin, të bëjë ndryshimet në gjendjen e re dhe të provojë përsëri. zëvendëso. Si rezultat, numëruesi do të rritet me dy, dhe shënimi "updated-by" do të përmbajë "AB" në fund.

Shembulli i mësipërm sugjeron se gjatë ekzekutimit zëvendëso bëhet një zëvendësim i plotë i gjithë burimit. Specifikimi që përdoret për zëvendësonuk duhet të jetë pjesor, ashtu si në aplikopor të jetë i plotë, duke përfshirë shtimin resourceVersion në metadata të specifikimit. Nëse nuk e përfshini resourceVersion ose versioni që ofroni nuk është aktual, zëvendësimi do të refuzohet. Prandaj, qasja më e mirë për të përdorur zëvendëso është të lexoni burimin, ta përditësoni dhe ta zëvendësoni menjëherë. Duke përdorur kubectlmund të duket kështu:

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

Dhe duhet të theksohet se dy komandat e mëposhtme, të ekzekutuara njëra pas tjetrës, do të kryhen me sukses, pasi deployment.yaml nuk përmban pronën .metadata.resourceVersion

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

Duket se kjo është në kontradiktë me atë që u tha më sipër, dmth "shtimi resourceVersion në metadatën e specifikimeve." A është e gabuar të thahet kështu? Jo, nuk është kështu, sepse nëse kubectl vëren se nuk keni specifikuar resourceVersion, ai do ta lexojë atë nga burimi dhe do ta shtojë në specifikimin që keni treguar dhe vetëm atëherë do ta ekzekutojë zëvendëso. Për shkak se kjo është potencialisht e rrezikshme, nëse mbështeteni në atomik, magjia funksionon plotësisht në anën kubectl, mos e mbështetni atë kur përdorni bibliotekat e klientit që punojnë me API. Në këtë rast, do t'ju duhet të lexoni specifikimin aktual të burimit, të përditësoni atë dhe më pas të ekzekutoni PUT kërkesën.

Nuk mund të bëni patch – bëni replace

Ndonjëherë duhet të bëni disa ndryshime që nuk mund të përpunohen nga API. Në këto raste, mund të zëvendësoni burimin me forcë, duke e fshirë atë dhe duke e krijuar përsëri. Kjo bëhet me anë të kubectl replace --force. Ekzekutimi i komandës menjëherë fshin burimet dhe pastaj i rikrijon ato sipas specifikimit të dhënë. Në API nuk ka trajtues "zëvendos forcërisht", dhe për ta bërë këtë përmes API, duhet të ekzekutoni dy operacione. Së pari, duhet të fshini burimin, duke caktuar për të gracePeriodSeconds në zero (0) dhe propagationPolicy në “Background”, dhe pastaj rindërto këtë burim me specifikimin e dëshiruar.

Kujdes: ky qasje potencialisht është i rrezikshëm, mund të çojë në një gjendje të pacaktuar

Aplikoni anash serverit

Siç u përmend më sipër, zhvilluesit e Kubernetes po punojnë në implementimin e logjikës apliko nga kubectl në API-në e Kubernetes. Logjika apliko është e disponueshme në Kubernetes 1.18 përmes kubectl apply --server-side ose përmes API-së, duke përdorur metodën PATCH me content-type application/apply-patch+YAML.

Shënim: JSON gjithashtu është një YAML i saktë, kështu që mund të dërgoni specifikimin në formë JSON, edhe nëse content-type do të application/apply-patch+yaml.

Përveç që logjika kubectl bëhet e disponueshme për të gjithë përmes API-së, apliko ana e serverit monitoron përgjegjësit për fushat në specifikim, duke lejuar kështu qasje të sigurt për redaktimin e saj pa konflikte. Në një tjetër fjalë, nëse apliko ana e serverit përhapet më gjerësisht, do të krijohet një ndërfaqe universale e sigurt për menaxhimin e burimeve për klientë të ndryshëm, siç janë kubectl, Pulumi ose Terraform, GitOps, si dhe skriptet e personalizuara që përdorin bibliotekat e klientëve.

Përfundimet

Shpresoj që ky përmbledhje i shkurtër mbi mënyrat e ndryshimit të burimeve në klastera ka qenë e dobishme për ju. Është e rëndësishme të dini se kundërshtarët nuk janë thjesht apply përballë replace, pasi mund të përditësoni burimin përmes apply, edit, patch ose replace. Në thelb, çdo qasje ka fushën e saj të aplikimit. Për ndryshime atomike, është më mirë të përdorni replace, ndryshe duhen përdorur strategic-merge patch nëpërmjet apply. Në rastin më të keq, shpresoj që e keni kuptuar se nuk mund të besoni Google ose StackOverflow kur kërkoni "kubernetes apply vs replace". Të paktën derisa ky artikull të zëvendësojë përgjigjen aktuale.

Kubernetes Apply, Replace dhe Patch - një krahasim i saktë

Burimi: habr.com

Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS 🔥 Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS | ProHoster