Pravilno poređenje Kubernetes primjene, zamjene i zakrpe

Kubernetes ima nekoliko opcija za ažuriranje resursa: primijeniti, urediti, zakrpiti i zamijeniti. Postoji konfuzija oko toga šta svaki od njih radi i kada ih koristiti. Hajde da to shvatimo.

Pravilno poređenje Kubernetes primjene, zamjene i zakrpe

ako pretraži na Googleu nalazi se fraza "kubernetes primijeniti vs zamjenu". odgovorite na StackOverflow, što nije tačno. Prilikom traženja "kubernetes primjena vs zakrpa" prva veza je dokumentacija za kubectl patch, što ne uključuje poređenje apply и patch. Ovaj članak će razmotriti različite opcije, kao i pravilnu upotrebu svake od njih.

Tokom ž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 sa Kubernetes klasterima preko CLI-a, već ste upoznati apply и edit. Tim apply čita specifikaciju resursa iz datoteke i pravi "upsert" u Kubernetes klaster, tj. kreira resurs ako ne postoji i ažurira ga ako postoji. Tim edit čita resurs preko API-ja, zatim upisuje specifikaciju resursa u lokalnu datoteku, koja se zatim otvara u uređivaču teksta. Nakon što uredite i sačuvate datoteku, kubectl će poslati promjene napravljene nazad kroz API, koji će pažljivo primijeniti ove promjene na resurs.

Ne znaju svi komande patch и replace. Tim patch omogućava vam da promijenite dio specifikacije resursa, pružajući samo promijenjeni dio na komandnoj liniji. Tim replace radi isto kao edit, ali sve treba učiniti ručno: morate preuzeti trenutnu verziju specifikacije resursa, na primjer, koristeći kubectl get -o yaml, uredite ga, a zatim koristite replace da ažurirate resurs prema promijenjenoj specifikaciji. Tim replace neće raditi ako je došlo do bilo kakvih promjena između čitanja i zamjene resursa.

Kubernetes API

Vjerovatno ste upoznati sa metodama CoreV1().Pods().Update(), replaceNamespacedService ili patch_namespaced_deployment, ako radite s klasterima preko klijentska biblioteka za Kubernetes API koristeći neki programski jezik. Biblioteka rukuje ovim metodama putem HTTP zahtjeva koristeći metode PUT и PATCH... U čemu update и replace koristiti PUTi patch, koliko god to bilo trivijalno, koristi PATCH.

Vredi napomenuti kubectl također radi sa klasterima preko API-ja. Drugim riječima, kubectlje omotač na vrhu klijentske biblioteke za jezik Go, koji u velikoj mjeri pruža mogućnost pružanja podnaredbi u kompaktnijem i čitljivijem obliku pored standardnih API mogućnosti. Na primjer, kao što ste možda već primijetili, metoda apply nije pomenuto gore u prethodnom paragrafu. Trenutno (maj 2020. cca. prevodilac) sva logika kubectl apply, tj. kreiranje nepostojećih resursa i ažuriranje postojećih, radi u potpunosti na strani koda kubectl. Ulažu se napori na logički transfer apply na API stranu, ali je još uvijek u beta verziji. U nastavku ću pisati detaljnije.

Zakrpa po defaultu

Najbolje korišteno patch, ako želite ažurirati resurs. Ovako rade obje klijentske biblioteke na vrhu Kubernetes API-ja i kubectl (nije iznenađujuće, pošto je to omot za klijentsku biblioteku, cca. prevodilac).

Radite strateški

Svi timovi kubectl apply, edit и patch koristite metodu PATCH u HTTP zahtjevima za ažuriranje postojećeg resursa. Ako se detaljnije zadubite u implementaciju naredbi, onda sve koriste pristup strateško spajanje zakrpa za ažuriranje resursa, iako naredba patch mogu koristiti druge pristupe (više o tome u nastavku). Pristup strateškog spajanja zakrpa pokušava da se "ispravi" spajanjem isporučene specifikacije sa postojećom specifikacijom. Preciznije, pokušava da kombinuje i objekte i nizove, što znači da promene imaju tendenciju da budu aditivne. Na primjer, pokretanje naredbe patch sa novom varijablom okruženja u specifikaciji pod kontejnera, uzrokuje da se ta varijabla okruženja doda postojećim varijablama okruženja umjesto da ih prepiše. Da biste uklonili koristeći ovaj pristup, morate prisiliti vrijednost parametra na null u datoj specifikaciji. Koji od timova kubectl Da li je najbolje koristiti za ažuriranje?

Ako kreirate i upravljate svojim resursima koristeći kubectl apply, prilikom ažuriranja bolje je uvijek koristiti kubectl applyu kubectl mogao upravljati konfiguracijom i ispravno pratiti tražene promjene od aplikacije do aplikacije. Prednost uvijek koristite apply je da prati prethodno primijenjenu specifikaciju, omogućavajući joj da zna kada su svojstva specifikacije i elementi niza eksplicitno uklonjeni. Ovo vam omogućava da koristite apply za uklanjanje svojstava i elemenata niza, dok normalno strateško spajanje neće raditi. Timovi edit и patch ne ažuriraj bilješke koje kubectl apply koristi za praćenje njegovih promjena, tako da sve promjene koje se prate i vrše putem Kubernetes API-ja, ali su napravljene putem naredbi edit и patch, nevidljiv za naredne komande apply, to jest apply ne uklanja ih čak i ako se ne pojavljuju u ulaznoj specifikaciji za apply (To piše u dokumentaciji edit и patch izvršite ažuriranje korištenih bilješki apply, ali u praksi - ne).

Ako ne koristite naredbu apply, može se koristiti kao edit, i patch, birajući naredbu koja najbolje odgovara promjeni koja se vrši. Prilikom dodavanja i mijenjanja svojstava sastavnice, oba pristupa su otprilike ista. Prilikom brisanja svojstava specifikacije ili elemenata niza edit ponaša se kao jednokratno lansiranje apply, uključujući praćenje toga kakva je specifikacija bila prije i nakon što je uređena, tako da možete eksplicitno ukloniti svojstva i elemente niza iz resursa. Morate eksplicitno postaviti vrijednost svojstva na null u specifikaciji za patchda ga uklonite sa resursa. Uklanjanje elementa niza pomoću zakrpa strateškog spajanja je složenije jer zahtijeva korištenje direktiva spajanja. Pogledajte druge pristupe nadogradnje u nastavku za održivije alternative.

Implementirati metode 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, morate 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 još dva pristupa ažuriranju: JSON zakrpa za spajanje и JSON zakrpa. Pristup zakrpe spajanja JSON uzima djelomičnu Kubernetes specifikaciju kao ulaz i podržava spajanje objekata slično pristupu strateškog spajanja zakrpa. Razlika između njih je u tome što podržava samo zamjenu niza, uključujući niz kontejnera u specifikaciji pod. To znači da kada koristite JSON zakrpu za spajanje, morate osigurati potpune specifikacije za sve kontejnere u slučaju da se bilo koje svojstvo bilo kojeg spremnika promijeni. Dakle, ovaj pristup je koristan za uklanjanje elemenata iz niza u BOM-u. Na komandnoj liniji možete odabrati JSON zakrpu spajanja koristeći kubectl patch --type=merge. Kada radite sa Kubernetes API-jem, trebali biste koristiti metodu zahtjeva PATCH i instalaciju 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 niz, u kojem svaki element niza predstavlja opis promjene koja se vrši na resursu. Ovaj pristup je fleksibilniji i moćniji način za izražavanje promjena koje su napravljene, ali po cijenu navođenja izmjena koje su napravljene u zasebnom, ne-Kubernetes formatu, umjesto slanja djelomične specifikacije resursa. IN kubectl možete odabrati JSON zakrpu koristeći kubectl patch --type=json. Kada koristite Kubernetes API, ovaj pristup radi koristeći metodu zahtjeva PATCH i instalaciju content-type в application/json-patch+json.

Treba nam samopouzdanje - koristite zamjenu

U nekim slučajevima morate biti sigurni da nema promjena na resursu između vremena čitanja resursa i ažuriranja. 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 sa brojačem koji je ažuriran iz više izvora, trebali biste biti sigurni da dva izvora ne ažuriraju brojač u isto vrijeme, što uzrokuje gubitak ažuriranja. Da biste demonstrirali, zamislite niz događaja koristeći pristup patch:

  • A i B dobijaju trenutno stanje resursa iz API-ja
  • Svaki lokalno ažurira specifikaciju povećanjem brojača za jedan i dodavanjem "A" ili "B" respektivno u napomenu "ažurirano od strane"
  • I ažurira resurs malo brže
  • B ažurira resurs

Kao rezultat toga, ažuriranje A je izgubljeno. Poslednja operacija patch pobjeda, brojač se povećava za jedan umjesto za dva, a vrijednost napomene "ažurirano" završava se sa "B" i ne sadrži "A". Hajde da uporedimo gore navedeno sa onim što se dešava kada se ažuriranja izvrše korišćenjem ovog pristupa replace:

  • A i B dobijaju trenutno stanje resursa iz API-ja
  • Svaki lokalno ažurira specifikaciju povećanjem brojača za jedan i dodavanjem "A" ili "B" respektivno u napomenu "ažurirano od strane"
  • I ažurira resurs malo brže
  • B pokušava ažurirati resurs, ali je ažuriranje odbijeno od strane API-ja jer je verzija resursa u specifikaciji replace ne odgovara trenutnoj verziji resursa u Kubernetesu jer je verzija resursa povećana operacijom zamjene A.

U gornjem slučaju, B će morati ponovo preuzeti resurs, izvršiti promjene u novom stanju i pokušati ponovo replace. Ovo će uzrokovati povećanje brojača za dva i napomenu "ažurirano od strane" uključiti "AB" na kraju.

Gornji primjer implicira da prilikom izvršavanja replace Cijeli resurs je u potpunosti zamijenjen. Specifikacija koja se koristi za replace, ne smije biti djelomična, ili u dijelovima kao u apply, ali kompletan, uključujući i dodatak resourceVersion u metapodatke specifikacije. Ako niste omogućili resourceVersion ili verzija koju navedete nije aktuelna, zamjena će biti odbijena. Dakle, najbolji pristup za korištenje je replace – pročitajte izvor, ažurirajte ga i odmah ga zamijenite. Koristeći 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 -

Vrijedi napomenuti da će se sljedeće dvije naredbe, koje se izvršavaju uzastopno, uspješno izvršiti, jer deployment.yaml ne sadrži imovinu .metadata.resourceVersion

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

Čini se da je to u suprotnosti sa onim što je gore rečeno, tj. "dodavanje resourceVersion u metapodatke specifikacije." Da li je pogrešno to reći? Ne, nije, jer ako kubectl obavještenja koja niste naveli resourceVersion, pročitat će ga iz izvora i dodati specifikaciji koju ste naveli, a tek onda izvršiti replace. Budući da je ovo potencijalno opasno ako se oslanjate na atomičnost, magija djeluje u potpunosti sa strane kubectl, ne biste se trebali oslanjati na njega kada koristite klijentske biblioteke koje rade s API-jem. U tom slučaju ćete morati pročitati trenutnu specifikaciju resursa, ažurirati je i zatim izvršiti PUT zahtjev.

Ne možete napraviti zakrpu – mi vršimo zamjenu

Ponekad morate napraviti neke promjene kojima API ne može upravljati. U tim slučajevima možete prisiliti zamjenu resursa brisanjem i ponovnim kreiranjem. Ovo se radi pomoću kubectl replace --force. Izvođenje naredbe odmah uklanja resurse, a zatim ih ponovo kreira iz isporučene specifikacije. U API-ju ne postoji rukovalac "prisilne zamjene", a da biste to učinili preko API-ja, potrebno je izvršiti dvije operacije. Prvo morate izbrisati resurs postavljanjem za njega gracePeriodSeconds na nulu (0) i propagationPolicy u „Pozadina“, a zatim ponovo kreirajte ovaj resurs sa željenom specifikacijom.

Upozorenje: Ovaj pristup je potencijalno opasan i može dovesti do nedefiniranog stanja.

Prijavite se na strani servera

Kao što je gore pomenuto, programeri Kubernetesa rade na implementaciji logike apply из kubectl u Kubernetes API-ju. Logika apply dostupno u Kubernetes 1.18 putem kubectl apply --server-side ili putem API-ja koristeći metodu 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 će biti application/apply-patch+yaml.

Osim te logike kubectl postaje dostupan svima putem API-ja, apply na strani servera, prati ko je odgovoran za polja u specifikaciji, čime se omogućava siguran višestruki pristup za njegovo uređivanje bez sukoba. Drugim riječima, ako apply na strani servera će se sve više proširiti, pojavit će se univerzalno sigurno sučelje za upravljanje resursima za različite klijente, na primjer, kubectl, Pulumi ili Terraform, GitOps, kao i samostalno pisane skripte koristeći klijentske biblioteke.

Ishodi

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 nasuprot zamjeni; 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; u suprotnom, trebali biste koristiti zakrpu strateškog spajanja putem aplikacije. U najmanju ruku, očekujem da shvatite da ne možete vjerovati Google-u ili StackOerflow-u kada tražite "kubernetes primijeniti vs zamijeniti". Barem dok ovaj članak ne zamijeni trenutni odgovor.

Pravilno poređenje Kubernetes primjene, zamjene i zakrpe

izvor: www.habr.com

Dodajte komentar