Správné srovnání Kubernetes Apply, Replace a Patch

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.

Správné srovnání Kubernetes Apply, Replace a Patch

Jestliže hledat na Google je umístěna fráze „kubernetes použít vs nahradit“. odpovědět na StackOverflow, což není správné. Při hledání "kubernetes apply vs patch" první odkaz je dokumentace 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 klientská knihovna pro Kubernetes API pomocí nějakého programovacího jazyka. Knihovna zpracovává tyto metody prostřednictvím HTTP požadavků pomocí metod PUT и PATCH... Čím update и replace použití PUTa 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, kubectlje 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í na logickém přenosu 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 záplatování strategického sloučení k aktualizaci zdrojů, i když příkaz 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 applyNa 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 applyTo 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 editA 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 patchk 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: Oprava sloučení JSON и JSON patch. Přístup opravy sloučení JSON využívá jako vstup částečnou specifikaci Kubernetes a podporuje slučování objektů podobný přístupu opravování strategického sloučení. Rozdíl mezi nimi je v tom, že podporuje pouze výměnu pole, včetně pole kontejneru ve specifikaci podu. To znamená, že při použití opravy sloučení JSON musíte poskytnout úplné specifikace pro všechny kontejnery v případě, že se změní jakákoli vlastnost jakéhokoli kontejneru. Tento přístup je tedy užitečný pro odstranění prvků z pole v kusovníku. Na příkazovém řádku můžete vybrat JSON merge patch using 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ůle application/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ěď.

Správné srovnání Kubernetes Apply, Replace a Patch

Zdroj: www.habr.com

Přidat komentář