Korrekt jämförelse av Kubernetes Apply, Replace and Patch

Kubernetes har flera alternativ för att uppdatera resurser: tillämpa, redigera, korrigera och ersätt. Det råder förvirring om vad var och en gör och när de ska användas. Låt oss ta reda på det.

Korrekt jämförelse av Kubernetes Apply, Replace and Patch

Om sök på Google frasen "kubernetes tillämpa vs ersätt" finns svar på StackOverflow, vilket inte är korrekt. Vid sökning "kubernetes applicera vs patch" den första länken är dokumentationen för kubectl patch, som inte inkluderar jämförelse apply и patch. Den här artikeln kommer att titta på de olika alternativen, såväl som den korrekta användningen av var och en.

Under livscykeln för en Kubernetes-resurs (tjänst, driftsättning, ingång, etc.) behöver du ibland ändra, lägga till eller ta bort vissa egenskaper för denna resurs. Till exempel, lägg till en anteckning, öka eller minska antalet repliker.

Kubernetes CLI

Om du redan arbetar med Kubernetes-kluster via CLI är du redan bekant med apply и edit. Team apply läser resursspecifikationen från filen och gör en "upsert" till Kubernetes-klustret, d.v.s. skapar resursen om den inte finns och uppdaterar den om den finns. Team edit läser en resurs via API:t, skriver sedan resursspecifikationen till en lokal fil, som sedan öppnas i en textredigerare. När du har redigerat och sparat filen, kubectl kommer att skicka tillbaka ändringarna via API:t, som noggrant kommer att tillämpa dessa ändringar på resursen.

Alla kan inte kommandona patch и replace. Team patch låter dig ändra en del av en resursspecifikation, och tillhandahåller endast den ändrade delen på kommandoraden. Team replace fungerar på samma sätt som edit, men allt måste göras manuellt: du måste ladda ner den aktuella versionen av resursspecifikationen, till exempel med kubectl get -o yaml, redigera den och använd sedan replace att uppdatera en resurs enligt en ändrad specifikation. Team replace kommer inte att fungera om några förändringar inträffade mellan att läsa och ersätta resursen.

Kubernetes API

Du är förmodligen bekant med metoderna CoreV1().Pods().Update(), replaceNamespacedService eller patch_namespaced_deployment, om du arbetar med kluster via klientbibliotek för Kubernetes API använder något programmeringsspråk. Biblioteket hanterar dessa metoder via HTTP-förfrågningar med metoderna PUT и PATCH... Vart i update и replace begagnade PUTOch patch, hur trivialt det än må vara, använder PATCH.

Det bör noteras att kubectl fungerar även med kluster via API. Med andra ord, kubectlär ett omslag ovanpå klientbiblioteket för Go-språket, som till stor del ger möjligheten att tillhandahålla underkommandon i en mer kompakt och läsbar form utöver de vanliga API-funktionerna. Till exempel, som du kanske redan har märkt, metoden apply nämndes inte ovan i föregående stycke. För närvarande (maj 2020, cirka. översättare) all logik kubectl apply, dvs. skapa obefintliga resurser och uppdatera befintliga, fungerar helt på kodsidan kubectl. Insatser görs på logiköverföring apply till API-sidan, men den är fortfarande i beta. Jag kommer att skriva mer i detalj nedan.

Patch som standard

Används bäst patch, om du vill uppdatera resursen. Så här fungerar båda klientbiblioteken ovanpå Kubernetes API och kubectl (inte överraskande, eftersom det är ett omslag för klientbiblioteket, cirka. översättare).

Arbeta strategiskt

Alla lag kubectl apply, edit и patch använda metoden PATCH i HTTP-begäranden att uppdatera en befintlig resurs. Om du fördjupar dig i implementeringen av kommandon mer i detalj, använder de alla metoden strategisk sammanslagning för att uppdatera resurser, även om kommandot patch kan använda andra metoder (mer om detta nedan). Strategisk-merge patch-metoden försöker "få det rätt" genom att slå samman den medföljande specifikationen med den befintliga specifikationen. Mer specifikt försöker den kombinera både objekt och arrayer, vilket innebär att ändringarna tenderar att vara additiv. Till exempel att köra kommandot patch med en ny miljövariabel i podcontainerspecifikationen, gör att miljövariabeln läggs till de befintliga miljövariablerna istället för att skriva över dem. För att ta bort med detta tillvägagångssätt måste du tvinga parametervärdet till null i den angivna specifikationen. Vilket av lagen kubectl Är det bäst att använda för uppdatering?

Om du skapar och hanterar dina resurser med hjälp av kubectl apply, när du uppdaterar är det bättre att alltid använda kubectl applyTill kubectl kunde hantera konfigurationen och korrekt spåra begärda ändringar från applikation till applikation. Fördel använd alltid apply är att den håller reda på en tidigare tillämpad specifikation, så att den kan veta när specifikationsegenskaper och arrayelement explicit tas bort. Detta gör att du kan använda apply för att ta bort egenskaper och arrayelement, medan en normal strategisk sammanslagning inte kommer att fungera. Lag edit и patch uppdatera inte anteckningar som kubectl apply använder för att spåra sina ändringar, så alla ändringar som spåras och görs via Kubernetes API, men som görs genom kommandon edit и patch, osynlig för efterföljande kommandon applyDet är, apply tar inte bort dem även om de inte finns i ingångsspecifikationen för apply (Dokumentationen säger det edit и patch göra uppdateringar av de anteckningar som används apply, men i praktiken - nej).

Om du inte använder kommandot apply, kan användas som edit, och patch, välja det kommando som bäst passar den ändring som görs. När du lägger till och ändrar BOM-egenskaper är båda tillvägagångssätten ungefär desamma. När du tar bort specifikationsegenskaper eller arrayelement edit beter sig som en engångslansering apply, inklusive att hålla reda på hur specifikationen såg ut före och efter att den redigerades, så att du explicit kan ta bort egenskaper och arrayelement från en resurs. Du måste uttryckligen ställa in egenskapsvärdet till null i specifikationen för patchför att ta bort det från resursen. Att ta bort ett arrayelement med hjälp av strategisk sammanfogning är mer komplext eftersom det kräver användning av sammanslagningsdirektiv. Se andra uppgraderingsmetoder nedan för mer genomförbara alternativ.

Att implementera uppdateringsmetoder i klientbiblioteket som beter sig på samma sätt som kommandona ovan kubectl, bör anges i förfrågningar content-type в application/strategic-merge-patch+json. Om du vill ta bort egenskaper i en specifikation måste du uttryckligen ställa in deras värden till null på liknande sätt kubectl patch. Om du behöver ta bort arrayelement bör du inkludera merge-direktiv i uppdateringsspecifikationen eller använda en annan metod för uppdateringar.

Andra metoder för uppdateringar

Kubernetes stöder två andra uppdateringsmetoder: JSON merge patch и JSON patch. JSON merge patch-metoden tar en partiell Kubernetes-specifikation som indata och stöder sammanslagning av objekt som liknar strategic-merge patching. Skillnaden mellan de två är att den bara stöder arrayersättning, inklusive container arrayen i pod-specifikationen. Detta innebär att när du använder en JSON merge patch, måste du tillhandahålla fullständiga specifikationer för alla behållare om någon egenskap hos någon behållare ändras. Så det här tillvägagångssättet är användbart för att ta bort element från en array i en BOM. På kommandoraden kan du välja JSON merge patch med hjälp av kubectl patch --type=merge. När du arbetar med Kubernetes API bör du använda förfrågningsmetoden PATCH och installation content-type в application/merge-patch+json.

JSON patch-metoden, snarare än att tillhandahålla en partiell specifikation av en resurs, använder att tillhandahålla de ändringar du vill göra i resursen som en array, där varje element i arrayen representerar en beskrivning av ändringen som görs i resursen. Detta tillvägagångssätt är ett mer flexibelt och kraftfullt sätt att uttrycka de ändringar som görs, men till priset av att lista ändringarna som görs i ett separat, icke-Kubernetes-format, snarare än att skicka en partiell resursspecifikation. I kubectl du kan välja JSON-patch med hjälp av kubectl patch --type=json. När du använder Kubernetes API fungerar detta tillvägagångssätt med förfrågningsmetoden PATCH och installation content-type в application/json-patch+json.

Vi behöver förtroende - använd ersätt

I vissa fall måste du vara säker på att inga ändringar görs i en resurs mellan det att resursen läses och när den uppdateras. Med andra ord bör du se till att alla ändringar kommer att ske atom-. I det här fallet bör du använda resurser för att uppdatera replace. Till exempel, om du har en ConfigMap med en räknare som uppdateras av flera källor, bör du vara säker på att två källor inte uppdaterar räknaren samtidigt, vilket gör att uppdateringen går förlorad. För att demonstrera, föreställ dig ett händelseförlopp med hjälp av metoden patch:

  • A och B får resursens aktuella tillstånd från API:et
  • Var och en uppdaterar specifikationen lokalt genom att öka räknaren med en och även lägga till "A" respektive "B" till "updated-by"-anteckningen
  • Och det uppdaterar resursen lite snabbare
  • B uppdaterar resursen

Som ett resultat går uppdatering A förlorad. Sista operationen patch vinner, räknaren ökas med en istället för två, och värdet på "updated-by"-noten slutar med "B" och innehåller inte "A". Låt oss jämföra ovanstående med vad som händer när uppdateringar görs med metoden replace:

  • A och B får resursens aktuella tillstånd från API:et
  • Var och en uppdaterar specifikationen lokalt genom att öka räknaren med en och även lägga till "A" respektive "B" till "updated-by"-anteckningen
  • Och det uppdaterar resursen lite snabbare
  • B försöker uppdatera resursen, men uppdateringen avvisas av API:t eftersom resursversionen finns i specifikationen replace matchar inte den aktuella versionen av resursen i Kubernetes eftersom versionen av resursen utökades med A:s ersättningsoperation.

I ovanstående fall måste B återhämta resursen, göra ändringar i det nya tillståndet och försöka igen replace. Detta kommer att göra att räknaren ökas med två och att "uppdaterad av"-noteringen inkluderar "AB" i slutet.

Ovanstående exempel innebär att när du kör replace Hela resursen är helt ersatt. Specifikation som används för replace, får inte vara partiell eller i delar som i apply, men komplett, inklusive tillägget resourceVersion i specifikationens metadata. Om du inte har aktiverat resourceVersion eller versionen du tillhandahåller inte är aktuell, kommer ersättningen att avvisas. Så det bästa sättet att använda är replace – läs resursen, uppdatera den och byt ut den omedelbart. Använder sig av kubectl, det kan se ut så här:

$ kubectl get deployment my-deployment -o json 
    | jq '.spec.template.spec.containers[0].env[1].value = "new value"' 
    | kubectl replace -f -

Det är värt att notera att följande två kommandon, som körs sekventiellt, kommer att köras framgångsrikt, eftersom deployment.yaml innehåller inte egendom .metadata.resourceVersion

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

Detta torde strida mot vad som sagts ovan, d.v.s. "tillägger resourceVersion in i specifikationens metadata." Är det fel att säga det? Nej, det är det inte, för om kubectl märker att du inte specificerat resourceVersion, kommer den att läsa den från resursen och lägga till den i specifikationen du angav, och först därefter köra den replace. Eftersom detta är potentiellt farligt om du förlitar dig på atomicitet, fungerar magin helt och hållet vid sidan av kubectl, bör du inte lita på det när du använder klientbibliotek som fungerar med API:et. I det här fallet måste du läsa den aktuella resursspecifikationen, uppdatera den och sedan köra PUT begäran.

Du kan inte göra en patch – vi byter ut

Ibland behöver du göra några ändringar som inte kan hanteras av API:et. I dessa fall kan du tvinga fram utbyte av resursen genom att ta bort och återskapa den. Detta görs med hjälp av kubectl replace --force. Att köra kommandot tar omedelbart bort resurserna och återskapar dem sedan från den medföljande specifikationen. Det finns ingen "force replace"-hanterare i API:t, och för att göra det via API:et måste du utföra två operationer. Först måste du ta bort resursen genom att ställa in den gracePeriodSeconds till noll (0) och propagationPolicy i "Bakgrund" och återskapa sedan denna resurs med önskad specifikation.

Varning: Detta tillvägagångssätt är potentiellt farligt och kan leda till ett odefinierat tillstånd.

Applicera på serversidan

Som nämnts ovan arbetar Kubernetes-utvecklare på att implementera logiken apply av kubectl i Kubernetes API. Logik apply tillgänglig i Kubernetes 1.18 via kubectl apply --server-side eller via API:t med metoden PATCH с content-type application/apply-patch+YAML.

Obs: JSON är också giltigt YAML, så du kan skicka specifikationen som JSON även om content-type kommer application/apply-patch+yaml.

Förutom den logiken kubectl blir tillgänglig för alla via API, apply på serversidan, håller reda på vem som är ansvarig för fälten i specifikationen, vilket möjliggör säker multipelåtkomst för dess konfliktfria redigering. Med andra ord, om apply på serversidan kommer att bli mer utbredd, ett universellt säkert resurshanteringsgränssnitt kommer att dyka upp för olika klienter, till exempel kubectl, Pulumi eller Terraform, GitOps, såväl som självskrivna skript som använder klientbibliotek.

Resultat av

Jag hoppas att denna korta översikt över olika sätt att uppdatera resurser i kluster var till hjälp för dig. Det är bra att veta att det inte bara är applicera mot ersätt, det är möjligt att uppdatera en resurs med hjälp av applicera, redigera, korrigera eller ersätt. När allt kommer omkring har i princip varje tillvägagångssätt sitt eget tillämpningsområde. För atomära förändringar är utbyte att föredra, annars bör du använda strategisk sammanfogningsplåster via applicera. Åtminstone förväntar jag mig att du förstår att du inte kan lita på Google eller StackOerflow när du söker efter "kubernetes apply vs replace". Åtminstone tills den här artikeln ersätter det nuvarande svaret.

Korrekt jämförelse av Kubernetes Apply, Replace and Patch

Källa: will.com

Lägg en kommentar