Kubernetes bietet mehrere Optionen zum Aktualisieren von Ressourcen: Anwenden, Bearbeiten, Patchen und Ersetzen. Es herrscht Unklarheit darüber, was die einzelnen Funktionen tun und wann sie eingesetzt werden sollen. Lass es uns herausfinden.
wenn kubectl patch
, was keinen Vergleich beinhaltet apply
и patch
. In diesem Artikel werden die verschiedenen Optionen sowie deren ordnungsgemäße Verwendung erläutert.
Während des Lebenszyklus einer Kubernetes-Ressource (Dienst, Bereitstellung, Ingress usw.) müssen Sie manchmal einige Eigenschaften dieser Ressource ändern, hinzufügen oder entfernen. Fügen Sie beispielsweise eine Notiz hinzu oder erhöhen oder verringern Sie die Anzahl der Replikate.
Kubernetes-CLI
Wenn Sie bereits über die CLI mit Kubernetes-Clustern arbeiten, sind Sie damit bereits vertraut apply
и edit
. Mannschaft apply
liest die Ressourcenspezifikation aus der Datei und führt einen „Upsert“ zum Kubernetes-Cluster durch, d. h. erstellt die Ressource, wenn sie nicht vorhanden ist, und aktualisiert sie, wenn sie vorhanden ist. Team edit
liest eine Ressource über die API und schreibt dann die Ressourcenspezifikation in eine lokale Datei, die dann in einem Texteditor geöffnet wird. Nachdem Sie die Datei bearbeitet und gespeichert haben, kubectl
sendet die vorgenommenen Änderungen über die API zurück, die diese Änderungen sorgfältig auf die Ressource anwendet.
Nicht jeder kennt die Befehle patch
и replace
. Mannschaft patch
ermöglicht es Ihnen, einen Teil einer Ressourcenspezifikation zu ändern und nur den geänderten Teil in der Befehlszeile bereitzustellen. Team replace
funktioniert genauso wie edit
, aber alles muss manuell erledigt werden: Sie müssen die aktuelle Version der Ressourcenspezifikation herunterladen, beispielsweise mit kubectl get -o yaml
, bearbeiten Sie es und verwenden Sie es dann replace
um eine Ressource gemäß einer geänderten Spezifikation zu aktualisieren. Team replace
funktioniert nicht, wenn zwischen dem Lesen und Ersetzen der Ressource Änderungen aufgetreten sind.
Kubernetes-API
Sie sind wahrscheinlich mit den Methoden vertraut CoreV1().Pods().Update()
, replaceNamespacedService
oder patch_namespaced_deployment
, wenn Sie mit Clustern arbeiten über PUT
и PATCH
. In diesem Fall update
и replace
verwenden PUT
Und patch
, egal wie trivial es auch sein mag, verwendet PATCH
.
Es sollte angemerkt werden, dass kubectl
Funktioniert auch mit Clustern über API. Mit anderen Worten, kubectl
ist ein Wrapper auf der Client-Bibliothek für die Go-Sprache, der neben den Standard-API-Funktionen weitgehend die Möglichkeit bietet, Unterbefehle in einer kompakteren und lesbareren Form bereitzustellen. Zum Beispiel, wie Sie vielleicht schon bemerkt haben, die Methode apply
wurde oben im vorherigen Absatz nicht erwähnt. Derzeit (Mai 2020, ca. Übersetzer) alles Logik kubectl apply
, d.h. Das Erstellen nicht vorhandener Ressourcen und das Aktualisieren vorhandener Ressourcen erfolgt vollständig auf der Codeseite kubectl
. Es werden Anstrengungen unternommen apply
auf der API-Seite, aber es ist noch in der Beta-Phase. Ich werde weiter unten ausführlicher schreiben.
Standardmäßig patchen
Am besten verwendet patch
, wenn Sie die Ressource aktualisieren möchten. Auf diese Weise funktionieren beide Client-Bibliotheken auf der Kubernetes-API und kubectl
(nicht überraschend, da es sich um einen Wrapper für die Client-Bibliothek handelt, ca. Übersetzer).
Arbeiten Sie strategisch
Alle Mannschaften kubectl
apply
, edit
и patch
Verwenden Sie die Methode PATCH
in HTTP-Anfragen zum Aktualisieren einer vorhandenen Ressource. Wenn Sie sich näher mit der Implementierung von Befehlen befassen, verwenden alle den Ansatz patch
kann andere Ansätze verwenden (mehr dazu weiter unten). Beim strategischen Merge-Patching-Ansatz wird versucht, „es richtig zu machen“, indem die bereitgestellte Spezifikation mit der vorhandenen Spezifikation zusammengeführt wird. Genauer gesagt wird versucht, sowohl Objekte als auch Arrays zu kombinieren, was bedeutet, dass die Änderungen tendenziell additiv sind. Beispiel: Ausführen des Befehls patch
mit einer neuen Umgebungsvariablen in der Pod-Container-Spezifikation führt dazu, dass diese Umgebungsvariable zu den vorhandenen Umgebungsvariablen hinzugefügt wird, anstatt sie zu überschreiben. Um diesen Ansatz zu verwenden, müssen Sie den Parameterwert in der bereitgestellten Spezifikation auf Null setzen. Welches der Teams kubectl
Ist es am besten zum Aktualisieren zu verwenden?
Wenn Sie Ihre Ressourcen erstellen und verwalten mit kubectl apply
, beim Aktualisieren ist es besser, immer zu verwenden kubectl apply
Auf kubectl
konnte die Konfiguration verwalten und angeforderte Änderungen von Anwendung zu Anwendung korrekt verfolgen. Vorteil immer nutzen apply
Der Vorteil liegt darin, dass es eine zuvor angewendete Spezifikation verfolgt und so weiß, wann Spezifikationseigenschaften und Array-Elemente explizit entfernt werden. Dies ermöglicht Ihnen die Verwendung apply
um Eigenschaften und Array-Elemente zu entfernen, während eine normale strategische Zusammenführung nicht funktioniert. Mannschaften edit
и patch
Notizen nicht aktualisieren kubectl apply
verwendet, um seine Änderungen zu verfolgen, also alle Änderungen, die über die Kubernetes-API verfolgt und vorgenommen, aber über Befehle vorgenommen werden edit
и patch
, unsichtbar für nachfolgende Befehle apply
Das heißt, apply
entfernt sie nicht, auch wenn sie nicht in der Eingabespezifikation für erscheinen apply
(Die Dokumentation sagt das edit
и patch
Aktualisierungen der verwendeten Notizen vornehmen apply
, aber in der Praxis - nein).
Wenn Sie den Befehl nicht verwenden apply
, kann verwendet werden als edit
Und patch
, indem Sie den Befehl auswählen, der am besten zu der vorgenommenen Änderung passt. Beim Hinzufügen und Ändern von Stücklisteneigenschaften sind beide Ansätze ungefähr gleich. Beim Löschen von Spezifikationseigenschaften oder Array-Elementen edit
verhält sich wie ein einmaliger Start apply
, einschließlich der Verfolgung des Zustands der Spezifikation vor und nach der Bearbeitung, sodass Sie Eigenschaften und Array-Elemente explizit aus einer Ressource entfernen können. Sie müssen den Eigenschaftswert in der Spezifikation für explizit auf null setzen patch
um es aus der Ressource zu entfernen. Das Entfernen eines Array-Elements mithilfe des strategischen Merge-Patchings ist komplexer, da hierfür Merge-Anweisungen erforderlich sind. Weitere praktikablere Alternativen finden Sie weiter unten in den anderen Upgrade-Ansätzen.
Um Aktualisierungsmethoden in der Clientbibliothek zu implementieren, die sich ähnlich wie die oben genannten Befehle verhalten kubectl
, sollte in Anfragen festgelegt werden content-type
в application/strategic-merge-patch+json
. Wenn Sie Eigenschaften in einer Spezifikation entfernen möchten, müssen Sie deren Werte auf ähnliche Weise explizit auf Null setzen kubectl patch
. Wenn Sie Array-Elemente entfernen müssen, sollten Sie Merge-Direktiven in die Update-Spezifikation aufnehmen oder einen anderen Ansatz für Updates verwenden.
Andere Ansätze für Updates
Kubernetes unterstützt zwei weitere Update-Ansätze: kubectl patch --type=merge
. Wenn Sie mit der Kubernetes-API arbeiten, sollten Sie die Request-Methode verwenden PATCH
und Installation content-type
в application/merge-patch+json
.
Der JSON-Patch-Ansatz stellt statt einer teilweisen Spezifikation einer Ressource die Änderungen, die Sie an der Ressource vornehmen möchten, als Array bereit, wobei jedes Element des Arrays eine Beschreibung der an der Ressource vorgenommenen Änderung darstellt. Dieser Ansatz ist eine flexiblere und leistungsfähigere Möglichkeit, die vorgenommenen Änderungen auszudrücken, allerdings auf Kosten der Auflistung der vorgenommenen Änderungen in einem separaten Nicht-Kubernetes-Format, anstatt eine teilweise Ressourcenspezifikation zu senden. IN kubectl
Sie können den JSON-Patch mit auswählen kubectl patch --type=json
. Bei Verwendung der Kubernetes-API funktioniert dieser Ansatz über die Request-Methode PATCH
und Installation content-type
в application/json-patch+json
.
Wir brauchen Vertrauen – verwenden Sie Ersetzen
In manchen Fällen müssen Sie sicherstellen, dass zwischen dem Lesen der Ressource und der Aktualisierung keine Änderungen an einer Ressource vorgenommen werden. Mit anderen Worten: Sie sollten sicherstellen, dass alle Änderungen wirksam werden atomar. In diesem Fall sollten Sie zum Aktualisieren Ressourcen verwenden replace
. Wenn Sie beispielsweise über eine ConfigMap mit einem Zähler verfügen, der von mehreren Quellen aktualisiert wird, sollten Sie sicherstellen, dass nicht zwei Quellen den Zähler gleichzeitig aktualisieren, wodurch die Aktualisierung verloren geht. Stellen Sie sich zur Veranschaulichung eine Abfolge von Ereignissen vor, die diesen Ansatz verwenden patch
:
- A und B erhalten den aktuellen Status der Ressource von der API
- Jeder aktualisiert die Spezifikation lokal, indem er den Zähler um eins erhöht und außerdem „A“ bzw. „B“ zur Notiz „aktualisiert von“ hinzufügt
- Und es aktualisiert die Ressource etwas schneller
- B aktualisiert die Ressource
Dadurch geht Update A verloren. Letzte Operation patch
gewinnt, wird der Zähler um eins statt um zwei erhöht, und der Wert der Notiz „aktualisiert von“ endet mit „B“ und enthält kein „A“. Vergleichen wir das oben Gesagte mit dem, was passiert, wenn Aktualisierungen mit diesem Ansatz durchgeführt werden replace
:
- A und B erhalten den aktuellen Status der Ressource von der API
- Jeder aktualisiert die Spezifikation lokal, indem er den Zähler um eins erhöht und außerdem „A“ bzw. „B“ zur Notiz „aktualisiert von“ hinzufügt
- Und es aktualisiert die Ressource etwas schneller
- B versucht, die Ressource zu aktualisieren, aber die Aktualisierung wird von der API abgelehnt, da die Ressourcenversion in der Spezifikation enthalten ist
replace
stimmt nicht mit der aktuellen Version der Ressource in Kubernetes überein, da die Version der Ressource durch den Ersetzungsvorgang von A erhöht wurde.
Im obigen Fall muss B die Ressource erneut abrufen, Änderungen am neuen Status vornehmen und es erneut versuchen replace
. Dadurch wird der Zähler um zwei erhöht und der Hinweis „Aktualisiert von“ enthält am Ende „AB“.
Das obige Beispiel impliziert dies bei der Ausführung replace
Die gesamte Ressource wird vollständig ersetzt. Spezifikation verwendet für replace
, darf nicht teilweise oder in Teilen wie in sein apply
, aber vollständig, einschließlich der Ergänzung resourceVersion
in die Spezifikationsmetadaten. Wenn Sie es nicht aktiviert haben resourceVersion
oder die von Ihnen bereitgestellte Version nicht aktuell ist, wird der Ersatz abgelehnt. Der beste Ansatz ist also replace
– Lesen Sie die Ressource, aktualisieren Sie sie und ersetzen Sie sie sofort. Benutzen kubectl
, es könnte so aussehen:
$ kubectl get deployment my-deployment -o json
| jq '.spec.template.spec.containers[0].env[1].value = "new value"'
| kubectl replace -f -
Es ist erwähnenswert, dass die folgenden beiden Befehle, die nacheinander ausgeführt werden, erfolgreich ausgeführt werden, da deployment.yaml
enthält keine Eigenschaft .metadata.resourceVersion
$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml
Dies scheint dem oben Gesagten zu widersprechen, d. h. „Hinzufügen resourceVersion
in die Spezifikationsmetadaten.“ Ist es falsch, das zu sagen? Nein, ist es nicht, denn if kubectl
bemerkt, dass Sie keine Angaben gemacht haben resourceVersion
, liest es es aus der Ressource, fügt es der von Ihnen angegebenen Spezifikation hinzu und führt es erst dann aus replace
. Da dies potenziell gefährlich ist, wenn man sich auf Atomizität verlässt, funktioniert die Magie völlig nebenbei kubectl
, sollten Sie sich nicht darauf verlassen, wenn Sie Clientbibliotheken verwenden, die mit der API arbeiten. In diesem Fall müssen Sie die aktuelle Ressourcenspezifikation lesen, aktualisieren und dann ausführen PUT
Anfrage.
Sie können keinen Patch machen – wir machen einen Ersatz
Manchmal müssen Sie einige Änderungen vornehmen, die von der API nicht verarbeitet werden können. In diesen Fällen können Sie den Austausch der Ressource erzwingen, indem Sie sie löschen und neu erstellen. Dies geschieht mit kubectl replace --force
. Durch die Ausführung des Befehls werden die Ressourcen sofort entfernt und anschließend anhand der bereitgestellten Spezifikation neu erstellt. In der API gibt es keinen „Force-Replace“-Handler. Um dies über die API zu tun, müssen Sie zwei Vorgänge ausführen. Zuerst müssen Sie die Ressource löschen, indem Sie sie festlegen gracePeriodSeconds
auf Null (0) und propagationPolicy
in „Hintergrund“ und erstellen Sie dann diese Ressource mit der gewünschten Spezifikation neu.
Warnung: Dieser Ansatz ist potenziell gefährlich und kann zu einem undefinierten Zustand führen.
Auf der Serverseite anwenden
Wie oben erwähnt, arbeiten Kubernetes-Entwickler an der Implementierung der Logik apply
von kubectl
in der Kubernetes-API. Logiken apply
Verfügbar in Kubernetes 1.18 über kubectl apply --server-side
oder über die API mit der Methode PATCH
с content-type
application/apply-patch+YAML
.
Hinweis: JSON ist auch gültiges YAML, sodass Sie die Spezifikation auch dann als JSON senden können
content-type
werdenapplication/apply-patch+yaml
.
Abgesehen von dieser Logik kubectl
wird über die API für jedermann verfügbar, apply
Verfolgt auf der Serverseite, wer für die Felder in der Spezifikation verantwortlich ist, und ermöglicht so einen sicheren Mehrfachzugriff für deren konfliktfreie Bearbeitung. Mit anderen Worten, wenn apply
Auf der Serverseite wird es eine größere Verbreitung geben, eine universelle sichere Ressourcenverwaltungsschnittstelle für verschiedene Clients erscheinen, zum Beispiel Kubectl, Pulumi oder Terraform, GitOps, sowie selbst geschriebene Skripte unter Verwendung von Client-Bibliotheken.
Ergebnisse
Ich hoffe, dieser kurze Überblick über verschiedene Möglichkeiten zur Aktualisierung von Ressourcen in Clustern war hilfreich für Sie. Es ist gut zu wissen, dass es nicht nur um Anwenden oder Ersetzen geht; es ist auch möglich, eine Ressource durch Anwenden, Bearbeiten, Patchen oder Ersetzen zu aktualisieren. Denn grundsätzlich hat jeder Ansatz seinen eigenen Anwendungsbereich. Für atomare Änderungen ist „replace“ vorzuziehen; andernfalls sollten Sie den „Strategic-Merge-Patch“ über „Apply“ verwenden. Zumindest erwarte ich, dass Sie verstehen, dass Sie Google oder StackOerflow bei der Suche nach „Kubernetes anwenden vs. ersetzen“ nicht vertrauen können. Zumindest bis dieser Artikel die aktuelle Antwort ersetzt.
Source: habr.com