Kubernetes ima nekoliko opcija za ažuriranje resursa: primijeniti, urediti, zakrpati i zamijeniti. Postoji zabuna oko toga što svaki od njih radi i kada ih koristiti. Hajdemo shvatiti.
Ako kubectl patch
, što ne uključuje usporedbu apply
и patch
. Ovaj članak će razmotriti različite mogućnosti, kao i pravilnu upotrebu svake od njih.
Tijekom životnog ciklusa Kubernetes resursa (usluga, implementacija, ulaz itd.), ponekad morate promijeniti, dodati ili ukloniti neka svojstva ovog resursa. Na primjer, dodajte bilješku, povećajte ili smanjite broj replika.
Kubernetes CLI
Ako već radite s Kubernetes klasterima putem CLI-ja, već ste upoznati s njima apply
и edit
. Tim apply
čita specifikaciju resursa iz datoteke i pravi "upsert" u Kubernetes klaster, tj. stvara resurs ako ne postoji i ažurira ga ako postoji. Tim edit
čita resurs putem API-ja, zatim zapisuje specifikaciju resursa u lokalnu datoteku, koja se zatim otvara u uređivaču teksta. Nakon što uredite i spremite datoteku, kubectl
će poslati promjene napravljene natrag kroz API, koji će pažljivo primijeniti te promjene na resurs.
Ne znaju svi naredbe patch
и replace
. Tim patch
omogućuje vam promjenu dijela specifikacije resursa, pružajući samo promijenjeni dio u naredbenom retku. Tim replace
radi isto kao edit
, ali sve treba učiniti ručno: trebate preuzeti trenutnu verziju specifikacije resursa, na primjer, pomoću kubectl get -o yaml
, uredite ga, a zatim upotrijebite replace
za ažuriranje resursa prema promijenjenoj specifikaciji. Tim replace
neće raditi ako je došlo do bilo kakvih promjena između čitanja i zamjene izvora.
Kubernetes API
Vjerojatno ste upoznati s metodama CoreV1().Pods().Update()
, replaceNamespacedService
ili patch_namespaced_deployment
, ako radite s klasterima putem PUT
и PATCH
... Pri čemu update
и replace
koristi PUT
I patch
, koliko god trivijalan bio, koristi PATCH
.
Valja napomenuti da je kubectl
također radi s klasterima putem API-ja. Drugim riječima, kubectl
je omotač na vrhu klijentske biblioteke za jezik Go, koji uvelike pruža mogućnost pružanja podnaredbi u kompaktnijem i čitljivijem obliku uz standardne API mogućnosti. Na primjer, kao što ste možda već primijetili, metoda apply
nije spomenuto gore u prethodnom paragrafu. Trenutno (svibanj 2020. cca. prevoditelj) sva logika kubectl apply
, tj. stvaranje nepostojećih resursa i ažuriranje postojećih, radi u potpunosti na strani koda kubectl
. Ulažu se napori apply
na strani API-ja, ali je još uvijek u beta verziji. U nastavku ću pisati detaljnije.
Zakrpa prema zadanim postavkama
Najbolje korišteno patch
, ako želite ažurirati resurs. Ovo je način na koji obje klijentske biblioteke rade povrh Kubernetes API-ja i kubectl
(nije iznenađujuće, budući da je to omotač za klijentsku biblioteku, cca. prevoditelj).
Radite strateški
Svi timovi kubectl
apply
, edit
и patch
koristiti metodu PATCH
u HTTP zahtjevima za ažuriranje postojećeg resursa. Ako se detaljnije udubite u implementaciju naredbi, onda sve one koriste pristup patch
može koristiti druge pristupe (o tome više u nastavku). Pristup krpanja strateškog spajanja pokušava "ispraviti" spajanjem isporučene specifikacije s postojećom specifikacijom. Točnije, pokušava kombinirati i objekte i nizove, što znači da su promjene obično aditivne. Na primjer, izvođenje naredbe patch
s novom varijablom okruženja u specifikaciji kontejnera pod, uzrokuje da se ta varijabla okruženja doda postojećim varijablama okruženja umjesto da ih prepisuje. Da biste uklonili korištenjem ovog pristupa, morate prisiliti vrijednost parametra na nulu u navedenoj specifikaciji. Koji od timova kubectl
Je li najbolje koristiti za ažuriranje?
Ako stvarate i upravljate svojim resursima pomoću kubectl apply
, pri ažuriranju bolje je uvijek koristiti kubectl apply
, čtoby kubectl
mogao upravljati konfiguracijom i ispravno pratiti tražene promjene od aplikacije do aplikacije. Prednost uvijek koristiti apply
je da prati prethodno primijenjenu specifikaciju, dopuštajući mu da zna kada su svojstva specifikacije i elementi niza eksplicitno uklonjeni. To vam omogućuje korištenje apply
za uklanjanje svojstava i elemenata niza, dok normalno strateško spajanje neće raditi. Timovi edit
и patch
nemojte ažurirati bilješke koje kubectl apply
koristi za praćenje svojih promjena, tako da sve promjene koje se prate i rade putem Kubernetes API-ja, ali su napravljene putem naredbi edit
и patch
, nevidljiv sljedećim naredbama apply
To je, apply
ne uklanja ih čak i ako se ne pojavljuju u specifikaciji unosa za apply
(Dokumentacija to kaže edit
и patch
ažurirati korištene bilješke apply
, ali u praksi - ne).
Ako ne koristite naredbu apply
, može se koristiti kao edit
I patch
, odabirom naredbe koja najbolje odgovara promjeni koja se vrši. Prilikom dodavanja i mijenjanja svojstava sastavnice, oba su pristupa otprilike ista. Prilikom brisanja svojstava specifikacije ili elemenata polja edit
ponaša se kao jednokratno lansiranje apply
, uključujući praćenje kakva je specifikacija bila prije i nakon što je uređena, tako da možete eksplicitno ukloniti svojstva i elemente niza iz resursa. Trebate izričito postaviti vrijednost svojstva na null u specifikaciji za patch
da biste ga uklonili iz izvora. Uklanjanje elementa niza korištenjem krpanja strateškog spajanja složenije je jer zahtijeva korištenje direktiva spajanja. U nastavku pogledajte druge pristupe nadogradnji za održivije alternative.
Za implementaciju metoda ažuriranja u biblioteci klijenta koje se ponašaju slično gornjim naredbama kubectl
, treba postaviti u zahtjevima content-type
в application/strategic-merge-patch+json
. Ako želite ukloniti svojstva u specifikaciji, trebate eksplicitno postaviti njihove vrijednosti na null na sličan način kubectl patch
. Ako trebate ukloniti elemente niza, trebali biste uključiti direktive spajanja u specifikaciju ažuriranja ili koristiti drugačiji pristup ažuriranjima.
Drugi pristupi ažuriranju
Kubernetes podržava dva druga pristupa ažuriranju: kubectl patch --type=merge
. Kada radite s Kubernetes API-jem, trebali biste koristiti metodu zahtjeva PATCH
i instalacija content-type
в application/merge-patch+json
.
Pristup JSON zakrpe, umjesto pružanja djelomične specifikacije resursa, koristi pružanje promjena koje želite napraviti na resursu kao nizu, u kojem svaki element niza predstavlja opis promjene koja se vrši na resursu. Ovaj je pristup fleksibilniji i moćniji način za izražavanje promjena koje su napravljene, ali po cijenu popisa promjena koje su napravljene u zasebnom formatu koji nije Kubernetes, umjesto slanja djelomične specifikacije resursa. U kubectl
možete odabrati JSON zakrpu pomoću kubectl patch --type=json
. Kada se koristi Kubernetes API, ovaj pristup radi pomoću metode zahtjeva PATCH
i instalacija content-type
в application/json-patch+json
.
Trebamo povjerenje - upotrijebite zamjenu
U nekim slučajevima, morate biti sigurni da nema promjena na izvoru između vremena kada je izvor pročitan i kada je ažuriran. Drugim riječima, trebali biste biti sigurni da će sve promjene biti atomski. U ovom slučaju, za ažuriranje resursa trebate koristiti replace
. Na primjer, ako imate ConfigMap s brojačem koji ažurira više izvora, trebali biste biti sigurni da dva izvora ne ažuriraju brojač u isto vrijeme, uzrokujući gubitak ažuriranja. Za demonstraciju, zamislite slijed događaja koristeći pristup patch
:
- A i B dobivaju trenutno stanje resursa iz API-ja
- Svaki od njih lokalno ažurira specifikaciju povećanjem brojača za jedan i dodavanjem "A" ili "B" u bilješku "ažurirano do"
- I ažurira resurs malo brže
- B ažurira izvor
Kao rezultat toga, ažuriranje A je izgubljeno. Zadnja operacija patch
pobjeđuje, brojač se povećava za jedan umjesto za dva, a vrijednost bilješke "updated-by" završava s "B" i ne sadrži "A". Usporedimo gore navedeno s onim što se događa kada se ažuriranja izvrše pomoću pristupa replace
:
- A i B dobivaju trenutno stanje resursa iz API-ja
- Svaki od njih lokalno ažurira specifikaciju povećanjem brojača za jedan i dodavanjem "A" ili "B" u bilješku "ažurirano do"
- I ažurira resurs malo brže
- B pokušava ažurirati resurs, ali ažuriranje odbija API jer je verzija resursa u specifikaciji
replace
ne odgovara trenutnoj verziji resursa u Kubernetesu jer je verzija resursa povećana A-ovom operacijom zamjene.
U gornjem slučaju, B će morati ponovno dohvatiti resurs, unijeti promjene u novo stanje i pokušati ponovno replace
. To će uzrokovati povećanje brojača za dva i bilješku "ažurirano do" uključiti "AB" na kraju.
Gornji primjer implicira da prilikom izvođenja replace
Cijeli resurs je potpuno zamijenjen. Specifikacija koja se koristi za replace
, ne smije biti djelomičan, ili u dijelovima kao u apply
, ali potpun, uključujući dodatak resourceVersion
u metapodatke specifikacije. Ako niste omogućili resourceVersion
ili verzija koju navedete nije aktualna, zamjena će biti odbijena. Stoga je najbolji pristup korištenju replace
– pročitajte izvor, ažurirajte ga i odmah zamijenite. Korištenje kubectl
, moglo bi izgledati ovako:
$ kubectl get deployment my-deployment -o json
| jq '.spec.template.spec.containers[0].env[1].value = "new value"'
| kubectl replace -f -
Vrijedno je napomenuti da će se sljedeće dvije naredbe, uzastopno izvršavane, uspješno izvršiti, jer deployment.yaml
ne sadrži imovinu .metadata.resourceVersion
$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml
Ovo bi izgleda proturječilo onome što je gore rečeno, tj. "dodajući resourceVersion
u specifikacijske metapodatke." Je li to pogrešno reći? Ne, nije, jer ako kubectl
obavijesti koje niste naveli resourceVersion
, pročitat će ga iz resursa i dodati u specifikaciju koju ste naveli, a tek onda izvršiti replace
. Budući da je ovo potencijalno opasno ako se oslanjate na atomičnost, magija djeluje potpuno sa strane kubectl
, ne biste se trebali oslanjati na njega kada koristite klijentske biblioteke koje rade s API-jem. U ovom slučaju morat ćete pročitati trenutnu specifikaciju resursa, ažurirati je i zatim izvršiti PUT
zahtjev.
Ne možete napraviti zakrpu - mi radimo zamjenu
Ponekad morate napraviti neke promjene koje API ne može obraditi. U tim slučajevima možete prisiliti zamjenu resursa brisanjem i ponovnim stvaranjem. To se radi pomoću kubectl replace --force
. Pokretanje naredbe odmah uklanja resurse i zatim ih ponovno stvara iz dostavljene specifikacije. U API-ju ne postoji rukovatelj "prisilne zamjene", a da biste to učinili putem API-ja, morate izvršiti dvije operacije. Najprije morate izbrisati resurs postavljanjem za njega gracePeriodSeconds
na nulu (0) i propagationPolicy
u "Pozadina", a zatim ponovno izradite ovaj resurs sa željenom specifikacijom.
Upozorenje: ovaj pristup je potencijalno opasan i može dovesti do nedefiniranog stanja.
Primjena na strani poslužitelja
Kao što je gore spomenuto, programeri Kubernetesa rade na implementaciji logike apply
od kubectl
u Kubernetes API-ju. Logike apply
dostupno u Kubernetesu 1.18 putem kubectl apply --server-side
ili putem API-ja pomoću metode PATCH
с content-type
application/apply-patch+YAML
.
Napomena: JSON je također važeći YAML, tako da možete poslati specifikaciju kao JSON čak i ako
content-type
voljaapplication/apply-patch+yaml
.
Osim te logike kubectl
postaje dostupan svima putem API-ja, apply
na strani poslužitelja, prati tko je odgovoran za polja u specifikaciji, čime se omogućuje siguran višestruki pristup za njezino uređivanje bez sukoba. Drugim riječima, ako apply
na strani poslužitelja će postati rašireniji, pojavit će se univerzalno sigurno sučelje za upravljanje resursima za različite klijente, na primjer, kubectl, Pulumi ili Terraform, GitOps, kao i skripte koje sami pišu koristeći klijentske biblioteke.
Rezultati
Nadam se da vam je ovaj kratki pregled različitih načina ažuriranja resursa u klasterima bio od pomoći. Dobro je znati da nije samo primjena protiv zamjene; moguće je ažurirati resurs pomoću primjene, uređivanja, zakrpe ili zamjene. Uostalom, u principu, svaki pristup ima svoje područje primjene. Za atomske promjene poželjna je zamjena; inače biste trebali koristiti zakrpu strateškog spajanja putem primjene. U najmanju ruku, očekujem da razumijete da ne možete vjerovati Googleu ili StackOerflowu kada tražite "kubernetes primijeniti vs zamijeniti". Barem dok ovaj članak ne zamijeni trenutni odgovor.
Izvor: www.habr.com