Kubernetes propose plusieurs options pour mettre à jour les ressources : appliquer, modifier, corriger et remplacer. Il existe une confusion quant à ce que chacun fait et quand les utiliser. Voyons cela.
si kubectl patch
, qui n'inclut pas de comparaison apply
и patch
. Cet article examinera les différentes options, ainsi que la bonne utilisation de chacune d’elles.
Durant le cycle de vie d'une ressource Kubernetes (service, déploiement, entrée, etc.), vous devez parfois modifier, ajouter ou supprimer certaines propriétés de cette ressource. Par exemple, ajoutez une note, augmentez ou diminuez le nombre de répliques.
CLI Kubernetes
Si vous travaillez déjà avec des clusters Kubernetes via la CLI, vous connaissez déjà apply
и edit
. Équipe apply
lit la spécification de ressource à partir du fichier et effectue un "upsert" vers le cluster Kubernetes, c'est-à-dire crée la ressource si elle n'existe pas et la met à jour si elle existe. Équipe edit
lit une ressource via l'API, puis écrit la spécification de la ressource dans un fichier local, qui est ensuite ouvert dans un éditeur de texte. Après avoir modifié et enregistré le fichier, kubectl
enverra les modifications apportées via l'API, qui appliquera soigneusement ces modifications à la ressource.
Tout le monde ne connaît pas les commandes patch
и replace
. Équipe patch
vous permet de modifier une partie d'une spécification de ressource, en fournissant uniquement la partie modifiée sur la ligne de commande. Équipe replace
fonctionne de la même manière que edit
, mais tout doit être fait manuellement : vous devez télécharger la version actuelle de la spécification de ressource, par exemple en utilisant kubectl get -o yaml
, modifiez-le, puis utilisez replace
pour mettre à jour une ressource selon une spécification modifiée. Équipe replace
ne fonctionnera pas si des changements se sont produits entre la lecture et le remplacement de la ressource.
API Kubernetes
Vous connaissez probablement les méthodes CoreV1().Pods().Update()
, replaceNamespacedService
ou patch_namespaced_deployment
, si vous travaillez avec des clusters via PUT
и PATCH
. Dans ce cas, update
и replace
utiliser PUT
Et patch
, aussi trivial soit-il, utilise PATCH
.
Il convient de noter que kubectl
fonctionne également avec des clusters via API. Autrement dit, kubectl
est un wrapper au-dessus de la bibliothèque client pour le langage Go, qui offre en grande partie la possibilité de fournir des sous-commandes sous une forme plus compacte et plus lisible en plus des capacités API standard. Par exemple, comme vous l'avez peut-être déjà remarqué, la méthode apply
n’a pas été mentionné ci-dessus dans le paragraphe précédent. Actuellement (mai 2020, environ. traducteur) toute la logique kubectl apply
, c'est à dire. créer des ressources inexistantes et mettre à jour celles existantes, fonctionne entièrement côté code kubectl
. Des efforts sont faits apply
du côté de l'API, mais il est toujours en version bêta. J'écrirai plus en détail ci-dessous.
Patch par défaut
Mieux utilisé patch
, si vous souhaitez mettre à jour la ressource. C'est ainsi que les deux bibliothèques clientes fonctionnent au-dessus de l'API Kubernetes et kubectl
(pas surprenant, puisqu'il s'agit d'un wrapper pour la bibliothèque client, environ. traducteur).
Travailler de manière stratégique
Toutes les équipes kubectl
apply
, edit
и patch
utiliser la méthode PATCH
dans les requêtes HTTP pour mettre à jour une ressource existante. Si vous approfondissez la mise en œuvre des commandes, elles utilisent toutes l'approche patch
peut utiliser d’autres approches (plus d’informations à ce sujet ci-dessous). L'approche de mise à jour stratégique par fusion tente de « bien faire les choses » en fusionnant la spécification fournie avec la spécification existante. Plus précisément, il tente de combiner à la fois des objets et des tableaux, ce qui signifie que les modifications ont tendance à être additives. Par exemple, exécuter la commande patch
avec une nouvelle variable d'environnement dans la spécification du conteneur de pods, cette variable d'environnement est ajoutée aux variables d'environnement existantes plutôt que de les écraser. Pour supprimer à l’aide de cette approche, vous devez forcer la valeur du paramètre à null dans la spécification fournie. Laquelle des équipes kubectl
Est-il préférable de l'utiliser pour la mise à jour ?
Si vous créez et gérez vos ressources en utilisant kubectl apply
, lors de la mise à jour, il est préférable de toujours utiliser kubectl apply
À kubectl
pourrait gérer la configuration et suivre correctement les modifications demandées d’une application à l’autre. Avantage toujours utiliser apply
est qu'il garde la trace d'une spécification précédemment appliquée, ce qui lui permet de savoir quand les propriétés de la spécification et les éléments du tableau sont explicitement supprimés. Cela vous permet d'utiliser apply
pour supprimer les propriétés et les éléments du tableau, alors qu'une fusion stratégique normale ne fonctionnera pas. Équipes edit
и patch
ne pas mettre à jour les notes qui kubectl apply
utilise pour suivre ses modifications, donc toutes les modifications qui sont suivies et apportées via l'API Kubernetes, mais effectuées via des commandes edit
и patch
, invisible pour les commandes suivantes apply
C'est-à- apply
ne les supprime pas même s'ils n'apparaissent pas dans la spécification d'entrée pour apply
(La documentation dit que edit
и patch
mettre à jour les notes utilisées apply
, mais en pratique - non).
Si vous n'utilisez pas la commande apply
, peut être utilisé comme edit
Et patch
, en choisissant la commande la mieux adaptée au changement en cours. Lors de l'ajout et de la modification de propriétés de nomenclature, les deux approches sont à peu près identiques. Lors de la suppression de propriétés de spécification ou d'éléments de tableau edit
se comporte comme un lancement unique apply
, y compris le suivi de la spécification avant et après sa modification, afin que vous puissiez explicitement supprimer les propriétés et les éléments du tableau d'une ressource. Vous devez définir explicitement la valeur de la propriété sur null dans la spécification pour patch
pour le supprimer de la ressource. La suppression d'un élément de tableau à l'aide de correctifs de fusion stratégique est plus complexe car elle nécessite l'utilisation de directives de fusion. Consultez d’autres approches de mise à niveau ci-dessous pour des alternatives plus viables.
Pour implémenter des méthodes de mise à jour dans la bibliothèque client qui se comportent de manière similaire aux commandes ci-dessus kubectl
, doit être défini dans les requêtes content-type
в application/strategic-merge-patch+json
. Si vous souhaitez supprimer des propriétés dans une spécification, vous devez définir explicitement leurs valeurs sur null de la même manière kubectl patch
. Si vous devez supprimer des éléments du tableau, vous devez inclure des directives de fusion dans la spécification de mise à jour ou utiliser une approche différente pour les mises à jour.
Autres approches des mises à jour
Kubernetes prend en charge deux autres approches de mise à jour : kubectl patch --type=merge
. Lorsque vous travaillez avec l'API Kubernetes, vous devez utiliser la méthode de requête PATCH
et montage content-type
в application/merge-patch+json
.
L'approche du correctif JSON, plutôt que de fournir une spécification partielle d'une ressource, consiste à fournir les modifications que vous souhaitez apporter à la ressource sous forme de tableau, dans lequel chaque élément du tableau représente une description de la modification apportée à la ressource. Cette approche constitue un moyen plus flexible et plus puissant d'exprimer les modifications apportées, mais au prix de la liste des modifications apportées dans un format distinct, non Kubernetes, plutôt que d'envoyer une spécification de ressource partielle. DANS kubectl
vous pouvez sélectionner le patch JSON en utilisant kubectl patch --type=json
. Lors de l'utilisation de l'API Kubernetes, cette approche fonctionne en utilisant la méthode de requête PATCH
et montage content-type
в application/json-patch+json
.
Nous avons besoin de confiance - utilisez replace
Dans certains cas, vous devez vous assurer qu'aucune modification n'est apportée à une ressource entre le moment où la ressource est lue et le moment où elle est mise à jour. En d'autres termes, vous devez vous assurer que tous les changements seront atomique. Dans ce cas, pour mettre à jour les ressources, vous devez utiliser replace
. Par exemple, si vous disposez d'un ConfigMap avec un compteur mis à jour par plusieurs sources, vous devez vous assurer que deux sources ne mettent pas à jour le compteur en même temps, ce qui entraînerait la perte de la mise à jour. Pour démontrer, imaginez une séquence d’événements en utilisant l’approche patch
:
- A et B obtiennent l'état actuel de la ressource à partir de l'API
- Chacun met à jour localement la spécification en incrémentant le compteur de un et en ajoutant également respectivement "A" ou "B" à la note "mis à jour par".
- Et il met à jour la ressource un peu plus rapidement
- B met à jour la ressource
Par conséquent, la mise à jour A est perdue. Dernière opération patch
gagne, le compteur est incrémenté de un au lieu de deux, et la valeur de la note « mise à jour par » se termine par « B » et ne contient pas de « A ». Comparons ce qui précède avec ce qui se passe lorsque les mises à jour sont effectuées en utilisant l'approche replace
:
- A et B obtiennent l'état actuel de la ressource à partir de l'API
- Chacun met à jour localement la spécification en incrémentant le compteur de un et en ajoutant également respectivement "A" ou "B" à la note "mis à jour par".
- Et il met à jour la ressource un peu plus rapidement
- B essaie de mettre à jour la ressource, mais la mise à jour est rejetée par l'API car la version de la ressource est dans la spécification
replace
ne correspond pas à la version actuelle de la ressource dans Kubernetes car la version de la ressource a été augmentée par l'opération de remplacement de A.
Dans le cas ci-dessus, B devra récupérer la ressource, apporter des modifications au nouvel état et réessayer replace
. Cela entraînera une incrémentation du compteur de deux et la note « mis à jour par » inclura « AB » à la fin.
L'exemple ci-dessus implique que lors de l'exécution replace
La ressource entière est complètement remplacée. Spécification utilisée pour replace
, ne doit pas être partiel, ni en partie comme dans apply
, mais complet, y compris l'ajout resourceVersion
dans les métadonnées de la spécification. Si vous n'avez pas activé resourceVersion
ou la version que vous fournissez n'est pas à jour, le remplacement sera rejeté. La meilleure approche à utiliser est donc replace
– lisez la ressource, mettez-la à jour et remplacez-la immédiatement. En utilisant kubectl
, cela pourrait ressembler à ceci :
$ kubectl get deployment my-deployment -o json
| jq '.spec.template.spec.containers[0].env[1].value = "new value"'
| kubectl replace -f -
Il convient de noter que les deux commandes suivantes, exécutées séquentiellement, s'exécuteront avec succès, car deployment.yaml
ne contient pas de propriété .metadata.resourceVersion
$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml
Cela semble contredire ce qui a été dit ci-dessus, c'est-à-dire "ajouter resourceVersion
dans les métadonnées de la spécification." Est-ce faux de dire cela ? Non, ce n'est pas le cas, parce que si kubectl
remarques que vous n'avez pas précisées resourceVersion
, il le lira à partir de la ressource et l'ajoutera à la spécification que vous avez spécifiée, puis l'exécutera seulement replace
. Parce que c'est potentiellement dangereux si vous comptez sur l'atomicité, la magie opère entièrement du côté kubectl
, vous ne devez pas vous y fier lorsque vous utilisez des bibliothèques clientes qui fonctionnent avec l'API. Dans ce cas, vous devrez lire la spécification de ressource actuelle, la mettre à jour puis exécuter PUT
demande.
Vous ne pouvez pas créer de correctif – nous effectuons un remplacement
Parfois, vous devez apporter des modifications qui ne peuvent pas être gérées par l'API. Dans ces cas, vous pouvez forcer le remplacement de la ressource en la supprimant et en la recréant. Cela se fait en utilisant kubectl replace --force
. L'exécution de la commande supprime immédiatement les ressources, puis les recrée à partir de la spécification fournie. Il n'y a pas de gestionnaire de « remplacement forcé » dans l'API, et pour le faire via l'API, vous devez effectuer deux opérations. Vous devez d'abord supprimer la ressource en la définissant gracePeriodSeconds
à zéro (0) et propagationPolicy
dans « Arrière-plan », puis recréez cette ressource avec la spécification souhaitée.
Avertissement : Cette approche est potentiellement dangereuse et peut conduire à un état indéfini.
Postuler côté serveur
Comme mentionné ci-dessus, les développeurs Kubernetes travaillent sur la mise en œuvre de la logique apply
de kubectl
dans l'API Kubernetes. Logiques apply
disponible dans Kubernetes 1.18 via kubectl apply --server-side
soit via l'API en utilisant la méthode PATCH
с content-type
application/apply-patch+YAML
.
Remarque : JSON est également un YAML valide, vous pouvez donc envoyer la spécification au format JSON même si
content-type
volontéapplication/apply-patch+yaml
.
Outre cette logique kubectl
devient accessible à tous via API, apply
côté serveur, garde une trace de qui est responsable des champs de la spécification, permettant ainsi un accès multiple sécurisé pour son édition sans conflit. Autrement dit, si apply
côté serveur deviendra plus répandu, une interface universelle sécurisée de gestion des ressources apparaîtra pour différents clients, par exemple kubectl, Pulumi ou Terraform, GitOps, ainsi que des scripts auto-écrits utilisant des bibliothèques clientes.
Les résultats de
J'espère que ce bref aperçu des différentes manières de mettre à jour les ressources dans les clusters vous a été utile. Il est bon de savoir qu'il ne s'agit pas simplement d'appliquer ou de remplacer ; il est possible de mettre à jour une ressource en utilisant Appliquer, Modifier, Corriger ou Remplacer. Après tout, en principe, chaque approche a son propre domaine d'application. Pour les modifications atomiques, le remplacement est préférable ; sinon, vous devez utiliser le correctif de fusion stratégique via appliquer. À tout le moins, j'attends de vous que vous compreniez que vous ne pouvez pas faire confiance à Google ou à StackOerflow lorsque vous recherchez "kubernetes apply vs replace". Au moins jusqu'à ce que cet article remplace la réponse actuelle.
Source: habr.com