Kubernetes heeft verschillende opties voor het updaten van bronnen: toepassen, bewerken, patchen en vervangen. Er bestaat verwarring over wat ze allemaal doen en wanneer ze moeten worden gebruikt. Laten we het uitzoeken.
als kubectl patch
, waarbij vergelijking niet is opgenomen apply
и patch
. In dit artikel worden de verschillende opties besproken, evenals het juiste gebruik ervan.
Tijdens de levenscyclus van een Kubernetes-resource (service, implementatie, inkomend verkeer, etc.) moet u soms enkele eigenschappen van deze resource wijzigen, toevoegen of verwijderen. Voeg bijvoorbeeld een notitie toe, verhoog of verlaag het aantal replica's.
Kubernetes-CLI
Als je al met Kubernetes-clusters werkt via de CLI, ben je er al bekend mee apply
и edit
. Team apply
leest de resourcespecificatie uit het bestand en maakt een "upsert" naar het Kubernetes-cluster, d.w.z. maakt de resource aan als deze niet bestaat en werkt deze bij als deze wel bestaat. Team edit
leest een bron via de API en schrijft vervolgens de bronspecificatie naar een lokaal bestand, dat vervolgens in een teksteditor wordt geopend. Nadat u het bestand hebt bewerkt en opgeslagen, kubectl
stuurt de aangebrachte wijzigingen terug via de API, die deze wijzigingen zorgvuldig op de bron zal toepassen.
Niet iedereen kent de commando's patch
и replace
. Team patch
Hiermee kunt u een deel van een resourcespecificatie wijzigen, waarbij alleen het gewijzigde deel op de opdrachtregel wordt weergegeven. Team replace
werkt hetzelfde als edit
, maar alles moet handmatig worden gedaan: u moet bijvoorbeeld de huidige versie van de bronspecificatie downloaden met behulp van kubectl get -o yaml
, bewerk het en gebruik het vervolgens replace
om een hulpbron bij te werken volgens een gewijzigde specificatie. Team replace
werkt niet als er wijzigingen zijn opgetreden tussen het lezen en vervangen van de bron.
Kubernetes-API
U kent de methoden waarschijnlijk wel CoreV1().Pods().Update()
, replaceNamespacedService
of patch_namespaced_deployment
, als je met clusters werkt via PUT
и PATCH
... Waarin update
и replace
gebruik PUT
En patch
, hoe triviaal het ook mag zijn, gebruikt PATCH
.
Opgemerkt dat kubectl
werkt ook met clusters via API. Met andere woorden, kubectl
is een wrapper bovenop de clientbibliotheek voor de Go-taal, die grotendeels de mogelijkheid biedt om subopdrachten in een compactere en leesbare vorm aan te bieden naast de standaard API-mogelijkheden. Zoals je misschien al hebt gemerkt, de methode apply
werd hierboven in de vorige paragraaf niet genoemd. Momenteel (mei 2020, ca. vertaler) allemaal logica kubectl apply
, d.w.z. het creëren van niet-bestaande bronnen en het bijwerken van bestaande, werkt volledig aan de codekant kubectl
. Er worden inspanningen geleverd apply
naar de API-kant, maar deze bevindt zich nog in de bètafase. Ik zal hieronder meer in detail schrijven.
Standaard patchen
Beste gebruikt patch
, als u de bron wilt bijwerken. Dit is hoe beide clientbibliotheken bovenop de Kubernetes API werken kubectl
(niet verrassend, aangezien het een wrapper is voor de clientbibliotheek, ca. vertaler).
Strategisch werken
Alle teams kubectl
apply
, edit
и patch
gebruik de methode PATCH
in HTTP-verzoeken om een bestaande bron bij te werken. Als je je meer in detail verdiept in de implementatie van commando's, dan gebruiken ze allemaal de aanpak patch
kan andere benaderingen gebruiken (meer hierover hieronder). De strategische merge-patching-aanpak probeert het "goed te doen" door de geleverde specificatie samen te voegen met de bestaande specificatie. Meer specifiek probeert het zowel objecten als arrays te combineren, wat betekent dat de veranderingen vaak additief zijn. Bijvoorbeeld door de opdracht uit te voeren patch
met een nieuwe omgevingsvariabele in de podcontainerspecificatie zorgt ervoor dat die omgevingsvariabele wordt toegevoegd aan de bestaande omgevingsvariabelen in plaats van deze te overschrijven. Als u deze aanpak wilt verwijderen, moet u de parameterwaarde in de opgegeven specificatie op nul zetten. Welke van de teams kubectl
Is het het beste om te gebruiken voor het updaten?
Als u uw bronnen maakt en beheert met behulp van kubectl apply
, bij het updaten is het beter om altijd te gebruiken kubectl apply
Naar kubectl
kan de configuratie beheren en de aangevraagde wijzigingen van applicatie tot applicatie op de juiste manier volgen. Voordeel altijd gebruiken apply
is dat het een eerder toegepaste specificatie bijhoudt, waardoor het weet wanneer specificatie-eigenschappen en array-elementen expliciet worden verwijderd. Hierdoor kunt u gebruiken apply
om eigenschappen en array-elementen te verwijderen, terwijl een normale strategische samenvoeging niet zal werken. Teams edit
и patch
notities niet bijwerken kubectl apply
gebruikt om de wijzigingen bij te houden, dus alle wijzigingen die worden bijgehouden en aangebracht via de Kubernetes API, maar gemaakt via opdrachten edit
и patch
, onzichtbaar voor volgende opdrachten apply
Dat wil zeggen, apply
verwijdert ze niet, ook al verschijnen ze niet in de invoerspecificatie voor apply
(De documentatie zegt dat edit
и patch
updates aanbrengen in de gebruikte notities apply
, maar in de praktijk - nee).
Als u het commando niet gebruikt apply
, kan worden gebruikt als edit
En patch
, waarbij u de opdracht kiest die het beste past bij de wijziging die wordt aangebracht. Bij het toevoegen en wijzigen van stuklijsteigenschappen zijn beide benaderingen grofweg hetzelfde. Bij het verwijderen van specificatie-eigenschappen of array-elementen edit
gedraagt zich als een eenmalige lancering apply
, inclusief het bijhouden van hoe de specificatie eruitzag vóór en nadat deze werd bewerkt, zodat u eigenschappen en array-elementen expliciet uit een bron kunt verwijderen. U moet de eigenschapswaarde expliciet instellen op null in de specificatie voor patch
om het uit de bron te verwijderen. Het verwijderen van een array-element met behulp van strategische merge-patching is complexer omdat hiervoor het gebruik van merge-richtlijnen vereist is. Zie andere upgradebenaderingen hieronder voor meer haalbare alternatieven.
Om updatemethoden in de clientbibliotheek te implementeren die zich op dezelfde manier gedragen als de bovenstaande opdrachten kubectl
, moet worden ingesteld in verzoeken content-type
в application/strategic-merge-patch+json
. Als u eigenschappen uit een specificatie wilt verwijderen, moet u hun waarden op een vergelijkbare manier expliciet op null instellen kubectl patch
. Als u array-elementen moet verwijderen, moet u samenvoegrichtlijnen opnemen in de updatespecificatie of een andere benadering van updates gebruiken.
Andere benaderingen van updates
Kubernetes ondersteunt twee andere updatebenaderingen: kubectl patch --type=merge
. Wanneer u met de Kubernetes API werkt, moet u de verzoekmethode gebruiken PATCH
en installatie content-type
в application/merge-patch+json
.
De JSON-patchbenadering maakt, in plaats van een gedeeltelijke specificatie van een bron te verstrekken, gebruik van het verstrekken van de wijzigingen die u aan de bron wilt aanbrengen als een array, waarbij elk element van de array een beschrijving vertegenwoordigt van de wijziging die in de bron wordt aangebracht. Deze aanpak is een flexibelere en krachtigere manier om de aangebrachte wijzigingen tot uitdrukking te brengen, maar gaat ten koste van het vermelden van de aangebrachte wijzigingen in een afzonderlijk, niet-Kubernetes-formaat, in plaats van het verzenden van een gedeeltelijke resourcespecificatie. IN kubectl
u kunt JSON-patch selecteren met behulp van kubectl patch --type=json
. Bij gebruik van de Kubernetes API werkt deze aanpak met behulp van de verzoekmethode PATCH
en installatie content-type
в application/json-patch+json
.
We hebben vertrouwen nodig - gebruik vervangen
In sommige gevallen moet u er zeker van zijn dat er geen wijzigingen worden aangebracht in een resource tussen het moment waarop de resource wordt gelezen en het moment waarop deze wordt bijgewerkt. Met andere woorden, u moet ervoor zorgen dat alle wijzigingen doorgevoerd worden atomair. In dit geval moet u de bronnen bijwerken die u moet gebruiken replace
. Als u bijvoorbeeld een ConfigMap heeft met een teller die door meerdere bronnen wordt bijgewerkt, moet u er zeker van zijn dat twee bronnen de teller niet tegelijkertijd bijwerken, waardoor de update verloren gaat. Om dit te demonstreren, stel je een reeks gebeurtenissen voor met behulp van de aanpak patch
:
- A en B krijgen de huidige status van de bron van de API
- Iedereen werkt de specificatie lokaal bij door de teller met één te verhogen en ook respectievelijk "A" of "B" toe te voegen aan de notitie "bijgewerkt door".
- En het werkt de bron iets sneller bij
- B werkt de bron bij
Als gevolg hiervan gaat update A verloren. Laatste operatie patch
wint, de teller wordt verhoogd met één in plaats van twee, en de waarde van de "bijgewerkt door"-noot eindigt met "B" en bevat geen "A". Laten we het bovenstaande vergelijken met wat er gebeurt als er updates worden uitgevoerd met behulp van deze aanpak replace
:
- A en B krijgen de huidige status van de bron van de API
- Iedereen werkt de specificatie lokaal bij door de teller met één te verhogen en ook respectievelijk "A" of "B" toe te voegen aan de notitie "bijgewerkt door".
- En het werkt de bron iets sneller bij
- B probeert de bron bij te werken, maar de update wordt door de API afgewezen omdat de bronversie in de specificatie staat
replace
komt niet overeen met de huidige versie van de bron in Kubernetes, omdat de versie van de bron is vergroot door de vervangingsbewerking van A.
In het bovenstaande geval zal B de bron opnieuw moeten ophalen, wijzigingen moeten aanbrengen in de nieuwe status en het opnieuw moeten proberen replace
. Dit zorgt ervoor dat de teller met twee wordt verhoogd en dat de "bijgewerkt door"-noot aan het einde "AB" bevat.
Het bovenstaande voorbeeld impliceert dat bij het uitvoeren replace
De gehele hulpbron wordt volledig vervangen. Specificatie gebruikt voor replace
, mag niet gedeeltelijk zijn, of in delen zoals in apply
, maar compleet, inclusief de toevoeging resourceVersion
in de specificatiemetagegevens. Als je dit niet hebt ingeschakeld resourceVersion
of de door u verstrekte versie is niet actueel, de vervanging wordt afgewezen. De beste aanpak is dus replace
– lees de bron, update deze en vervang deze onmiddellijk. Gebruik makend van kubectl
, het zou er zo uit kunnen zien:
$ kubectl get deployment my-deployment -o json
| jq '.spec.template.spec.containers[0].env[1].value = "new value"'
| kubectl replace -f -
Het is vermeldenswaard dat de volgende twee opdrachten, die opeenvolgend worden uitgevoerd, sindsdien met succes zullen worden uitgevoerd deployment.yaml
bevat geen eigendom .metadata.resourceVersion
$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml
Dit lijkt in strijd te zijn met wat hierboven is gezegd, d.w.z. "toevoegen resourceVersion
in de metagegevens van de specificatie." Is het verkeerd om dat te zeggen? Nee, dat is niet zo, want als kubectl
mededelingen die u niet heeft opgegeven resourceVersion
, zal het het uit de bron lezen en toevoegen aan de door u opgegeven specificatie, en het dan pas uitvoeren replace
. Omdat dit potentieel gevaarlijk is als je op atomiciteit vertrouwt, werkt de magie volledig zijdelings kubectl
, moet u er niet op vertrouwen als u clientbibliotheken gebruikt die met de API werken. In dit geval moet u de huidige resourcespecificatie lezen, bijwerken en vervolgens uitvoeren PUT
verzoek.
Je kunt geen patch uitvoeren – wij doen een vervanging
Soms moet u enkele wijzigingen aanbrengen die niet door de API kunnen worden afgehandeld. In deze gevallen kunt u vervanging van de bron afdwingen door deze te verwijderen en opnieuw te maken. Dit gebeurt met behulp van kubectl replace --force
. Als u de opdracht uitvoert, worden de bronnen onmiddellijk verwijderd en vervolgens opnieuw gemaakt op basis van de opgegeven specificatie. Er is geen 'force replacement'-handler in de API, en om dit via de API te doen, moet u twee bewerkingen uitvoeren. Eerst moet u de bron verwijderen door deze in te stellen gracePeriodSeconds
naar nul (0) en propagationPolicy
in “Achtergrond” en maak vervolgens deze bron opnieuw met de gewenste specificatie.
Waarschuwing: deze aanpak is potentieel gevaarlijk en kan leiden tot een ongedefinieerde toestand.
Toepassen aan de serverzijde
Zoals hierboven vermeld, werken Kubernetes-ontwikkelaars aan de implementatie van de logica apply
van kubectl
in de Kubernetes-API. Logica apply
beschikbaar in Kubernetes 1.18 via kubectl apply --server-side
of via de API met behulp van de methode PATCH
с content-type
application/apply-patch+YAML
.
Opmerking: JSON is ook geldige YAML, dus u kunt de specificatie zelfs als JSON verzenden
content-type
zullenapplication/apply-patch+yaml
.
Naast die logica kubectl
wordt voor iedereen beschikbaar via API, apply
aan de serverzijde wordt bijgehouden wie verantwoordelijk is voor de velden in de specificatie, waardoor veilige meervoudige toegang mogelijk is voor conflictvrije bewerking. Met andere woorden: als apply
aan de serverkant zal het steeds wijdverspreider worden, er zal een universele, veilige interface voor resourcebeheer verschijnen voor verschillende clients, bijvoorbeeld kubectl, Pulumi of Terraform, GitOps, evenals zelfgeschreven scripts die gebruik maken van clientbibliotheken.
Resultaten van
Ik hoop dat dit korte overzicht van verschillende manieren om bronnen in clusters bij te werken nuttig voor u was. Het is goed om te weten dat het niet slechts een kwestie van toepassen versus vervangen is; het is mogelijk om een bron bij te werken met behulp van toepassen, bewerken, patchen of vervangen. Iedere aanpak heeft immers in principe zijn eigen toepassingsgebied. Voor atomaire veranderingen verdient vervangen de voorkeur; anders moet u de strategische merge-patch gebruiken via apply. Ik verwacht op zijn minst dat u begrijpt dat u Google of StackOerflow niet kunt vertrouwen bij het zoeken naar "kubernetes apply vs Replace". In ieder geval totdat dit artikel het huidige antwoord vervangt.
Bron: www.habr.com