Kubernetes má několik možností aktualizace zdrojů: použít, upravit, opravit a nahradit. Existuje zmatek v tom, co každý z nich dělá a kdy je použít. Pojďme na to přijít.
Jestliže kubectl patch
, která nezahrnuje srovnání apply
и patch
. Tento článek se podívá na různé možnosti a také na správné použití každé z nich.
Během životního cyklu prostředku Kubernetes (služba, nasazení, vstup atd.) je někdy potřeba změnit, přidat nebo odebrat některé vlastnosti tohoto prostředku. Můžete například přidat poznámku, zvýšit nebo snížit počet replik.
Kubernetes CLI
Pokud již pracujete s clustery Kubernetes prostřednictvím rozhraní CLI, již to znáte apply
и edit
. tým apply
načte specifikaci prostředku ze souboru a udělá „upsert“ do clusteru Kubernetes, tzn. vytvoří zdroj, pokud neexistuje, a aktualizuje jej, pokud existuje. tým edit
přečte zdroj prostřednictvím rozhraní API, poté zapíše specifikaci zdroje do místního souboru, který se poté otevře v textovém editoru. Po úpravě a uložení souboru kubectl
odešle provedené změny zpět prostřednictvím rozhraní API, které tyto změny pečlivě použije na zdroj.
Ne každý zná příkazy patch
и replace
. tým patch
umožňuje změnit část specifikace prostředku a poskytnout pouze změněnou část na příkazovém řádku. tým replace
funguje stejně jako edit
, ale vše je třeba provést ručně: musíte si stáhnout aktuální verzi specifikace zdroje, například pomocí kubectl get -o yaml
, upravte jej a poté použijte replace
aktualizovat zdroj podle změněné specifikace. tým replace
nebude fungovat, pokud mezi čtením a nahrazením zdroje došlo k jakýmkoli změnám.
Kubernetes API
Metody pravděpodobně znáte CoreV1().Pods().Update()
, replaceNamespacedService
nebo patch_namespaced_deployment
, pokud pracujete s clustery přes PUT
и PATCH
... Čím update
и replace
použití PUT
a patch
, bez ohledu na to, jak triviální to může být, používá PATCH
.
Je třeba poznamenat, že kubectl
také pracuje s clustery přes API. Jinými slovy, kubectl
je obal nad klientskou knihovnou pro jazyk Go, který do značné míry poskytuje možnost poskytovat dílčí příkazy v kompaktnější a čitelnější formě kromě standardních funkcí API. Například, jak jste si již mohli všimnout, metoda apply
nebylo uvedeno výše v předchozím odstavci. Aktuálně (květen 2020, Cca. překladatel) veškerá logika kubectl apply
, tj. vytváření neexistujících zdrojů a aktualizace stávajících, funguje výhradně na straně kódu kubectl
. Vyvíjí se úsilí apply
na stranu API, ale je stále ve verzi beta. Podrobněji napíšu níže.
Patch ve výchozím nastavení
Nejlépe aplikovat patch
, pokud chcete zdroj aktualizovat. Takto fungují obě klientské knihovny nad rozhraním Kubernetes API a kubectl
(není překvapivé, protože jde o obal pro klientskou knihovnu, Cca. překladatel).
Pracujte strategicky
Všechny týmy kubectl
apply
, edit
и patch
použít metodu PATCH
v požadavcích HTTP na aktualizaci existujícího zdroje. Pokud se podrobněji ponoříte do implementace příkazů, pak všechny používají tento přístup patch
může použít jiné přístupy (více o tom níže). Přístup opravování strategického sloučení se pokouší „dosáhnout správného výsledku“ sloučením dodané specifikace se stávající specifikací. Přesněji řečeno, snaží se kombinovat objekty i pole, což znamená, že změny mají tendenci být aditivní. Například spuštění příkazu patch
s novou proměnnou prostředí ve specifikaci kontejneru pod způsobí, že se tato proměnná prostředí přidá ke stávajícím proměnným prostředí, místo aby je přepsala. Chcete-li odstranit pomocí tohoto přístupu, musíte vynutit hodnotu parametru null v poskytnuté specifikaci. Který z týmů kubectl
Je nejlepší použít pro aktualizaci?
Pokud vytváříte a spravujete své zdroje pomocí kubectl apply
, při aktualizaci je lepší vždy použít kubectl apply
Na kubectl
mohl spravovat konfiguraci a správně sledovat požadované změny z aplikace do aplikace. Vždy použijte výhodu apply
spočívá v tom, že sleduje dříve použitou specifikaci, což mu umožňuje vědět, kdy jsou vlastnosti specifikace a prvky pole explicitně odstraněny. To vám umožní používat apply
k odstranění vlastností a prvků pole, zatímco normální strategické sloučení nebude fungovat. Týmy edit
и patch
neaktualizujte poznámky, že kubectl apply
používá ke sledování svých změn, takže všechny změny, které jsou sledovány a prováděny prostřednictvím rozhraní Kubernetes API, ale prováděné prostřednictvím příkazů edit
и patch
, neviditelný pro následující příkazy apply
To znamená, že apply
neodstraní je, i když se neobjeví ve vstupní specifikaci pro apply
(Dokumentace to říká edit
и patch
provádět aktualizace použitých poznámek apply
, ale v praxi - ne).
Pokud nepoužijete příkaz apply
, lze použít jako edit
A patch
, vyberte příkaz, který nejlépe odpovídá prováděné změně. Při přidávání a změně vlastností kusovníku jsou oba přístupy zhruba stejné. Při odstraňování vlastností specifikace nebo prvků pole edit
se chová jako jednorázové spuštění apply
, včetně sledování toho, jaká byla specifikace před a po úpravě, takže můžete explicitně odebrat vlastnosti a prvky pole ze zdroje. Ve specifikaci pro musíte explicitně nastavit hodnotu vlastnosti na null patch
k odstranění ze zdroje. Odebrání prvku pole pomocí záplatování strategického sloučení je složitější, protože vyžaduje použití direktiv sloučení. Další životaschopné alternativy naleznete níže v dalších přístupech k upgradu.
Implementovat metody aktualizace v klientské knihovně, které se chovají podobně jako výše uvedené příkazy kubectl
, by mělo být nastaveno v žádostech content-type
в application/strategic-merge-patch+json
. Pokud chcete odebrat vlastnosti ve specifikaci, musíte podobným způsobem explicitně nastavit jejich hodnoty na null kubectl patch
. Pokud potřebujete odstranit prvky pole, měli byste zahrnout direktivy sloučení do specifikace aktualizace nebo použít jiný přístup k aktualizacím.
Jiné přístupy k aktualizacím
Kubernetes podporuje dva další přístupy k aktualizaci: kubectl patch --type=merge
. Při práci s Kubernetes API byste měli použít metodu požadavku PATCH
a instalace content-type
в application/merge-patch+json
.
Přístup opravy JSON, spíše než poskytování částečné specifikace zdroje, používá poskytování změn, které chcete provést ve zdroji, jako pole, ve kterém každý prvek pole představuje popis změny, která se ve zdroji provádí. Tento přístup je flexibilnější a výkonnější způsob, jak vyjádřit prováděné změny, ale za cenu výpisu provedených změn v samostatném formátu, který nepochází z Kubernetes, místo toho, aby se posílala částečná specifikace zdroje. V kubectl
můžete vybrat opravu JSON pomocí kubectl patch --type=json
. Při použití Kubernetes API tento přístup funguje pomocí metody požadavku PATCH
a instalace content-type
в application/json-patch+json
.
Potřebujeme důvěru – použijte nahradit
V některých případech si musíte být jisti, že mezi přečtením zdroje a jeho aktualizací nebyly provedeny žádné změny prostředku. Jinými slovy, měli byste se ujistit, že všechny změny budou atomový. V tomto případě byste měli použít k aktualizaci zdrojů replace
. Pokud například máte ConfigMap s čítačem, který je aktualizován z více zdrojů, měli byste si být jisti, že dva zdroje neaktualizují čítač současně, což způsobí ztrátu aktualizace. Pro demonstraci si představte sled událostí pomocí tohoto přístupu patch
:
- A a B získají aktuální stav zdroje z API
- Každý z nich lokálně aktualizuje specifikaci zvýšením počítadla o jednu a také přidáním „A“ nebo „B“ do poznámky „aktualizováno“.
- A aktualizuje zdroj o něco rychleji
- B aktualizuje zdroj
V důsledku toho je aktualizace A ztracena. Poslední operace patch
vyhraje, počítadlo se zvýší o jedničku místo o dvě a hodnota poznámky „updated-by“ končí „B“ a neobsahuje „A“. Porovnejme výše uvedené s tím, co se stane, když jsou aktualizace provedeny pomocí tohoto přístupu replace
:
- A a B získají aktuální stav zdroje z API
- Každý z nich lokálně aktualizuje specifikaci zvýšením počítadla o jednu a také přidáním „A“ nebo „B“ do poznámky „aktualizováno“.
- A aktualizuje zdroj o něco rychleji
- B se pokouší aktualizovat prostředek, ale aktualizace je odmítnuta rozhraním API, protože verze prostředku je ve specifikaci
replace
neodpovídá aktuální verzi prostředku v Kubernetes, protože verze prostředku byla zvýšena operací nahrazení A.
Ve výše uvedeném případě bude B muset znovu načíst prostředek, provést změny v novém stavu a zkusit to znovu replace
. To způsobí, že počítadlo se zvýší o dvě a poznámka "updated-by" bude obsahovat "AB" na konci.
Výše uvedený příklad naznačuje, že při provádění replace
Celý zdroj je kompletně vyměněn. Specifikace použitá pro replace
, nesmí být částečné nebo po částech jako v apply
, ale kompletní včetně doplnění resourceVersion
do metadat specifikace. Pokud jste to nepovolili resourceVersion
nebo vámi poskytnutá verze není aktuální, náhrada bude zamítnuta. Takže nejlepší přístup k použití je replace
– přečtěte si zdroj, aktualizujte jej a okamžitě vyměňte. Použitím kubectl
, může to vypadat takto:
$ kubectl get deployment my-deployment -o json
| jq '.spec.template.spec.containers[0].env[1].value = "new value"'
| kubectl replace -f -
Stojí za zmínku, že následující dva příkazy, prováděné sekvenčně, budou úspěšně provedeny, protože deployment.yaml
neobsahuje vlastnost .metadata.resourceVersion
$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml
To by se zdálo v rozporu s tím, co bylo řečeno výše, tzn. "přidání resourceVersion
do metadat specifikace." Je špatné to říci? Ne, není, protože pokud kubectl
upozornění, které jste nespecifikovali resourceVersion
, přečte jej ze zdroje a přidá jej ke specifikaci, kterou jste zadali, a teprve poté jej provede replace
. Protože to je potenciálně nebezpečné, pokud se spoléháte na atomicitu, magie funguje zcela stranou kubectl
, neměli byste na něj spoléhat při používání klientských knihoven, které pracují s API. V tomto případě si budete muset přečíst aktuální specifikaci prostředku, aktualizovat ji a poté spustit PUT
žádost.
Nemůžete provést opravu – my provedeme výměnu
Někdy je potřeba provést nějaké změny, které API nezvládne. V těchto případech můžete vynutit nahrazení prostředku jeho odstraněním a opětovným vytvořením. To se provádí pomocí kubectl replace --force
. Spuštění příkazu okamžitě odstraní prostředky a poté je znovu vytvoří z dodané specifikace. V rozhraní API není žádná obslužná rutina „vynutit nahrazení“, a abyste to mohli provést prostřednictvím rozhraní API, musíte provést dvě operace. Nejprve musíte odstranit zdroj nastavením pro něj gracePeriodSeconds
na nulu (0) a propagationPolicy
v „Pozadí“ a poté znovu vytvořte tento zdroj s požadovanou specifikací.
Upozornění: Tento přístup je potenciálně nebezpečný a může vést k nedefinovanému stavu.
Použít na straně serveru
Jak bylo uvedeno výše, vývojáři Kubernetes pracují na implementaci logiky apply
z kubectl
v Kubernetes API. Logika apply
k dispozici v Kubernetes 1.18 přes kubectl apply --server-side
nebo prostřednictvím API pomocí metody PATCH
с content-type
application/apply-patch+YAML
.
Poznámka: JSON je také platný YAML, takže specifikaci můžete odeslat jako JSON, i když
content-type
vůleapplication/apply-patch+yaml
.
Kromě té logiky kubectl
bude k dispozici všem prostřednictvím API, apply
na straně serveru sleduje, kdo je zodpovědný za pole ve specifikaci, a umožňuje tak bezpečný vícenásobný přístup pro jejich bezkonfliktní úpravy. Jinými slovy, pokud apply
na straně serveru se rozšíří, objeví se univerzální zabezpečené rozhraní pro správu zdrojů pro různé klienty, například kubectl, Pulumi nebo Terraform, GitOps, stejně jako skripty psané samostatně pomocí klientských knihoven.
Výsledky
Doufám, že vám tento krátký přehled různých způsobů aktualizace zdrojů v clusterech pomohl. Je dobré vědět, že nejde jen o použití versus nahrazení; je možné aktualizovat zdroj pomocí použití, úpravy, opravy nebo nahrazení. Koneckonců, v zásadě má každý přístup svou vlastní oblast použití. Pro atomické změny je vhodnější nahradit, jinak byste měli použít strategickou záplatu pro sloučení pomocí Apply. Přinejmenším očekávám, že pochopíte, že při hledání „kubernetes použít vs nahradit“ nemůžete věřit Googlu nebo StackOerflow. Alespoň do té doby, než tento článek nahradí aktuální odpověď.
Zdroj: www.habr.com