
— notre utilitaire GitOps CLI open source pour la construction et la livraison d'applications dans Kubernetes. Dans , une nouvelle fonctionnalité a été introduite dans l'assembleur d'images : le taggage d'images basé sur le contenu ou content-based tagging. Jusqu'à présent, le schéma de taggage typique dans werf supposait le taggage des images Docker par le tag Git, la branche Git ou le commit Git. Mais chacun de ces schémas présente des inconvénients qui sont entièrement résolus par la nouvelle stratégie de taggage. Les détails à ce sujet et ce qui la rend si bonne — ci-dessous.
Déploiement d'un ensemble de microservices depuis un seul dépôt Git
Il est courant que les applications soient divisées en plusieurs services, plus ou moins indépendants. Les releases de ces services peuvent se faire indépendamment : un ou plusieurs services peuvent être publiés en même temps, tandis que les autres doivent continuer à fonctionner sans aucune modification. Cependant, en ce qui concerne le stockage du code et la gestion des projets, il est plus pratique de garder ces services d'application dans un seul dépôt.
Il y a des cas où les services sont réellement indépendants et ne sont pas liés à une seule application. Dans ce cas, ils seront situés dans des projets distincts et leur publication se fera par des processus CI/CD séparés dans chacun des projets.
Cependant, dans la réalité, les développeurs segmentent souvent une application unique en plusieurs microservices, mais créer un dépôt et un projet distinct pour chacun… — est clairement excessif. C'est précisément cette situation qui sera abordée ici : plusieurs de ces microservices résident dans un dépôt unique du projet et les releases se font à travers un seul processus dans le CI/CD.
Taggage par branche Git et tag Git
Supposons que la stratégie de taggage la plus courante soit tag-or-branch. Pour les branches Git, les images sont taggées avec le nom de la branche, pour une branche donnée, il n'existe à un moment donné qu'une seule image publiée au nom de cette branche. Pour les tags Git, les images sont taggées respectivement avec le nom du tag.
Lorsqu'un nouveau tag Git est créé — par exemple, lors de la sortie d'une nouvelle version — un nouveau tag Docker sera créé pour toutes les images du projet dans le registre Docker :
-
myregistry.org/myproject/frontend:v1.1.10 -
myregistry.org/myproject/myservice1:v1.1.10 -
myregistry.org/myproject/myservice2:v1.1.10 -
myregistry.org/myproject/myservice3:v1.1.10 -
myregistry.org/myproject/myservice4:v1.1.10 -
myregistry.org/myproject/myservice5:v1.1.10 -
myregistry.org/myproject/database:v1.1.10
Ces nouveaux noms d'image passent par des modèles Helm dans la configuration Kubernetes. Lors du lancement du déploiement avec la commande werf deploy la mise à jour du champ image dans les manifestes des ressources Kubernetes et le redémarrage des ressources correspondantes en raison du changement de nom de l'image.
Le problème: dans le cas où le contenu de l'image n'a pas réellement changé depuis le dernier déploiement (tag Git), mais seulement son tag Docker, il se produit un redémarrage inutiles de cette application et, par conséquent, il peut y avoir quelques interruptions. Bien qu'il n'y ait eu aucune raison réelle de procéder à ce redémarrage.
En conséquence, avec le schéma de tagging actuel, il est nécessaire de gérer plusieurs dépôts Git distincts, ce qui pose le problème de l'organisation du déploiement de ces plusieurs dépôts. Dans l'ensemble, ce schéma devient encombré et complexe. Il est préférable de regrouper plusieurs services dans un seul dépôt et de créer des tags Docker de sorte qu'il n'y ait pas de redémarrages inutiles.
Tagging par commit Git
Il existe également une stratégie de tagging dans werf liée aux commits Git.
Un commit Git est un identifiant du contenu dans le dépôt Git et dépend de l'historique des modifications des fichiers dans le dépôt Git, il semble donc logique de l'utiliser pour taguer les images dans le Docker Registry.
Cependant, le tagging par commit Git présente les mêmes inconvénients que le tagging par branches Git ou par tags Git :
- Un commit vide pourrait avoir été créé, sans modifier les fichiers, mais le tag Docker de l'image sera modifié.
- Un commit de fusion pourrait avoir été créé, sans modifier les fichiers, mais le tag Docker de l'image sera modifié.
- Un commit pourrait avoir été créé, modifiant des fichiers dans Git qui ne sont pas inclus dans l'image, et le tag Docker de l'image sera encore modifié.
Le tagging par nom de branche Git ne reflète pas la version de l'image.
Il y a aussi un autre problème lié à la stratégie de tagging par branches Git.
Le tagging par nom de branche fonctionne tant que les commits de cette branche sont récupérés successivement dans l'ordre chronologique.
Si, dans le schéma actuel, un utilisateur lance une reconstruction d'un ancien commit lié à une certaine branche, werf écrasera l'image par le tag Docker correspondant avec la nouvelle version de l'image pour cet ancien commit. Les déploiements utilisant ce tag risquent, lors du redémarrage des pods, de tirer une autre version de l'image, ce qui entraînera la perte de connexion de notre application avec le système CI, menant à une désynchronisation.
De plus, lors de push successifs dans une branche avec un court intervalle de temps entre eux, un ancien commit peut être reconstruit après un plus récent : l'ancienne version de l'image écrasera la nouvelle par le tag de la branche Git. Ces problèmes peuvent être gérés par un système CI/CD (par exemple, dans GitLab CI, un pipeline est lancé pour une série de commits). Cependant, toutes les systèmes ne le prennent pas en charge et il devrait y avoir un moyen plus fiable de prévenir un problème aussi fondamental.
Qu'est-ce que le tagging basé sur le contenu ?
Ainsi, qu'est-ce que le tagging basé sur le contenu — le tagging des images par leur contenu.
Pour créer des tags Docker, on n'utilise pas les primitives de Git (branche Git, tag Git…), mais une somme de contrôle associée à :
- le contenu de l'image. L'identifiant-tag de l'image reflète son contenu. Lors de la construction d'une nouvelle version, cet identifiant ne changera pas si les fichiers de l'image n'ont pas été modifiés ;
- l'historique de création de cette image dans Git. Les images liées à différentes branches Git et à différents historiques de construction via werf auront des identifiants-tags différents.
En tant que tel, l'identifiant-tag est ce que l'on appelle une signature des étapes de l'image.
Chaque image est composée d'un ensemble d'étapes : from, before-install, git-archive, install, imports-after-install, before-setup,… git-latest-patch etc. Chaque étape a un identifiant qui reflète son contenu — signature de l'étape (signature de l'étape).
L'image finale, composée de ces étapes, est taguée par ce qu'on appelle la signature de l'ensemble de ces étapes — signature des étapes, — qui est généralisante pour toutes les étapes de l'image.
Chaque image de la configuration werf.yaml a en général sa propre signature, et donc, son tag Docker.
La signature des étapes résout tous les problèmes énoncés :
- Elle est résistante aux commits Git vides.
- Elle est résistante aux commits Git qui modifient des fichiers n'étant pas pertinents pour l'image.
- Elle ne provoque pas de problème d'écrasement de la version actuelle de l'image lors du redémarrage des construits pour d'anciens commits Git de la branche.
C'est maintenant la stratégie de tagging recommandée et utilisée par défaut dans werf pour tous les systèmes CI.
Comment l'activer et l'utiliser dans werf
L'option correspondante est apparue pour la commande werf publish: --tag-by-stages-signature=true|false
Dans le système CI, la stratégie de tagging est définie par la commande werf ci-env. Auparavant, pour cela, un paramètre était défini werf ci-env --tagging-strategy=tag-or-branch. Maintenant, si vous indiquez werf ci-env --tagging-strategy=stages-signature ou si vous ne spécifiez pas cette option, werf utilisera par défaut la stratégie de tagging stages-signature. La commande werf ci-env ajoutera automatiquement les bonnes options pour la commande werf build-and-publish ou werf publish), donc aucune option supplémentaire pour ces commandes n'est nécessaire.
Par exemple, la commande :
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature… peut créer les images suivantes :
-
registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d -
registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6
Ici 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d — c'est la signature de la phase de l'image backend, et f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 — signature de la phase de l'image frontend.
Lors de l'utilisation de fonctionnalités spéciales werf_container_image et werf_container_env dans les modèles Helm, rien n'a besoin d'être changé : ces fonctions généreront automatiquement les bons noms d'images.
Exemple de configuration dans le système CI :
type multiwerf && source <(multiwerf use 1.1 beta)
type werf && source <(werf ci-env gitlab)
werf build-and-publish|deployPlus d'informations sur la configuration sont disponibles dans la documentation :
- ;
- ;
- .
Au total
- Une nouvelle option
werf publish --tag-by-stages-signature=true|false. - Nouvelle valeur de l'option
werf ci-env --tagging-strategy=stages-signature|tag-or-branch(si non spécifié, alors par défaut ça serastages-signature). - Si auparavant des options de tagging basées sur les commits Git étaient utilisées (
WERF_TAG_GIT_COMMITou optionwerf publish --tag-git-commit COMMIT), il est impératif de passer à la stratégie de tagging stages-signature. - Il est préférable de passer immédiatement les nouveaux projets à ce nouveau schéma de tagging.
- Pour les anciens projets convertis vers werf 1.1, il est conseillé de passer au nouveau schéma de tagging, mais l'ancien tag-or-branch est toujours pris en charge.
Le tagging basé sur le contenu résout tous les problèmes abordés dans l'article :
- La résistance du nom du tag Docker aux commits Git vides.
- La résistance du nom du tag Docker aux commits Git qui modifient des fichiers non pertinents pour l'image.
- Ne provoque pas de problème avec l'écrasement de la version actuelle de l'image lors du redémarrage des builds pour d'anciens commits Git sur des branches Git.
Profitez-en ! Et n'oubliez pas de passer chez nous sur , pour créer une issue ou trouver déjà existante, mettre un like, créer une PR ou simplement observer l'évolution du projet.
P.S.
Lisez aussi dans notre blog :
- «»
- «»
- «»;
- Utilisation de werf pour le déploiement de charts Helm complexes
- «»;
- «»;
- «»;
- «».
Source : habr.com
