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.
Hvis 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 PUT
и PATCH
... Hvor update
и replace
bruk PUT
Og 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, kubectl
er 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 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 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 apply
Til 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 apply
Som 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 edit
Og 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 patch
for å 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: 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
vilapplication/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.
Kilde: www.habr.com