Riktig sammenligning av Kubernetes Apply, Replace og Patch

For Kubernetes er det flere alternativer for oppdatering av ressurser: apply, edit, patch og replace. Det er forvirring om hva hver av dem gjør og når de skal brukes. La oss se nærmere på det.

Riktig sammenligning av Kubernetes Apply, Replace og Patch

Hvis søke på Google frasen "kubernetes apply vs replace", finner svaret på StackOverflow, som ikke er korrekt. Når man søker "kubernetes apply vs patch" er det første treffet - dokumentasjonen til kubectl patch, som ikke inkluderer sammenligningen apply og patch. I denne artikkelen vil forskjellige alternativer bli diskutert, samt riktig bruk av hver av dem.

I løpet av livssyklusen til en Kubernetes-ressurs (tjeneste, deployment, ingress osv.) må man noen ganger endre, legge til eller fjerne visse egenskaper ved denne ressursen. For eksempel, legge til en kommentar, øke eller redusere antall replikater.

Kubernetes CLI

Hvis du allerede jobber med Kubernetes-klynger via CLI, er du kjent med apply og edit. Kommandoen apply leser ressursens spesifikasjon fra en fil og gjør en "upsert" i Kubernetes-klyngen, det vil si den oppretter ressursen hvis den ikke finnes, og oppdaterer den hvis den eksisterer. Kommandoen edit leser ressursen gjennom API-en, hvoretter den skriver ressursens spesifikasjon til en lokal fil, som så åpnes i en tekstredigerer. Etter at du har redigert og lagret filen, kubectl sender de gjorte endringene tilbake via API-en, som omtanke gjelder for å anvende disse endringene på ressursen.

Ikke alle kjenner til kommandoene patch og replace. Kommandoen patch lar deg endre en del av ressursens spesifikasjon ved å kun oppgi den endrede delen i kommandolinjen. Kommandoen replace virker på samme måte som edit, men alt må gjøres manuelt: du må laste ned den nåværende versjonen av ressursens spesifikasjon, for eksempel ved å bruke kubectl get -o yaml, redigere den, deretter bruke replace for å oppdatere ressursen med den endrede spesifikasjonen. Kommandoen replace vil ikke fungere dersom det har skjedd endringer mellom lesing og erstatning av ressursen.

Kubernetes API

Du er sannsynligvis kjent med metodene CoreV1().Pods().Update(), replaceNamespacedService eller patch_namespaced_deployment, hvis du jobber med klynger via klientbiblioteket for Kubernetes API ved hjelp av et programmeringsspråk. Biblioteket håndterer disse metodene med HTTP-protokollforespørselene ved å bruke metoder en PUT og PATCH. På den måten update og replace dette til fingeravtrykk. Tidligere var blokkeringen av tilgang til lokale ressurser kun aktivert ved streng beskyttelse mot sporing, nå aktiveres det gradvis for alle brukere. en PUT, men patch, så banalt som det måtte være, bruker PATCH.

Det er verdt å merke seg at kubectl også fungerer med klynger gjennom API-en. Med andre ord, kubectl– er en innpakning over klientbiblioteket for Go-språket som i stor grad gir muligheten til å tilby underkommandoer på en mer kompakt og lesbar måte i tillegg til de innebygde API-mulighetene. For eksempel, som du kanskje allerede har lagt merke til, ble metoden apply ikke nevnt ovenfor i forrige avsnitt. For øyeblikket (mai 2020, translator's note) all logikk kubectl apply, dvs. oppretting av ikke-eksisterende ressurser og oppdatering av eksisterende, fungerer helt fra kode-siden kubectl. Det blir gjort innsats for å flytte logikk apply til API-siden, men dette er fortsatt i beta-testing. Mer informasjon nedenfor.

Patch som standard

Det er best å bruke patch, hvis du ønsker å oppdatere ressursen. Slik fungerer både klientbiblioteker over API Kubernetes og kubectl (ikke overraskende, siden det er en innpakning av klientbiblioteket, translator's note).

Jobbe strategisk

Alle kommandoer kubectl apply, edit og patch bruker metoden PATCH i HTTP-forespørslene for å oppdatere eksisterende ressurser. Hvis du dykker dypere inn i implementeringen av kommandoene, bruker alle tilnærmingen strategic-merge patching for oppdatering av ressurser, selv om kommandoen patch kan bruke andre tilnærminger (mer om dette nedenfor). Tilnærmingen strategic-merge patching prøver å "gjøre alt riktig" når den slår sammen den angitte spesifikasjonen med den eksisterende spesifikasjonen. Mer spesifikt prøver den å kombinere både objekter og matriser, noe som betyr at endringer vanligvis er additiver. For eksempel, når du kjører kommandoen patch med den nye miljøvariabelen i spesifikasjonen for pod-beholderen, blir denne miljøvariabelen lagt til de eksisterende miljøvariablene i stedet for å overskrive dem. For å fjerne ved hjelp av denne tilnærmingen må du tvinge verdien av parameteren til null i den angitte spesifikasjonen. Hvilke kommandoer kubectl er best å bruke for oppdatering?

Hvis du oppretter og administrerer ressursene dine med kubectl apply, når du oppdaterer, er det alltid best å bruke kubectl apply, slik at kubectl kan administrere konfigurasjonen og holde styr på forespurte endringer fra anvendelse til anvendelse. Fordelen med alltid å bruke apply er at det sporer den tidligere anvendte spesifikasjonen, noe som gjør det i stand til å vite når spesifikasjonsegenskaper og matriseelementer eksplisitt fjernes. Dette muliggjør bruk av apply for å fjerne egenskaper og elementer fra matriser, mens vanlig strategisk sammenslåing ikke vil fungere. Kommandoer edit og patch oppdaterer ikke merknader som kubectl apply de bruker til å spore endringene sine, så eventuelle endringer som spores og gjøres gjennom API-en Kubernetes, men utført gjennom kommandoer edit og patch, vil være usynlige for påfølgende kommandoer apply, det vil si apply fjerner dem ikke, selv om de ikke vises i den inngående spesifikasjonen for apply (Dokumentasjonen sier at edit og patch de gjør oppdateringer til merknader som brukes apply, men i praksis - nei).

Hvis du ikke bruker kommandoen apply, kan du bruke som edit, så vel som patch, ved å velge den kommandoen som passer best til den endringen som gjøres. Når egenskaper i spesifikasjonen legges til og endres, er begge tilnærmingene omtrent like. Ved fjerning av egenskaper i spesifikasjonen eller elementer i matriser edit oppfører seg som en engangs-kjøring apply, og sporer også hva spesifikasjonen var før og etter redigering, så du kan eksplisitt fjerne egenskaper og elementer fra matriser fra ressursen. Du må eksplisitt sette verdien av egenskapen til null i spesifikasjonen for patch, for å fjerne den fra ressursen. Å fjerne et element i en matrise ved bruk av strategisk sammenslåing er mer komplisert, da det krever bruk av sammenslåingsdirektiver. Se andre tilnærminger til oppdateringer nedenfor for å velge mer akseptable alternativer.

For å implementere metoder for oppdatering i klientbiblioteket som oppfører seg på samme måte som kommandoene nevnt ovenfor kubectl, bør forespørslene angi content-type i application/strategic-merge-patch+json. Hvis du vil fjerne egenskaper fra spesifikasjonen, må du eksplisitt sette verdiene deres til null på samme måte som kubectl patch. Hvis du må fjerne elementer fra matriser, bør du inkludere sammenslåingsdirektiver i oppdateringsspesifikasjonen eller bruke en annen tilnærming til oppdateringer.

Andre tilnærminger til oppdateringer

Kubernetes støtter to andre tilnærminger til oppdateringer: JSON sammenslåing patch og JSON patch. JSON merge patch-tiln tar ein delvis spesifikasjon av Kubernetes som innputt og støtter sammenslåing av objekter på lignende måte som strategic-merge patching. Forskjellen mellom dem er at det kun støtter utskifting av matriser, inkludert beholdermatrisen i pod-spesifikasjonen. Dette betyr at når du bruker JSON merge patch må du gi komplette spesifikasjoner for alle beholdere dersom du endrer et hvilket som helst egenskap til en beholder. Dermed er denne tilnærmingen nyttig for å fjerne elementer fra en matrise i spesifikasjonen. I kommandolinjen kan du velge JSON merge patch ved å bruke kubectl patch --type=merge. Når du arbeider med Kubernetes API må du bruke forespørselmetoden PATCH og sette content-type i application/merge-patch+json.

JSON patch-tilnærmingen i stedet for å gi en delvis spesifikasjon av ressursen, bruker å gi endringer som du ønsker å gjøre på ressursen i form av et array, der hvert element i arrayet representerer en beskrivelse av endringen som gjøres på ressursen. Denne tilnærmingen er en mer fleksibel og kraftfull måte å uttrykke endringene på, men fordi listen over endringer kommer i et separat, ikke-Kubernetes format, i stedet for å sende en delvis spesifikasjon av ressursen. I kubectl kan du velge JSON patch ved å bruke kubectl patch --type=json. Når du bruker Kubernetes API, fungerer denne tilnærmingen ved å bruke forespørselmetoden PATCH og sette content-type i application/json-patch+json.

Må sikkert — bruk replace

I noen tilfeller er det nødvendig å være sikker på at ressursen ikke blir endret mellom tidspunktet for å lese ressursen og oppdateringen. Med andre ord, det er viktig å sikre at alle endringer vil være atomiske. I dette tilfellet bør du bruke replace. For eksempel, hvis det er en ConfigMap med en teller som blir oppdatert av flere kilder, bør man være trygg på at to kilder ikke oppdaterer telleren samtidig, noe som vil føre til tap av oppdateringen. For å demonstrere, forestill deg en sekvens av hendelser der patch:

  • A og B får nåværende tilstand av ressursen fra API-et
  • Hver av dem oppdaterer lokalt spesifikasjonen ved å øke telleren med en, og også legge til "A" eller "B" i henholdsvis merknaden "updated-by"
  • A oppdaterer ressursen litt raskere
  • B oppdaterer ressursen

Som oppdatering A tapt. Siste operasjon patch vinner, telleren øker med en enhet i stedet for to, og verdien i merknaden "updated-by" slutter med "B" og inneholder ikke "A". La oss sammenligne dette med hva som skjer når oppdateringer utføres ved hjelp av tilnærmingen replace:

  • A og B får nåværende tilstand av ressursen fra API-et
  • Hver av dem oppdaterer lokalt spesifikasjonen ved å øke telleren med en, og også legge til "A" eller "B" i henholdsvis merknaden "updated-by"
  • A oppdaterer ressursen litt raskere
  • B prøver å oppdatere ressursen, men oppdateringen blir avvist av API-et, fordi versjonen av ressursen i spesifikasjonen replace ikke samsvarer med den gjeldende versjonen av ressursen i Kubernetes, ettersom versjonen av ressursen ble økt ved utførelsen av erstatningsoperasjonen fra A.

I det ovennevnte tilfellet må B hente ressursen på nytt, gjøre endringer til den nye tilstanden og prøve igjen replace. Som et resultat vil telleren økes med to, og merknaden "updated-by" vil inneholde "AB" på slutten.

Det foregående eksemplet antyder at når det utføres replace utføres en full erstatning av hele ressursen. Spesifikasjonen som brukes for replace, må være ikke-partiell, eller delt som i apply, men fullstendig, inkludert tillegget av resourceVersion i metadataene til spesifikasjonen. Hvis du ikke inkluderte resourceVersion eller versjonen du oppgav ikke er gjeldende, vil erstatningen bli avvist. Dermed er den beste tilnærmingen å bruke replace – å lese ressursen, oppdatere den og deretter umiddelbart erstatte. 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 de følgende to kommandoene, som utføres etter hverandre, vil bli gjennomført med suksess, ettersom deployment.yaml ikke inneholder egenskapen .metadata.resourceVersion

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

Det ser ut til å være i motstrid, sammenlignet med det som ble sagt tidligere, det vil si "å legge til resourceVersion i metadataene til spesifikasjonen". Er det feil å påstå dette? Nei, det er det ikke, fordi hvis kubectl merker at du ikke oppga resourceVersion, vil den lese den fra ressursen og legge den til spesifikasjonen du oppga, og deretter utføre replace. Siden dette er potensielt farlig, hvis man stoler på atomisitet, fungerer magien helt på siden av kubectl, så det er ikke lurt å stole på det når man bruker klientbiblioteker som arbeider med API. I dette tilfellet må du lese den nåværende spesifikasjonen til ressursen, oppdatere den og deretter utføre en PUT forespørselen.

Det er ikke mulig å gjøre patch – vi gjør erstatning

Noen ganger må du gjøre endringer som ikke kan håndteres av APIen. I slike tilfeller kan du tvinge erstatning av ressursen ved å slette og gjenskape den. Dette gjøres med kubectl replace --force. Å kjøre kommandoen sletter umiddelbart ressursene, og deretter gjenoppretter den dem med den oppgitte spesifikasjonen. APIen har ingen behandler for "tvinge erstatning", og for å gjøre dette via API, må du utføre to operasjoner. Først må du slette ressursen, og sette gracePeriodSeconds til null (0) og propagationPolicy til "Background", og deretter gjenopprette denne ressursen med ønsket spesifikasjon.

Advarsel: Denne metoden er potensielt farlig og kan føre til en usikker tilstand.

Apply på serversiden.

Som nevnt tidligere, jobber Kubernetes-utviklere med å implementere logikken apply fra kubectl i Kubernetes API. Logikken apply er tilgjengelig i Kubernetes 1.18 via kubectl apply --server-side eller gjennom APIet, ved å bruke metoden PATCH med content-type application/apply-patch+YAML.

Merk: JSON er også gyldig YAML, så du kan sende spesifikasjonen i JSON-format, selv om content-type muligheten til å se beskyttet strømmende video som bruker AV1-kodek. application/apply-patch+yaml.

I tillegg til at logikken kubectl blir tilgjengelig for alle gjennom APIet, apply på serversiden overvåker ansvarlige for feltene i spesifikasjonen, og dermed tillater sikkert flerbrukertilgang for konfliktfri redigering. Med andre ord, hvis apply på serversiden får bredere utbredelse, vil det komme et universelt trygt grensesnitt for administrasjon av ressurser for forskjellige klienter, for eksempel kubectl, Pulumi eller Terraform, GitOps, samt egne skript som bruker klientbiblioteker.

Resultater

Jeg håper at denne korte oversikten over forskjellige måter å oppdatere ressurser i klynger har vært nyttig for deg. Det er nyttig å vite at motstandere ikke bare er apply mot replace, for du kan oppdatere ressursen med apply, edit, patch eller replace. Hver tilnærming har sitt bruksområde. For atomiske endringer er replace å foretrekke, ellers er det bedre å bruke strategic-merge patch via apply. I verste fall håper jeg at du har forstått at man ikke skal stole på Google eller StackOverflow når man søker etter "kubernetes apply vs replace". I det minste inntil denne artikkelen erstatte det nåværende svaret.

Riktig sammenligning av Kubernetes Apply, Replace og Patch

Kilde: habr.com

Kjøp pålitelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere 🔥 Kjøp pålitelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere | ProHoster