Kubernetes biedt verschillende opties voor het bijwerken van resources: apply, edit, patch en replace. Er is verwarring over wat elk van deze doet en wanneer je ze moet toepassen. Laten we dat verduidelijken.

Als de zin "kubernetes apply vs replace", je vindt , wat niet juist is. "kubernetes apply vs patch" is de eerste link ā de documentatie op kubectl patch, die geen vergelijking bevat apply en patch. In dit artikel worden verschillende opties besproken, evenals het juiste gebruik van elk van hen.
Gedurende de levenscyclus van een Kubernetes-resource (service, deployment, ingress, enz.) is het soms nodig om bepaalde eigenschappen van deze resource te wijzigen, toe te voegen of te verwijderen. Bijvoorbeeld, een notitie toevoegen, of het aantal replicas verhogen of verlagen.
Kubernetes CLI
Als je al met Kubernetes-clusters werkt via de CLI, ben je vertrouwd met apply en Bewerk afbeeldingsparameters. De opdracht apply de specificatie van de resource uit een bestand lezen en een "upsert" in het Kubernetes-cluster doen, dat wil zeggen, de resource creƫren als deze niet bestaat, en deze bijwerken als deze bestaat. De opdracht Bewerk afbeeldingsparameters leest de resource via de API, waarna de specificatie van de resource in een lokaal bestand wordt geschreven, dat vervolgens in een teksteditor wordt geopend. Nadat je het bestand hebt bewerkt en opgeslagen, kubectl stuurt de wijzigingen terug via de API, die zorgzaam deze wijzigingen op de resource toepast.
Niet iedereen kent de opdracht patch en replace. De opdracht patch biedt de mogelijkheid om een deel van de specificatie van de resource te wijzigen door alleen het gewijzigde deel in de opdrachtregel op te geven. De opdracht replace werkt hetzelfde als Bewerk afbeeldingsparameters, maar alles moet handmatig gedaan worden: je moet de huidige versie van de specificatie van de resource downloaden, bijvoorbeeld met kubectl get -o yaml, deze bewerken en vervolgens gebruiken replace voor het bijwerken van de resource volgens de gewijzigde specificatie. De opdracht replace zal niet werken als er wijzigingen zijn geweest tussen het lezen en vervangen van de resource.
Kubernetes API
Waarschijnlijk ben je bekend met de methoden CoreV1().Pods().Update(), replaceNamespacedService of patch_namespaced_deployment, als je met clusters werkt via met behulp van een bepaalde programmeertaal. De bibliotheek verwerkt deze methoden met HTTP-verzoeken, waarbij de methoden TRACE en POST. Daarbij update en replace gebruikt TRACE, met behulp van 1 bit, gelijk aan 0, patch, hoe saai het ook klinkt, gebruikt POST.
Het moet worden opgemerkt dat kubectl werkt ook met clusters via de API. Met andere woorden, kubectlis een wrapper bovenop de clientbibliotheek voor de programmeertaal Go, die in belangrijke mate de mogelijkheid biedt om subcommando's compacter en leesbaarder te presenteren naast de standaard API-mogelijkheden. Bijvoorbeeld, zoals je wellicht al hebt opgemerkt, werd de methode apply niet genoemd in de vorige alinea. Op dit moment (mei 2020, opmerking van de vertaler) werkt alle logica kubectl apply, d.w.z. het creëren van niet-bestaande bronnen en het bijwerken van bestaande, volledig aan de kant van de code. kubectlEr worden inspanningen geleverd apply naar de API-kant te verplaatsen, maar dit is nog steeds in bètatesting. Hieronder zal ik het verder uitleggen.
Patch standaard
Het beste kan worden toegepast patch, als je een bron wilt bijwerken. Zo werken zowel clientbibliotheken bovenop de Kubernetes API als kubectl (niet verrassend, want het is een wrapper van de clientbibliotheek, opmerking van de vertaler).
Strategisch werken
Alle commando's kubectl apply, Bewerk afbeeldingsparameters en patch gebruik maken van de methode POST in HTTP-verzoeken om een bestaande bron bij te werken. Als we dieper ingaan op de implementatie van de commando's, dan maakt iedereen gebruik van de aanpak voor het bijwerken van bronnen, hoewel het commando patch ook andere benaderingen kan gebruiken (meer hierover hieronder). De aanpak strategic-merge patching probeert "alles goed te doen" bij het samenvoegen van de opgegeven specificatie met de bestaande specificatie. Meer specifiek probeert het zowel objecten als arrays samen te voegen, wat betekent dat wijzigingen meestal additief zijn. Bijvoorbeeld, het uitvoeren van het commando patch met een nieuwe omgevingsvariabele in de pod-container specificatie voegt deze omgevingsvariabele toe aan de bestaande omgevingsvariabelen, in plaats van ze te overschrijven. Om te verwijderen met deze aanpak moet de parameter expliciet op null worden ingesteld in de opgegeven specificatie. Welke commando's kubectl zijn het beste om te gebruiken voor updates?
Als je je bronnen aanmaakt en beheert via kubectl apply, is het altijd het beste om bij updates kubectl apply, zodat kubectl te gebruiken, zodat het de configuratie kan beheren en de gevraagde wijzigingen correct van toepassing tot toepassing kan volgen. Het voordeel van het altijd gebruiken van apply is dat het de eerder toegepaste specificatie bijhoudt, waardoor het weet wanneer specificatie-eigenschappen en array-elementen expliciet worden verwijderd. Dit maakt gebruik mogelijk. apply voor het verwijderen van eigenschappen en elementen van een array, terwijl gewone strategische samenvoegingen niet zullen werken. Commando's Bewerk afbeeldingsparameters en patch vernieuwen geen opmerkingen die kubectl apply worden toegepast voor het volgen van hun wijzigingen, dus eventuele wijzigingen die worden gevolgd en aangebracht via de Kubernetes API, maar gedaan via commando's Bewerk afbeeldingsparameters en patch, zijn onzichtbaar voor volgende commando's apply, namelijk de apply verwijdert ze niet, zelfs niet als ze niet verschijnen in de invoerspecificatie voor apply (In de documentatie staat dat Bewerk afbeeldingsparameters en patch ze opmerkingen bijwerken die worden gebruikt apply, maar in de praktijk ā niet).
Als je het commando niet gebruikt apply, kan het worden gebruikt als Bewerk afbeeldingsparameters, als voor patch, kies het commando dat het beste aansluit bij de wijziging die je aanbrengt. Bij het toevoegen en wijzigen van eigenschappen van de specificatie zijn beide benaderingen ongeveer gelijk. Bij het verwijderen van eigenschappen van de specificatie of elementen van de array Bewerk afbeeldingsparameters gedraagt zich als een eenmalige uitvoering apply, inclusief het volgen van wat de specificatie was vóór en na bewerking, zodat eigenschappen en elementen van de array expliciet uit de bron kunnen worden verwijderd. Het moet expliciet worden ingesteld op een null-waarde in de specificatie voor patch, om het uit de bron te verwijderen. Het verwijderen van een element van de array met behulp van strategische samenvoegpatching is complexer, omdat het gebruik van samenvoeginstructies vereist is. Zie hieronder andere benaderingen voor updates om meer acceptabele alternatieven te kiezen.
Om in de clientbibliotheek update-methoden te implementeren die zich gedragen als de bovengenoemde commando's kubectl, moeten in de verzoeken worden ingesteld content-type in application/strategic-merge-patch+json. Als je eigenschappen in de specificatie wilt verwijderen, moet je hun waarden expliciet instellen op null, vergelijkbaar met kubectl patch. Als je elementen van de array wilt verwijderen, moet je samenvoeginstructies opnemen in de update-specificatie of een andere benadering voor updates gebruiken.
Andere benaderingen voor updates
In Kubernetes worden twee andere benaderingen voor updates ondersteund: en De JSON merge patch-benadering accepteert gedeeltelijke specificaties van Kubernetes als invoer en ondersteunt het samenvoegen van objecten op een manier die lijkt op de benadering van strategic-merge patching. Het belangrijkste verschil is dat het alleen de vervangingen van arrays ondersteunt, inclusief de array van containers in de pod-specificatie. Dit betekent dat bij het gebruik van JSON merge patch je volledige specificaties moet opgeven voor alle containers als je een eigenschap van een container wijzigt. Daarom is deze benadering nuttig voor het verwijderen van elementen uit een array in de specificatie. In de opdrachtregel kun je JSON merge patch selecteren met kubectl patch --type=merge. Bij het werken met de Kubernetes API moet je de verzoekmethode gebruiken POST en instellen content-type in application/merge-patch+json.
De JSON patch-benadering gebruikt, in plaats van een gedeeltelijke specificatie van de resource op te geven, een array van wijzigingen die je wilt aanbrengen in de resource, waarbij elk element van de array een beschrijving van de wijziging vertegenwoordigt die aan de resource wordt aangebracht. Deze benadering is een flexibelere en krachtigere manier om de aangebrachte wijzigingen uit te drukken, maar ten koste van het feit dat de lijst van aangebrachte wijzigingen in een apart, niet-Kubernetes-formaat komt, in plaats van een gedeeltelijke specificatie van de resource te verzenden. In kubectl kun je JSON patch selecteren met kubectl patch --type=json. Bij het gebruik van de Kubernetes API werkt deze benadering met de verzoekmethode POST en instellen content-type in application/json-patch+json.
Behoefte aan zekerheid ā we gebruiken replace
In sommige gevallen is het nodig om er zeker van te zijn dat er geen wijzigingen in de resource worden aangebracht tussen het moment van het lezen van de resource en de update. Met andere woorden, je moet ervoor zorgen dat alle wijzigingen atomairzijn. In dat geval is het verstandig om replacete gebruiken. Bijvoorbeeld, als er een ConfigMap is met een teller die door meerdere bronnen wordt bijgewerkt, moet je ervoor zorgen dat twee bronnen de teller niet tegelijkertijd bijwerken, wat zou leiden tot verlies van een update. Ter illustratie stel je een reeks gebeurtenissen voor met de benadering patch:
- A en B halen de huidige status van de resource op uit de API
- Elk van hen werkt vervolgens lokaal de specificatie bij door de teller met ƩƩn te verhogen en respectievelijk 'A' of 'B' toe te voegen aan de opmerking 'updated-by'
- A is iets sneller en werkt de resource bij
- B werkt de resource bij
Als resultaat is update A verloren. Laatste actie patch wint, de teller stijgt met ƩƩn in plaats van twee, en de waarde van de opmerking "updated-by" eindigt op "B" en bevat niet "A". Laten we het bovenstaande vergelijken met wat er gebeurt wanneer updates worden uitgevoerd met behulp van de aanpak replace:
- A en B halen de huidige status van de resource op uit de API
- Elk van hen werkt vervolgens lokaal de specificatie bij door de teller met ƩƩn te verhogen en respectievelijk 'A' of 'B' toe te voegen aan de opmerking 'updated-by'
- A is iets sneller en werkt de resource bij
- B probeert de bron bij te werken, maar de update wordt door de API geweigerd omdat de versie van de bron in de specificatie
replaceniet overeenkomt met de huidige versie van de bron in Kubernetes, aangezien de versie van de bron is verhoogd tijdens de vervangingsoperatie aan de kant van A.
In het bovenstaande geval zal B de bron opnieuw moeten ophalen, wijzigingen aanbrengen in de nieuwe status en opnieuw proberen het replace. Daardoor zal de teller met twee worden verhoogd en zal de opmerking "updated-by" "AB" aan het einde bevatten.
Het bovenstaande voorbeeld impliceert dat bij de uitvoering van replace een volledige vervanging van de hele bron plaatsvindt. De specificatie die wordt gebruikt voor replace, moet geen gedeeltelijke zijn, of delen zoals in apply, maar volledig zijn, inclusief de toevoeging van resourceVersion in de metadata van de specificatie. Als u het niet hebt opgenomen resourceVersion of de versie die u heeft opgegeven is niet de huidige, zal de vervanging worden geweigerd. Daarom is de beste aanpak om replace de bron te lezen, deze bij te werken en onmiddellijk te vervangen. Met behulp van kubectl, kan dit er als volgt uitzien:
$ kubectl get deployment my-deployment -o json
| jq '.spec.template.spec.containers[0].env[1].value = "new value"'
| kubectl replace -f -Let op dat de volgende twee opdrachten, die achtereenvolgens worden uitgevoerd, succesvol zullen zijn, aangezien service.yaml geen eigenschap bevat .metadata.resourceVersion
$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yamlHet lijkt misschien tegenstrijdig met wat hierboven is gezegd, namelijk "de toevoeging resourceVersion aan de metadata van de specificatie". Is het onjuist om dit te beweren? Nee, dat is het niet, aangezien als kubectl ziet dat u niet hebt opgegeven resourceVersion, hij deze zal lezen uit de bron en toevoegen aan de specificatie die u hebt opgegeven en pas daarna zal uitvoeren replace. Aangezien deze potentieel gevaarlijk is, als men afhankelijk is van atomiciteit, werkt deze magie volledig aan de kant van kubectl, moet men niet op deze vertrouwen bij het gebruik van clientbibliotheken die met de API werken. In dit geval moet u de huidige specificatie van de bron lezen, deze bijwerken en vervolgens een TRACE verzoek uitvoeren.
Je kunt geen patch maken - je doet een vervanging.
Soms zijn er wijzigingen nodig die niet via de API kunnen worden uitgevoerd. In die gevallen kan een resource geforceerd worden vervangen door deze te verwijderen en opnieuw aan te maken. Dit gebeurt met behulp van kubectl replace --force. Het uitvoeren van de opdracht verwijdert onmiddellijk de resources en maakt ze opnieuw aan volgens de gegeven specificatie. De API heeft geen handler voor "forcibly replace", en om dit via de API te doen, moeten twee bewerkingen worden uitgevoerd. Eerst moet de resource worden verwijderd, waarbij gracePeriodSeconds op nul (0) wordt ingesteld en propagationPolicy op 'Background' staat, en vervolgens moet deze resource opnieuw worden aangemaakt met de gewenste specificatie.
Let op: deze aanpak is potentieel riskant en kan leiden tot een ongedefinieerde toestand.
Apply aan de serverzijde.
Zoals eerder vermeld, werken de ontwikkelaars van Kubernetes aan de implementatie van logica apply uit kubectl in de Kubernetes API. De logica apply is beschikbaar in Kubernetes 1.18 via kubectl apply --server-side of via de API, met de methode POST met content-type application/apply-patch+YAML.
Opmerking: JSON is ook geldige YAML, dus je kunt de specificatie als JSON verzenden, zelfs als
content-typezalapplication/apply-patch+yaml.
Bovendien, aangezien de logica kubectl beschikbaar wordt voor iedereen via de API, apply houdt de serverzijde toezicht op de verantwoordelijken voor de velden in de specificatie, waardoor veilig multi-user toegang voor conflictvrij bewerken mogelijk wordt. Met andere woorden, als apply de serverzijde breder wordt verspreid, zal er een universele veilige interface voor resourcebeheer ontstaan voor verschillende clients, zoals kubectl, Pulumi of Terraform, GitOps, en ook zelfgeschreven scripts die gebruikmaken van klantbibliotheken.
Conclusies
Ik hoop dat dit korte overzicht van de verschillende manieren om resources in clusters bij te werken nuttig voor je was. Het is nuttig om te weten dat het niet gewoon 'apply' tegen 'replace' is, want je kunt een resource bijwerken met behulp van apply, edit, patch of replace. Iedere aanpak heeft zijn toepassingsgebied. Voor atomische wijzigingen verdient replace de voorkeur; in andere gevallen moet je strategic-merge patch via apply gebruiken. Uiteindelijk hoop ik dat je hebt begrepen dat je Google of StackOverflow niet kunt vertrouwen bij het zoeken naar "kubernetes apply vs replace", althans totdat dit artikel het huidige antwoord vervangt.

Bron: habr.com
