Comparaison appropriée des applications, remplacements et correctifs de Kubernetes

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.

Comparaison appropriée des applications, remplacements et correctifs de Kubernetes

si recherche sur Google l'expression "kubernetes appliquer vs remplacer" se trouve répondre à StackOverflow, ce qui n'est pas correct. Lors de la recherche "kubernetes apply vs patch", le premier lien est la documentation pour 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 bibliothèque client pour l'API Kubernetes en utilisant un langage de programmation. La bibliothèque gère ces méthodes via des requêtes HTTP en utilisant les méthodes PUT и PATCH. Dans ce cas, update и replace utiliser PUTEt patch, aussi trivial soit-il, utilise PATCH.

Il convient de noter que kubectl fonctionne également avec des clusters via API. Autrement dit, kubectlest 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 sur le transfert logique 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 correctifs de fusion stratégique pour mettre à jour les ressources, bien que la commande 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 applyC'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 editEt 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 patchpour 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 : Patch de fusion JSON и Correctif JSON. L'approche des correctifs de fusion JSON prend en entrée une spécification Kubernetes partielle et prend en charge la fusion d'objets de la même manière que l'approche des correctifs de fusion stratégique. La différence entre les deux est qu'il ne prend en charge que le remplacement de tableau, y compris le tableau de conteneurs dans la spécification du pod. Cela signifie que lorsque vous utilisez un correctif de fusion JSON, vous devez fournir des spécifications complètes pour tous les conteneurs au cas où une propriété d'un conteneur changerait. Cette approche est donc utile pour supprimer des éléments d’un tableau dans une nomenclature. Sur la ligne de commande, vous pouvez sélectionner le correctif de fusion JSON en utilisant 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.

Comparaison appropriée des applications, remplacements et correctifs de Kubernetes

Source: habr.com

Ajouter un commentaire