Ispravna usporedba Kubernetes Apply, Replace i Patch

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.

Ispravna usporedba Kubernetes Apply, Replace i Patch

Ako pretraži na Googleu nalazi se izraz "kubernetes primijeniti vs zamijeniti". odgovori na StackOverflow, što nije točno. Prilikom traženja "kubernetes apply vs patch" prva poveznica je dokumentacija za 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 klijentska biblioteka za Kubernetes API koristeći neki programski jezik. Knjižnica rukuje ovim metodama putem HTTP zahtjeva koristeći metode PUT и PATCH... Pri čemu update и replace koristi PUTI patch, koliko god trivijalan bio, koristi PATCH.

Valja napomenuti da je kubectl također radi s klasterima putem API-ja. Drugim riječima, kubectlje 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 na logički prijenos 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 strateško spajanje krpanja za ažuriranje resursa, iako naredba 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 applyTo 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 editI 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 patchda 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: JSON zakrpa spajanja и JSON zakrpa. Pristup krpanja spajanja JSON uzima djelomičnu specifikaciju Kubernetesa kao ulaz i podržava spajanje objekata slično pristupu krpanja strateškog spajanja. Razlika između ta dva je u tome što podržava samo zamjenu niza, uključujući polje spremnika u specifikaciji pod-a. To znači da kada koristite zakrpu spajanja JSON-a, morate dati potpune specifikacije za sve spremnike u slučaju da se bilo koje svojstvo bilo kojeg spremnika promijeni. Stoga je ovaj pristup koristan za uklanjanje elemenata iz niza u BOM-u. U naredbenom retku možete odabrati zakrpu spajanja JSON pomoću 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 volja application/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.

Ispravna usporedba Kubernetes Apply, Replace i Patch

Izvor: www.habr.com

Dodajte komentar