Riktig sammenligning av Kubernetes Apply, Replace and Patch

Kubernetes har flere alternativer for å oppdatere ressurser: bruk, rediger, oppdatering og erstatt. Det er forvirring om hva hver enkelt gjør og når de skal brukes. La oss finne ut av det.

Riktig sammenligning av Kubernetes Apply, Replace and Patch

Hvis søk på Google uttrykket "kubernetes gjelder vs erstatte" er plassert svar på StackOverflow, som ikke er riktig. Ved søk "kubernetes gjelder vs patch" den første lenken er dokumentasjonen for kubectl patch, som ikke inkluderer sammenligning apply и patch. Denne artikkelen vil se på de forskjellige alternativene, samt riktig bruk av hver enkelt.

I løpet av livssyklusen til en Kubernetes-ressurs (tjeneste, distribusjon, ingress, etc.), må du noen ganger endre, legge til eller fjerne noen egenskaper for denne ressursen. Du kan for eksempel legge til et notat, øke eller redusere antallet replikaer.

Kubernetes CLI

Hvis du allerede jobber med Kubernetes-klynger via CLI, er du allerede kjent med apply и edit. Team apply leser ressursspesifikasjonen fra filen og gjør en "upsert" til Kubernetes-klyngen, dvs. oppretter ressursen hvis den ikke eksisterer og oppdaterer den hvis den eksisterer. Team edit leser en ressurs via API, skriver deretter ressursspesifikasjonen til en lokal fil, som deretter åpnes i et tekstredigeringsprogram. Etter at du har redigert og lagret filen, kubectl vil sende endringene som er gjort tilbake gjennom APIen, som nøye vil bruke disse endringene på ressursen.

Ikke alle kjenner kommandoene patch и replace. Team patch lar deg endre en del av en ressursspesifikasjon, og gir kun den endrede delen på kommandolinjen. Team replace fungerer det samme som edit, men alt må gjøres manuelt: du må laste ned gjeldende versjon av ressursspesifikasjonen, for eksempel ved å bruke kubectl get -o yaml, rediger den og bruk deretter replace å oppdatere en ressurs i henhold til en endret spesifikasjon. Team replace vil ikke fungere hvis det skjedde endringer mellom lesing og utskifting av ressursen.

Kubernetes API

Du er sikkert kjent med metodene CoreV1().Pods().Update(), replaceNamespacedService eller patch_namespaced_deployment, hvis du jobber med klynger via klientbibliotek for Kubernetes API bruker et eller annet programmeringsspråk. Biblioteket håndterer disse metodene via HTTP-forespørsler ved å bruke metodene PUT и PATCH... Hvor update и replace bruk PUTOg patch, uansett hvor trivielt det måtte være, bruker PATCH.

Det bør bemerkes at kubectl fungerer også med klynger via API. Med andre ord, kubectler en innpakning på toppen av klientbiblioteket for Go-språket, som i stor grad gir muligheten til å gi underkommandoer i en mer kompakt og lesbar form i tillegg til standard API-funksjoner. For eksempel, som du kanskje allerede har lagt merke til, metoden apply ble ikke nevnt ovenfor i forrige avsnitt. For øyeblikket (mai 2020, ca. oversetter) all logikk kubectl apply, dvs. å lage ikke-eksisterende ressurser og oppdatere eksisterende, fungerer helt på kodesiden kubectl. Det gjøres innsats på logikkoverføring apply til API-siden, men den er fortsatt i beta. Jeg vil skrive mer detaljert nedenfor.

Patch som standard

Best brukt patch, hvis du vil oppdatere ressursen. Dette er hvordan begge klientbibliotekene fungerer på toppen av Kubernetes API og kubectl (ikke overraskende, siden det er en innpakning for klientbiblioteket, ca. oversetter).

Arbeid strategisk

Alle lag kubectl apply, edit и patch bruke metoden PATCH i HTTP-forespørsler om å oppdatere en eksisterende ressurs. Hvis du fordyper deg i implementeringen av kommandoer mer detaljert, bruker alle tilnærmingen strategisk-sammenslåing patching å oppdatere ressurser, selv om kommandoen patch kan bruke andre tilnærminger (mer om dette nedenfor). Strategisk-sammenslåing-patching-tilnærmingen forsøker å "få det riktig" ved å slå sammen den medfølgende spesifikasjonen med den eksisterende spesifikasjonen. Mer spesifikt prøver den å kombinere både objekter og matriser, noe som betyr at endringene har en tendens til å være additive. For eksempel å kjøre kommandoen patch med en ny miljøvariabel i pod-beholderspesifikasjonen, fører til at miljøvariabelen legges til de eksisterende miljøvariablene i stedet for å overskrive dem. For å fjerne ved å bruke denne tilnærmingen, må du tvinge parameterverdien til null i den angitte spesifikasjonen. Hvilket av lagene kubectl Er det best å bruke for oppdatering?

Hvis du oppretter og administrerer ressursene dine ved hjelp av kubectl apply, når du oppdaterer er det bedre å alltid bruke kubectl applyTil kubectl kunne administrere konfigurasjonen og riktig spore forespurte endringer fra applikasjon til applikasjon. Fordel bruk alltid apply er at den holder styr på en tidligere anvendt spesifikasjon, slik at den kan vite når spesifikasjonsegenskaper og matriseelementer eksplisitt er fjernet. Dette lar deg bruke apply for å fjerne egenskaper og array-elementer, mens en vanlig strategisk sammenslåing ikke vil fungere. Lag edit и patch ikke oppdater notater som kubectl apply bruker for å spore endringene, så alle endringer som spores og gjøres gjennom Kubernetes API, men som gjøres gjennom kommandoer edit и patch, usynlig for påfølgende kommandoer applySom er, apply fjerner dem ikke selv om de ikke vises i inngangsspesifikasjonen for apply (Dokumentasjonen sier det edit и patch foreta oppdateringer til notatene som brukes apply, men i praksis - nei).

Hvis du ikke bruker kommandoen apply, kan brukes som editOg patch, ved å velge kommandoen som passer best til endringen som gjøres. Når du legger til og endrer stykklisteegenskaper, er begge tilnærmingene omtrent like. Når du sletter spesifikasjonsegenskaper eller matriseelementer edit oppfører seg som en engangslansering apply, inkludert å holde styr på hvordan spesifikasjonen var før og etter at den ble redigert, slik at du eksplisitt kan fjerne egenskaper og matriseelementer fra en ressurs. Du må eksplisitt sette egenskapsverdien til null i spesifikasjonen for patchfor å fjerne den fra ressursen. Å fjerne et array-element ved hjelp av strategisk flette-patching er mer komplekst fordi det krever bruk av flettedirektiver. Se andre oppgraderingsmetoder nedenfor for mer levedyktige alternativer.

For å implementere oppdateringsmetoder i klientbiblioteket som oppfører seg på samme måte som kommandoene ovenfor kubectl, bør angis i forespørsler content-type в application/strategic-merge-patch+json. Hvis du vil fjerne egenskaper i en spesifikasjon, må du eksplisitt sette verdiene deres til null på lignende måte kubectl patch. Hvis du trenger å fjerne array-elementer, bør du inkludere flettedirektiver i oppdateringsspesifikasjonen eller bruke en annen tilnærming til oppdateringer.

Andre tilnærminger til oppdateringer

Kubernetes støtter to andre oppdateringsmetoder: JSON-sammenslåingsoppdatering и JSON-oppdatering. JSON merge patch-tilnærmingen tar en delvis Kubernetes-spesifikasjon som input og støtter sammenslåing av objekter som ligner på strategic-merge patching-tilnærmingen. Forskjellen mellom de to er at den kun støtter array-erstatning, inkludert container-arrayen i pod-spesifikasjonen. Dette betyr at når du bruker en JSON-flettingsoppdatering, må du oppgi fullstendige spesifikasjoner for alle containere i tilfelle noen av egenskapene til en container endres. Så denne tilnærmingen er nyttig for å fjerne elementer fra en matrise i en stykkliste. På kommandolinjen kan du velge JSON merge patch ved hjelp av kubectl patch --type=merge. Når du arbeider med Kubernetes API, bør du bruke forespørselsmetoden PATCH og installasjon content-type в application/merge-patch+json.

JSON patch-tilnærmingen, i stedet for å gi en delvis spesifikasjon av en ressurs, bruker å gi endringene du vil gjøre i ressursen som en matrise, der hvert element i matrisen representerer en beskrivelse av endringen som gjøres til ressursen. Denne tilnærmingen er en mer fleksibel og kraftig måte å uttrykke endringene som gjøres, men på bekostning av å liste endringene som gjøres i et eget, ikke-Kubernetes-format, i stedet for å sende en delvis ressursspesifikasjon. I kubectl du kan velge JSON-oppdatering ved å bruke kubectl patch --type=json. Når du bruker Kubernetes API, fungerer denne tilnærmingen ved å bruke forespørselsmetoden PATCH og installasjon content-type в application/json-patch+json.

Vi trenger tillit - bruk erstatte

I noen tilfeller må du være sikker på at det ikke gjøres endringer i en ressurs mellom det tidspunktet ressursen leses og når den oppdateres. Du bør med andre ord sørge for at alle endringer blir det atomisk. I dette tilfellet bør du bruke for å oppdatere ressurser replace. For eksempel, hvis du har et ConfigMap med en teller som er oppdatert av flere kilder, bør du være sikker på at to kilder ikke oppdaterer telleren samtidig, noe som fører til at oppdateringen går tapt. For å demonstrere, se for deg et hendelsesforløp ved å bruke tilnærmingen patch:

  • A og B henter ressursens nåværende tilstand fra API-en
  • Hver enkelt oppdaterer spesifikasjonen lokalt ved å øke telleren med én og også legge til henholdsvis "A" eller "B" til notatet "oppdatert av"
  • Og den oppdaterer ressursen litt raskere
  • B oppdaterer ressursen

Som et resultat går oppdatering A tapt. Siste operasjon patch vinner, telleren økes med én i stedet for to, og verdien av "updated-by"-seddelen ender med "B" og inneholder ikke "A". La oss sammenligne ovenstående med hva som skjer når oppdateringer gjøres ved hjelp av tilnærmingen replace:

  • A og B henter ressursens nåværende tilstand fra API-en
  • Hver enkelt oppdaterer spesifikasjonen lokalt ved å øke telleren med én og også legge til henholdsvis "A" eller "B" til notatet "oppdatert av"
  • Og den oppdaterer ressursen litt raskere
  • B prøver å oppdatere ressursen, men oppdateringen avvises av API fordi ressursversjonen er i spesifikasjonen replace samsvarer ikke med gjeldende versjon av ressursen i Kubernetes fordi versjonen av ressursen ble økt med As erstatningsoperasjon.

I tilfellet ovenfor må B hente ressursen på nytt, gjøre endringer i den nye tilstanden og prøve på nytt replace. Dette vil føre til at telleren økes med to og "oppdatert av"-notatet til å inkludere "AB" på slutten.

Eksempelet ovenfor antyder at når du utfører replace Hele ressursen er fullstendig erstattet. Spesifikasjon brukt for replace, må ikke være delvis, eller i deler som i apply, men komplett, inkludert tillegget resourceVersion inn i spesifikasjonens metadata. Hvis du ikke har aktivert resourceVersion eller versjonen du oppgir ikke er aktuell, vil erstatningen bli avvist. Så den beste tilnærmingen til bruk er replace – les ressursen, oppdater den og erstatt den umiddelbart. Ved hjelp av kubectl, kan det se slik ut:

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

Det er verdt å merke seg at følgende to kommandoer, utført sekvensielt, vil utføres vellykket, siden deployment.yaml inneholder ikke eiendom .metadata.resourceVersion

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

Dette ser ut til å motsi det som ble sagt ovenfor, dvs. "legger til resourceVersion inn i spesifikasjonens metadata." Er det feil å si det? Nei, det er det ikke, for hvis kubectl merknader som du ikke spesifiserte resourceVersion, vil den lese den fra ressursen og legge den til spesifikasjonen du spesifiserte, og bare deretter utføre den replace. Fordi dette er potensielt farlig hvis du stoler på atomitet, fungerer magien helt på siden kubectl, bør du ikke stole på det når du bruker klientbiblioteker som fungerer med API. I dette tilfellet må du lese den gjeldende ressursspesifikasjonen, oppdatere den og deretter kjøre PUT be om.

Du kan ikke lage en oppdatering – vi bytter ut

Noen ganger må du gjøre noen endringer som ikke kan håndteres av API. I disse tilfellene kan du fremtvinge erstatning av ressursen ved å slette og gjenopprette den. Dette gjøres ved hjelp av kubectl replace --force. Når du kjører kommandoen, fjernes ressursene umiddelbart og deretter gjenskapes fra den medfølgende spesifikasjonen. Det er ingen "force replace"-behandler i API, og for å gjøre det gjennom API, må du utføre to operasjoner. Først må du slette ressursen ved å stille inn for den gracePeriodSeconds til null (0) og propagationPolicy i "Bakgrunn" og lag deretter denne ressursen på nytt med ønsket spesifikasjon.

Advarsel: Denne tilnærmingen er potensielt farlig og kan føre til en udefinert tilstand.

Påfør på serversiden

Som nevnt ovenfor jobber Kubernetes-utviklere med å implementere logikken apply av kubectl i Kubernetes API. Logikk apply tilgjengelig i Kubernetes 1.18 via kubectl apply --server-side eller via API ved hjelp av metoden PATCH с content-type application/apply-patch+YAML.

Merk: JSON er også gyldig YAML, så du kan sende spesifikasjonen som JSON selv om content-type vil application/apply-patch+yaml.

Utenom den logikken kubectl blir tilgjengelig for alle via API, apply på serversiden, holder styr på hvem som er ansvarlig for feltene i spesifikasjonen, og tillater dermed sikker flertilgang for dens konfliktfrie redigering. Med andre ord, hvis apply på serversiden vil bli mer utbredt, vil det dukke opp et universelt sikkert ressursadministrasjonsgrensesnitt for forskjellige klienter, for eksempel kubectl, Pulumi eller Terraform, GitOps, samt selvskrevne skript som bruker klientbiblioteker.

Resultater av

Jeg håper denne korte oversikten over ulike måter å oppdatere ressurser i klynger på var nyttig for deg. Det er godt å vite at det ikke bare er å bruke versus erstatte; det er mulig å oppdatere en ressurs ved å bruke, redigere, lappe eller erstatte. Tross alt, i prinsippet, har hver tilnærming sitt eget bruksområde. For atomære endringer er erstatning å foretrekke; ellers bør du bruke strategisk flettelapp via applicering. I det minste forventer jeg at du forstår at du ikke kan stole på Google eller StackOerflow når du søker etter "kubernetes apply vs replace". I hvert fall inntil denne artikkelen erstatter det nåværende svaret.

Riktig sammenligning av Kubernetes Apply, Replace and Patch

Kilde: www.habr.com

Legg til en kommentar