Pravilno primerjanje Kubernetes Apply, Replace in Patch

Za Kubernetes je na voljo več možnosti za posodabljanje virov: apply, edit, patch in replace. Pri tem, kaj vsak od njih počne in kdaj jih uporabiti, prihaja do zmede. Poglejmo si to pobliže.

Pravilno primerjanje Kubernetes Apply, Replace in Patch

Если iskati v Googlu izraza "kubernetes apply vs replace", najdete odgovor na StackOverflow, ki pa ni pravilen. Pri iskanju "kubernetes apply vs patch" je prva povezava - dokumentacija za kubectl patch, ki ne vključuje primerjave apply in patch. V tem članku bomo preučili različne možnosti in tudi pravilno uporabo vsake izmed njih.

V času življenjskega cikla Kubernetes virov (storitev, deployment, ingress ipd.) je včasih potrebno spremeniti, dodati ali odstraniti nekatere lastnosti tega viresa. Na primer, dodati opombo, povečati ali zmanjšati število replik.

Kubernetes CLI

Če že delate s Kubernetes klasteri preko CLI, ste verjetno seznanjeni z apply in edit. Ukaz apply ki prebere specifikacijo viresa iz datoteke in izvede "upsert" v Kubernetes klaster, torej ustvari vir, če le-ta ne obstaja, in ga posodobi, če že obstaja. Ukaz edit prebere vir preko API, nato pa zapiše specifikacijo viresa v lokalno datoteko, ki se nato odpre v urejevalniku besedila. Po tem, ko datoteko uredite in shranite, kubectl pošlje opravljene spremembe nazaj preko API, ki skrbno uporabi te spremembe na viru.

Niso vsi seznanjeni z ukazi patch in replace. Ukaz patch omogoča spreminjanje dela specifikacije viresa, tako da na ukazni vrstici navedete samo spremenjeni del. Ukaz replace deluje tako kot edit, vendar je vse potrebno narediti ročno: treba je prenesti trenutno različico specifikacije viresa, na primer z uporabo kubectl get -o yaml, jo urediti, nato pa uporabiti replace za posodobitev viresa po spremenjeni specifikaciji. Ukaz replace ne bo deloval, če so se med branjem in zamenjavo viresa zgodile kakršne koli spremembe.

Kubernetes API

Verjetno ste seznanjeni z metodami CoreV1().Pods().Update(), replaceNamespacedService ili patch_namespaced_deployment, če delate s klasteri preko klientske knjižnice za Kubernetes API s pomočjo določenega programskega jezika. Knjižnica obravnava te metode s pomočjo HTTP poizvedb, pri čemer uporablja metode PUT in PATCH. Pri tem update in replace uporabljajo PUT, a patch, koliko se morda zdi banalno, uporablja PATCH.

Je třeba poznamenat, že kubectl prav tako deluje s klasteri preko API. Z drugimi besedami, kubectl– je ovo omotnica iznad klijentske biblioteke za jezik Go, koja u značajnoj meri omogućava da podkomande budu predstavljene u kompaktom i čitljivom obliku, pored ugrađenih mogućnosti API-ja. Na primer, kao što ste već mogli primetiti, metoda apply nije pomenuta u prethodnom odlomku. Trenutno (maj 2020, translator's note) cela logika kubectl apply, tj. kreiranje nepostojećih resursa i ažuriranje postojećih, funkcioniše potpuno na strani koda kubectl. Poduzimaju se napori da se logika apply premesti na stranu API-ja, ali je to još u beta testiranju. Detaljnije ću opisati u nastavku.

Patch po zadatku

Najbolje je primeniti patch, ako želite da ažurirate resurs. Tako funkcionišu i klijentske biblioteke iznad Kubernetes API-ja, kao i kubectl (nije ni čudo, jer je on omotnica klijentske biblioteke, translator's note).

Raditi strateški

Sve komande kubectl apply, edit in patch koriste metodu PATCH u HTTP zahtevima za ažuriranje postojećeg resursa. Ako se detaljnije pogleda implementacija komandi, sve koriste pristup strategic-merge patching za ažuriranje resursa, iako tim patch može koristiti i druge pristupe (više o tome u nastavku). Pristup strategic-merge patching pokušava da "uradi sve kako treba" prilikom kombinovanja dostavljene specifikacije sa postojećom specifiikacijom. Konkretno, pokušava da kombinuje objekte i nizove, što znači da su promene uglavnom aditivne. Na primer, pokretanje komande patch sa novom promenljivom okruženja u specifikaciji kontejnera pod, podrazumeva da se ova promenljiva okruženja dodaje postojećim promenljivim okruženja, a ne prepisuje ih. Za brisanje pomoću ovog pristupa treba obavezno postaviti vrednost parametra na null u dostavljenoj specifikaciji. Koje od komandi kubectl za ažuriranje je najbolje koristiti?

Ako kreirate i upravljate svojim resursima pomoću kubectl apply, prilikom ažuriranja je uvek najbolje koristiti kubectl apply, kako bi kubectl moga upravljati konfiguracijom i pravilno pratiti zatražene promene od primene do primene. Prednost korišćenja apply je u tome što prati prethodno primenjenu specifikaciju, omogućavajući mu da zna kada se svojstva specifikacije i elementi niza eksplicitno brišu. To omogućava korišćenje apply za odstranjevanje lastnosti in elementov seznama, medtem ko običajno strateško združevanje ne bo delovalo. Ukazi edit in patch ne posodabljajo opomb, ki kubectl apply se uporabljajo za sledenje spremembam, zato so vse spremembe, ki jih sledi API Kubernetes, a jih vnesejo ukazi edit in patch, nevidne za naknadne ukaze apply, torej apply ne odstrani, tudi če se ne pojavijo v vhodni specifikaciji za apply (V dokumentaciji je omenjeno, da edit in patch izvajajo posodobitve opomb, ki se uporabljajo apply, ampak v praksi – ne).

Če ne uporabljate ukaza apply, lahko uporabite tako edit, kot tudi patch, izberite tisti ukaz, ki najbolje ustreza vneseni spremembi. Pri dodajanju in spreminjanju lastnosti specifikacije sta oba pristopa približno enaka. Pri odstranjevanju lastnosti specifikacije ali elementov seznama edit deluje kot enkratno izvajanje apply, vključujoč sledenje temu, kakšna je bila specifikacija pred in po urejanju, zato je mogoče izrecno odstraniti lastnosti in elemente seznama iz vira. Potrebno je izrecno nastaviti vrednost lastnosti na null v specifikaciji za patch, da jo odstranite iz vira. Odstranjevanje elementa seznama z uporabo strateškega združevanja je bolj zapleteno, saj je potrebno uporabiti združevalne direktive. Oglejte si druge pristope k posodobitvam spodaj za več sprejemljivih alternativ.

Za uresničitev metod posodabljanja v odjemalski knjižnici, ki se obnašajo podobno kot zgoraj omenjeni ukazi kubectl, je treba v zahtevkih nastaviti content-type u application/strategic-merge-patch+json. Če želite odstraniti lastnosti v specifikaciji, morate izrecno nastaviti njihove vrednosti na null enako kubectl patch. Če morate odstraniti elemente seznama, bi morali vključiti združevalne direktive v specifikacijo posodobitve ali uporabiti drug pristop k posodobitvam.

Drugi pristopi k posodobitvam

V Kubernetesu so podprti še dva druga pristopa k posodobitvam: JSON merge patch in JSON patch. Pristop JSON merge patch sprejme delno specifikacijo Kubernetes kot vhodne podatke in podpira združevanje objektov podobno pristopu strategic-merge patching. Razlika med njima je v tem, da podpira le zamenjavo tabel, vključno z tabelo vsebniki v specifikaciji pod. To pomeni, da morate pri uporabi JSON merge patch zagotoviti popolne specifikacije za vse vsebnike v primeru spremembe katere koli lastnosti katerega koli vsebnika. Ta pristop je torej koristen za odstranjevanje elementov iz tabele v specifikaciji. V ukazni vrstici lahko izberete JSON merge patch, tako da uporabite kubectl patch --type=merge. Pri delu z API Kubernetes je treba uporabiti metodo poizvedbe PATCH in namestitev content-type u application/merge-patch+json.

Pristop JSON patch namesto tega, da bi zagotovili delno specifikacijo vira, uporablja zagotavljanje sprememb, ki jih želite vnesti v vir, v obliki tabele, kjer vsak element tabele predstavlja opis spremembe, ki se vnaša v vir. Ta pristop je bolj fleksibilen in zmogljiv način za izražanje vnašanih sprememb, vendar zaradi tega, ker seznam vnašanih sprememb ne uporablja formata Kubernetes, namesto pošiljanja delne specifikacije vira. V kubectl lahko izberete JSON patch, tako da uporabite kubectl patch --type=json. Pri uporabi API Kubernetes ta pristop deluje z uporabo metode poizvedbe PATCH in namestitev content-type u application/json-patch+json.

Potrebna je gotovost — uporabljamo replace

V nekaterih primerih potrebujemo gotovost, da do virov ne bo prišlo do sprememb med časom branja vira in njegovim posodabljanjem. Drugimi besedami, treba je zagotoviti, da bodo vse spremembe atomarne. V tem primeru je za posodabljanje virov najbolje uporabiti replace. Na primer, če obstaja ConfigMap s števcem, ki ga posodabljajo več virov, je treba zagotoviti, da dva vira ne bosta hkrati posodabljala števca, kar bi privedlo do izgube posodobitve. Za ponazoritev si predstavljajte zaporedje dogodkov z uporabo pristopa patch:

  • A in B pridobita trenutno stanje vira iz API
  • Vsak od njiju lokalno posodablja specifikacijo, tako da poveča števec za enoto ter doda "A" ali "B" v ustrezno opombo "updated-by"
  • A nekoliko hitreje posodablja vir
  • B posodablja vir

Zaradi tega je bila izgubljena posodobitev A. Zadnja operacija patch zmaguje, števec se poveča za enoto namesto dveh, končna vrednost opombe "updated-by" pa se konča na "B" in ne vsebuje "A". Primerjajmo zgoraj navedeno s tem, kar se zgodi, ko se posodobitve izvedejo z uporabo pristopa replace:

  • A in B pridobita trenutno stanje vira iz API
  • Vsak od njiju lokalno posodablja specifikacijo, tako da poveča števec za enoto ter doda "A" ali "B" v ustrezno opombo "updated-by"
  • A nekoliko hitreje posodablja vir
  • B poskuša posodobiti vir, vendar API zavrne posodobitev, ker se različica vira v specifikaciji replace ne ujema z trenutno različico vira v Kubernetesu, saj se je različica vira povečala med izvajanjem operacije replace s strani A.

V zgornjem primeru bo moral B znova pridobiti vir, narediti spremembe v novem stanju in poskusiti znova replace. Kot rezultat se bo števec povečal za dva, opomba "updated-by" pa bo vsebovala "AB" na koncu.

Zgornji primer predpostavlja, da se pri izvajanju replace izvede popolna zamenjava celotnega vira. Specifikacija, ki se uporablja za replace, mora biti nepogojna, ali delna kot v apply, ampak polna, vključno z dodajanjem resourceVersion v metapodatke specifikacije. Če niste vključili resourceVersion ali dana različica ni trenutna, bo zamenjava zavrnjena. Tako je najboljši pristop za uporabo replace – prebrati vir, ga posodobiti in takoj zamenjati. Z uporabo kubectl, lahko to izgleda tako:

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

Pri tem je treba omeniti, da se bosta naslednji dve ukazi, izvršeni zaporedno, uspešno izvedli, saj deployment.yaml ne vsebuje lastnosti .metadata.resourceVersion

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

Zdi se, da to nasprotuje temu, kar je bilo prejšnje, torej "dodajanje resourceVersion v metapodatke specifikacije". Ali je trditev napačna? Ne, ni, saj če kubectl opazi, da niste navedli resourceVersion, jo bo prebral iz vira in dodal v vašo določeno specifikacijo, šele nato bo izvedel replace. Ker je to potencialno nevarno, če zaupate atomarnosti, ta magija deluje popolnoma na strani kubectl, ne zaupajte ji pri uporabi knjižnic strank, ki delajo z API. V tem primeru boste morali prebrati trenutno specifikacijo vira, jo posodobiti in nato izvesti PUT poizvedbo.

Ni mogoče opraviti patch – opravimo replace

Včasih je treba opraviti nekatere spremembe, ki jih API ne more obdelati. V teh primerih lahko prisilno zamenjate vir tako, da ga izbrišete in ponovno ustvarite. To se naredi s kubectl replace --force. Zažiganje ukaza takoj izbriše vire in jih nato ponovno ustvari s predloženo specifikacijo. API ne vsebuje obdelovalnika "prisilno zamenjati", da bi to storili preko API, je treba izvesti dve operaciji. Najprej je treba izbrisati vir tako, da se nastavitev gracePeriodSeconds nastavi na nič (0) in propagationPolicy na 'Background', nato pa ponovno ustvariti ta vir z želeno specifikacijo.

Pozor: ta pristop je potencialno nevaren, lahko povzroči nedoločenost

Apply na strani strežnika

Kot je bilo omenjeno zgoraj, razvijalci Kubernetes delajo na implementaciji logike apply iz kubectl v Kubernetes API-ju. Logika apply je na voljo v Kubernetes 1.18 preko kubectl apply --server-side ali preko API-ja, z uporabo metode PATCH z content-type application/apply-patch+YAML.

Opomba: JSON je prav tako veljaven YAML, zato lahko pošljete specifikacijo v obliki JSON, tudi če content-type biće application/apply-patch+yaml.

Poleg tega, da postane logika kubectl na voljo za vse preko API-ja, apply na strani strežnika spremlja odgovornosti za polja v specifikaciji, kar omogoča varen večinski dostop za njeno brezkonfliktno urejanje. Drugimi besedami, če apply na strani strežnika pridobi širšo distribucijo, bo nastal univerzalen varen vmesnik za upravljanje virov za različne stranke, kot so kubectl, Pulumi ali Terraform, GitOps in tudi lastni skripti, ki uporabljajo odjemalske knjižnice.

Zaključki

Upam, da je bil ta kratek pregled različnih načinov posodabljanja virov v grozdih koristen za vas. Koristno je vedeti, da nasprotniki ne grejo le za apply proti replace, saj je mogoče posodobiti vir s pomočjo apply, edit, patch ali replace. V osnovi ima vsak pristop svoje področje uporabe. Za atomske spremembe je boljša izbira replace, sicer je bolje uporabiti strategic-merge patch preko apply. Na koncu upam, da ste razumeli, da ne smete zaupati Googlu ali StackOverflow pri iskanju "kubernetes apply vs replace". Vsaj dokler ta članek ne nadomesti trenutnega odgovora.

Pravilno primerjanje Kubernetes Apply, Replace in Patch

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster