Korrekt sammenligning af Kubernetes Apply, Replace og Patch

Kubernetes har flere muligheder for at opdatere ressourcer: anvend, rediger, patch og erstat. Der er forvirring om, hvad hver enkelt gør, og hvornår de skal bruges. Lad os finde ud af det.

Korrekt sammenligning af Kubernetes Apply, Replace og Patch

Hvis søg på Google sætningen "kubernetes anvende vs erstatte" er placeret svar til StackOverflow, hvilket ikke er korrekt. Ved søgning "kubernetes apply vs patch" det første link er dokumentationen til kubectl patch, som ikke omfatter sammenligning apply и patch. Denne artikel vil se på de forskellige muligheder, samt den korrekte brug af hver enkelt.

I løbet af en Kubernetes-ressources livscyklus (tjeneste, implementering, indgang osv.), er du nogle gange nødt til at ændre, tilføje eller fjerne nogle egenskaber for denne ressource. Tilføj f.eks. en note, øg eller mindsk antallet af replikaer.

Kubernetes CLI

Hvis du allerede arbejder med Kubernetes-klynger via CLI, er du allerede bekendt med apply и edit. Hold apply læser ressourcespecifikationen fra filen og laver en "upsert" til Kubernetes-klyngen, dvs. opretter ressourcen, hvis den ikke findes, og opdaterer den, hvis den findes. Hold edit læser en ressource via API'et, skriver derefter ressourcespecifikationen til en lokal fil, som derefter åbnes i en teksteditor. Når du har redigeret og gemt filen, kubectl vil sende ændringerne tilbage gennem API'en, som omhyggeligt vil anvende disse ændringer på ressourcen.

Ikke alle kender kommandoerne patch и replace. Hold patch giver dig mulighed for at ændre en del af en ressourcespecifikation, idet du kun giver den ændrede del på kommandolinjen. Hold replace virker det samme som edit, men alt skal gøres manuelt: du skal downloade den aktuelle version af ressourcespecifikationen, f.eks. kubectl get -o yaml, rediger det, og brug derefter replace at opdatere en ressource i henhold til en ændret specifikation. Hold replace vil ikke fungere, hvis der er sket ændringer mellem læsning og udskiftning af ressourcen.

Kubernetes API

Du er sikkert bekendt med metoderne CoreV1().Pods().Update(), replaceNamespacedService eller patch_namespaced_deployment, hvis du arbejder med klynger via klientbibliotek til Kubernetes API bruge et eller andet programmeringssprog. Biblioteket håndterer disse metoder via HTTP-anmodninger ved hjælp af metoderne PUT и PATCH... Hvori update и replace brug PUTOg patch, uanset hvor trivielt det måtte være, bruger PATCH.

Det skal bemærkes, at kubectl fungerer også med klynger via API. Med andre ord, kubectler en indpakning oven på klientbiblioteket til Go-sproget, som i vid udstrækning giver mulighed for at levere underkommandoer i en mere kompakt og læsbar form ud over standard API-funktionerne. For eksempel, som du måske allerede har bemærket, metoden apply var ikke nævnt ovenfor i det foregående afsnit. I øjeblikket (maj 2020, ca. oversætter) al logik kubectl apply, dvs. oprettelse af ikke-eksisterende ressourcer og opdatering af eksisterende, fungerer udelukkende på kodesiden kubectl. Der gøres en indsats om logisk overførsel apply til API-siden, men den er stadig i beta. Jeg vil skrive mere detaljeret nedenfor.

Patch som standard

Bedst brugt patch, hvis du vil opdatere ressourcen. Sådan fungerer begge klientbiblioteker oven på Kubernetes API og kubectl (ikke overraskende, da det er en indpakning til klientbiblioteket, ca. oversætter).

Arbejd strategisk

Alle hold kubectl apply, edit и patch bruge metoden PATCH i HTTP-anmodninger om at opdatere en eksisterende ressource. Hvis du dykker ned i implementeringen af ​​kommandoer mere detaljeret, så bruger de alle fremgangsmåden strategisk-fusion patching at opdatere ressourcer, selvom kommandoen patch kan bruge andre tilgange (mere om dette nedenfor). Strategic-merge patching-tilgangen forsøger at "få det rigtigt" ved at flette den leverede specifikation med den eksisterende specifikation. Mere specifikt forsøger den at kombinere både objekter og arrays, hvilket betyder, at ændringerne har en tendens til at være additive. For eksempel at køre kommandoen patch med en ny miljøvariabel i pod-beholderspecifikationen, får den miljøvariabel til at blive tilføjet til de eksisterende miljøvariabler i stedet for at overskrive dem. For at fjerne ved hjælp af denne fremgangsmåde skal du tvinge parameterværdien til null i den angivne specifikation. Hvilket af holdene kubectl Er det bedst at bruge til opdatering?

Hvis du opretter og administrerer dine ressourcer vha kubectl apply, når du opdaterer, er det bedre altid at bruge kubectl applyså det kubectl kunne administrere konfiguration og korrekt spore anmodede ændringer fra applikation til applikation. Fordel brug altid apply er, at den holder styr på en tidligere anvendt specifikation, så den kan vide, hvornår specifikationsegenskaber og array-elementer er eksplicit fjernet. Dette giver dig mulighed for at bruge apply at fjerne egenskaber og array-elementer, mens en normal strategisk fletning ikke vil fungere. Hold edit и patch opdater ikke noter, der kubectl apply bruger til at spore sine ændringer, så alle ændringer, der spores og foretages gennem Kubernetes API, men foretages gennem kommandoer edit и patch, usynlig for efterfølgende kommandoer applyDet vil sige, apply fjerner dem ikke, selvom de ikke fremgår af inputspecifikationen for apply (Dokumentationen siger det edit и patch foretage opdateringer til de brugte noter apply, men i praksis - nej).

Hvis du ikke bruger kommandoen apply, kan bruges som editOg patch, ved at vælge den kommando, der passer bedst til den ændring, der foretages. Når du tilføjer og ændrer styklisteegenskaber, er begge tilgange nogenlunde de samme. Ved sletning af specifikationsegenskaber eller array-elementer edit opfører sig som en engangslancering apply, herunder at holde styr på, hvordan specifikationen var før og efter den blev redigeret, så du eksplicit kan fjerne egenskaber og array-elementer fra en ressource. Du skal udtrykkeligt indstille egenskabsværdien til null i specifikationen for patchfor at fjerne det fra ressourcen. Fjernelse af et array-element ved hjælp af strategisk-flet-patching er mere komplekst, fordi det kræver brug af merge-direktiver. Se andre opgraderingsmetoder nedenfor for mere levedygtige alternativer.

At implementere opdateringsmetoder i klientbiblioteket, der opfører sig på samme måde som kommandoerne ovenfor kubectl, skal angives i anmodninger content-type в application/strategic-merge-patch+json. Hvis du vil fjerne egenskaber i en specifikation, skal du udtrykkeligt indstille deres værdier til null på lignende måde kubectl patch. Hvis du har brug for at fjerne array-elementer, bør du inkludere flettedirektiver i opdateringsspecifikationen eller bruge en anden tilgang til opdateringer.

Andre tilgange til opdateringer

Kubernetes understøtter to andre opdateringstilgange: JSON-fletningspatch и JSON-patch. JSON-fletningspatch-tilgangen tager en delvis Kubernetes-specifikation som input og understøtter fletteobjekter, der svarer til strategic-merge patching-tilgangen. Forskellen mellem de to er, at den kun understøtter array-erstatning, inklusive container-arrayet i pod-specifikationen. Dette betyder, at når du bruger en JSON-fletningspatch, skal du angive fuldstændige specifikationer for alle containere i tilfælde af, at en egenskab ved en container ændres. Så denne tilgang er nyttig til at fjerne elementer fra et array i en stykliste. På kommandolinjen kan du vælge JSON merge patch vha kubectl patch --type=merge. Når du arbejder med Kubernetes API, bør du bruge anmodningsmetoden PATCH og installation content-type в application/merge-patch+json.

JSON patch-tilgangen bruger, i stedet for at give en delvis specifikation af en ressource, at angive de ændringer, du vil foretage til ressourcen, som et array, hvor hvert element i arrayet repræsenterer en beskrivelse af den ændring, der foretages til ressourcen. Denne tilgang er en mere fleksibel og kraftfuld måde at udtrykke de ændringer, der foretages på, men på bekostning af at liste ændringerne, der foretages i et separat, ikke-Kubernetes-format, i stedet for at sende en delvis ressourcespecifikation. I kubectl du kan vælge JSON patch vha kubectl patch --type=json. Når du bruger Kubernetes API, fungerer denne tilgang ved hjælp af anmodningsmetoden PATCH og installation content-type в application/json-patch+json.

Vi har brug for tillid - brug erstatning

I nogle tilfælde skal du være sikker på, at der ikke foretages ændringer i en ressource mellem det tidspunkt, hvor ressourcen læses, og når den er opdateret. Med andre ord bør du sørge for, at alle ændringer bliver atomar. I dette tilfælde skal du bruge for at opdatere ressourcer replace. For eksempel, hvis du har et ConfigMap med en tæller, der er opdateret af flere kilder, skal du være sikker på, at to kilder ikke opdaterer tælleren på samme tid, hvilket medfører, at opdateringen går tabt. For at demonstrere, forestil dig en sekvens af begivenheder ved hjælp af tilgangen patch:

  • A og B får ressourcens aktuelle tilstand fra API'et
  • Hver enkelt opdaterer specifikationen lokalt ved at øge tælleren med én og også tilføje henholdsvis "A" eller "B" til noten "opdateret af"
  • Og det opdaterer ressourcen lidt hurtigere
  • B opdaterer ressourcen

Som følge heraf går opdatering A tabt. Sidste operation patch vinder, øges tælleren med én i stedet for to, og værdien af ​​"updated-by"-sedlen slutter med "B" og indeholder ikke "A". Lad os sammenligne ovenstående med, hvad der sker, når opdateringer udføres ved hjælp af fremgangsmåden replace:

  • A og B får ressourcens aktuelle tilstand fra API'et
  • Hver enkelt opdaterer specifikationen lokalt ved at øge tælleren med én og også tilføje henholdsvis "A" eller "B" til noten "opdateret af"
  • Og det opdaterer ressourcen lidt hurtigere
  • B forsøger at opdatere ressourcen, men opdateringen afvises af API'en, fordi ressourceversionen er i specifikationen replace stemmer ikke overens med den aktuelle version af ressourcen i Kubernetes, fordi versionen af ​​ressourcen blev forøget med A's erstatningsoperation.

I ovenstående tilfælde bliver B nødt til at hente ressourcen igen, foretage ændringer i den nye tilstand og prøve igen replace. Dette vil medføre, at tælleren øges med to, og "opdateret af"-noten til at inkludere "AB" i slutningen.

Ovenstående eksempel antyder, at når du udfører replace Hele ressourcen er fuldstændig udskiftet. Specifikation brugt til replace, må ikke være delvist eller i dele som i apply, men komplet, inklusive tilføjelsen resourceVersion ind i specifikationsmetadataene. Hvis du ikke har aktiveret resourceVersion eller den version, du angiver, ikke er aktuel, vil erstatningen blive afvist. Så den bedste tilgang til at bruge er replace – læs ressourcen, opdater den og udskift den med det samme. Ved brug af kubectl, kan det se sådan ud:

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

Det er værd at bemærke, at de følgende to kommandoer, der udføres sekventielt, vil udføres med succes, da deployment.yaml indeholder ikke ejendom .metadata.resourceVersion

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

Dette synes at være i modstrid med det, der blev sagt ovenfor, dvs. "tilføjer resourceVersion ind i specifikationsmetadataene." Er det forkert at sige det? Nej, det er det ikke, for hvis kubectl bemærker, at du ikke har angivet resourceVersion, vil den læse den fra ressourcen og tilføje den til den specifikation, du har angivet, og først derefter udføre den replace. Fordi dette er potentielt farligt, hvis du stoler på atomicitet, virker magien helt på siden kubectl, bør du ikke stole på det, når du bruger klientbiblioteker, der fungerer med API'en. I dette tilfælde skal du læse den aktuelle ressourcespecifikation, opdatere den og derefter udføre PUT anmodning.

Du kan ikke lave en patch - vi laver en erstatning

Nogle gange skal du lave nogle ændringer, som ikke kan håndteres af API'en. I disse tilfælde kan du gennemtvinge udskiftning af ressourcen ved at slette og genskabe den. Dette gøres vha kubectl replace --force. Kørsel af kommandoen fjerner ressourcerne øjeblikkeligt og genskaber dem derefter fra den medfølgende specifikation. Der er ingen "force replace"-handler i API'et, og for at gøre det gennem API'et skal du udføre to operationer. Først skal du slette ressourcen ved at indstille for den gracePeriodSeconds til nul (0) og propagationPolicy i "Baggrund", og genskab derefter denne ressource med den ønskede specifikation.

Advarsel: Denne tilgang er potentielt farlig og kan føre til en udefineret tilstand.

Anvend på serversiden

Som nævnt ovenfor arbejder Kubernetes-udviklere på at implementere logikken apply af kubectl i Kubernetes API. Logikker apply tilgængelig i Kubernetes 1.18 via kubectl apply --server-side eller via API'et ved hjælp af metoden PATCH с content-type application/apply-patch+YAML.

Bemærk: JSON er også gyldig YAML, så du kan sende specifikationen som JSON, selvom content-type vil application/apply-patch+yaml.

Udover den logik kubectl bliver tilgængelig for alle via API, apply på serversiden holder styr på, hvem der er ansvarlig for felterne i specifikationen, og tillader dermed sikker multipeladgang til dens konfliktfrie redigering. Med andre ord, hvis apply på serversiden vil blive mere udbredt, vil en universel sikker ressourcestyringsgrænseflade dukke op for forskellige klienter, for eksempel kubectl, Pulumi eller Terraform, GitOps, samt selvskrevne scripts ved hjælp af klientbiblioteker.

Resultaterne af

Jeg håber, at denne korte oversigt over forskellige måder at opdatere ressourcer på i klynger var nyttig for dig. Det er godt at vide, at det ikke kun er anvende versus erstatning; det er muligt at opdatere en ressource ved hjælp af anvende, redigere, patch eller erstatte. I princippet har hver tilgang trods alt sit eget anvendelsesområde. For atomære ændringer er udskiftning at foretrække; ellers skal du bruge strategisk fletnings-patch via applicering. I det mindste forventer jeg, at du forstår, at du ikke kan stole på Google eller StackOerflow, når du søger efter "kubernetes apply vs replace". I hvert fald indtil denne artikel erstatter det nuværende svar.

Korrekt sammenligning af Kubernetes Apply, Replace og Patch

Kilde: www.habr.com

Tilføj en kommentar