{"id":35955,"date":"2019-10-31T22:08:26","date_gmt":"2019-10-31T19:08:26","guid":{"rendered":"https:\/\/prohoster.info\/blog\/razvertyvanie-prilozhenij-na-neskolkih-klasterah-kubernetes-s-helm\/"},"modified":"2019-10-31T22:08:26","modified_gmt":"2019-10-31T19:08:26","slug":"razvertyvanie-prilozhenij-na-neskolkih-klasterah-kubernetes-s-helm","status":"publish","type":"post","link":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/razvertyvanie-prilozhenij-na-neskolkih-klasterah-kubernetes-s-helm","title":{"rendered":"D\u00e9ploiement d'applications sur plusieurs clusters Kubernetes avec Helm","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<\/p>\n<p><\/p>\n<h2 id=\"kak-dailymotion-ispolzuet-kubernetes-razvertyvanie-prilozheniy\">Comment Dailymotion utilise Kubernetes : d\u00e9ploiement d'applications<\/h2>\n<p><\/p>\n<p>Chez Dailymotion, nous avons commenc\u00e9 \u00e0 utiliser Kubernetes en production il y a 3 ans. Cependant, d\u00e9ployer des applications sur plusieurs clusters peut \u00eatre un v\u00e9ritable d\u00e9fi, c'est pourquoi ces derni\u00e8res ann\u00e9es, nous avons cherch\u00e9 \u00e0 am\u00e9liorer nos outils et nos processus.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3 id=\"s-chego-nachalos\">Le d\u00e9but de tout<\/h3>\n<p><\/p>\n<p>Ici, nous expliquons comment nous d\u00e9ployons nos applications sur plusieurs clusters Kubernetes \u00e0 travers le monde.<\/p>\n<p><\/p>\n<p>Pour d\u00e9ployer plusieurs objets Kubernetes en m\u00eame temps, nous utilisons <noindex><a rel=\"nofollow\" href=\"https:\/\/helm.sh\/\">Helm<\/a><\/noindex>, et tous nos charts sont stock\u00e9s dans un seul d\u00e9p\u00f4t git. Pour d\u00e9ployer l'ensemble de la pile applicative compos\u00e9e de plusieurs services, nous utilisons ce que l'on appelle un chart aggr\u00e9gateur. En gros, c'est un chart qui d\u00e9clare les d\u00e9pendances et permet d'initialiser l'API et ses services en une seule commande.<\/p>\n<p><\/p>\n<p>Nous avons \u00e9galement \u00e9crit un petit script Python au-dessus de Helm pour effectuer des v\u00e9rifications, cr\u00e9er des charts, ajouter des secrets et d\u00e9ployer des applications. Toutes ces t\u00e2ches sont r\u00e9alis\u00e9es sur une plateforme CI centrale \u00e0 l'aide d'une image docker.<\/p>\n<p><\/p>\n<p>Passons aux choses s\u00e9rieuses.<\/p>\n<p><\/p>\n<blockquote><p>Note. Quand vous lisez ceci, la premi\u00e8re version candidate de Helm 3 a d\u00e9j\u00e0 \u00e9t\u00e9 annonc\u00e9e. La version principale contient un ensemble d'am\u00e9liorations visant \u00e0 r\u00e9soudre certains probl\u00e8mes auxquels nous avons \u00e9t\u00e9 confront\u00e9s dans le pass\u00e9.<\/p><\/blockquote>\n<p><\/p>\n<h3 id=\"rabochiy-process-razrabotki-chartov\">Workflow de d\u00e9veloppement des charts<\/h3>\n<p><\/p>\n<p>Pour les applications, nous utilisons la ramification, et nous avons d\u00e9cid\u00e9 d'appliquer cette m\u00eame approche aux charts.<\/p>\n<p><\/p>\n<ul>\n<li>La branche <strong>dev<\/strong> est utilis\u00e9e pour cr\u00e9er des charts qui seront test\u00e9s sur des clusters de d\u00e9veloppement.<\/li>\n<li>Lorsque la demande de tirage est soumise \u00e0 <strong>master<\/strong>, elle est v\u00e9rifi\u00e9e en staging.<\/li>\n<li>Enfin, nous cr\u00e9ons une demande de tirage pour transmettre les modifications \u00e0 la branche <strong>prod<\/strong> et les appliquer en production.<\/li>\n<\/ul>\n<p><\/p>\n<p>Chaque environnement a son propre d\u00e9p\u00f4t priv\u00e9 qui stocke nos charts, et nous utilisons <noindex><a rel=\"nofollow\" href=\"https:\/\/chartmuseum.com\/\">Chartmuseum<\/a><\/noindex> avec des API tr\u00e8s utiles. Ainsi, nous garantissons une stricte isolation entre les environnements et un test des charts dans des conditions r\u00e9elles avant de les utiliser en production.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/rz\/vt\/uk\/rzvtuk6q7b_rkeaxnyujzhmfjog.png\"><\/a><\/noindex><\/p>\n<p><\/p>\n<p><em>D\u00e9p\u00f4ts de charts dans diff\u00e9rents environnements<\/em><\/p>\n<p><\/p>\n<p>Il est \u00e0 noter que lorsque les d\u00e9veloppeurs envoient une branche dev, la version de leur chart est automatiquement envoy\u00e9e \u00e0 dev Chartmuseum. Ainsi, tous les d\u00e9veloppeurs utilisent un seul d\u00e9p\u00f4t dev et doivent pr\u00eater attention \u00e0 la version de leur chart pour ne pas utiliser accidentellement les modifications de quelqu'un d'autre.<\/p>\n<p><\/p>\n<p>De plus, notre petit script Python v\u00e9rifie les objets Kubernetes selon les sp\u00e9cifications de Kubernetes OpenAPI en utilisant <noindex><a rel=\"nofollow\" href=\"https:\/\/kubeval.instrumenta.dev\/\">Kubeval<\/a><\/noindex>, avant de les publier dans Chartmuseum.<\/p>\n<p><\/p>\n<h3 id=\"obschee-opisanie-rabochego-processa-razrabotki-charta\">Description g\u00e9n\u00e9rale du flux de travail de d\u00e9veloppement de chartes<\/h3>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/yd\/cw\/qw\/ydcwqw-vqfitu5bj8ky4nh7xxea.png\"><\/a><\/noindex><\/p>\n<p><\/p>\n<ol>\n<li>Configuration des t\u00e2ches de pipeline selon les sp\u00e9cifications <noindex><a rel=\"nofollow\" href=\"https:\/\/gazr.io\/\">gazr.io<\/a><\/noindex> pour le contr\u00f4le qualit\u00e9 (lint, test unitaire).<\/li>\n<li>Envoi de l'image docker avec des outils Python qui d\u00e9ploient nos applications.<\/li>\n<li>Configuration de l'environnement par nom de branche.<\/li>\n<li>V\u00e9rification des fichiers yaml Kubernetes avec Kubeval.<\/li>\n<li>Augmentation automatique de la version du chart et de ses charts parents (charts qui d\u00e9pendent du chart modifi\u00e9).<\/li>\n<li>Envoi du chart dans Chartmuseum, qui correspond \u00e0 son environnement<\/li>\n<\/ol>\n<p><\/p>\n<h2 id=\"upravlenie-razlichiyami-v-klasterah\">Gestion des diff\u00e9rences dans les clusters<\/h2>\n<p><\/p>\n<h3 id=\"federaciya-klasterov\">F\u00e9d\u00e9ration de clusters<\/h3>\n<p><\/p>\n<p>Il fut un temps o\u00f9 nous utilisions <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/cluster-administration\/federation\/\">la f\u00e9d\u00e9ration des clusters Kubernetes<\/a><\/noindex>, o\u00f9 il \u00e9tait possible de d\u00e9clarer des objets Kubernetes \u00e0 partir d'un seul point d'extr\u00e9mit\u00e9 API. Mais des probl\u00e8mes sont survenus. Par exemple, certains objets Kubernetes ne pouvaient pas \u00eatre cr\u00e9\u00e9s \u00e0 l'point d'extr\u00e9mit\u00e9 de f\u00e9d\u00e9ration, ce qui compliquait la gestion des objets agr\u00e9g\u00e9s et d'autres objets pour des clusters individuels.<\/p>\n<p><\/p>\n<p>Pour r\u00e9soudre le probl\u00e8me, nous avons commenc\u00e9 \u00e0 g\u00e9rer les clusters de mani\u00e8re ind\u00e9pendante, ce qui a consid\u00e9rablement simplifi\u00e9 le processus (nous avons utilis\u00e9 la premi\u00e8re version de la f\u00e9d\u00e9ration ; quelque chose a pu changer dans la deuxi\u00e8me version).<\/p>\n<p><\/p>\n<h3 id=\"georaspredelennaya-platforma\">Plateforme g\u00e9o-distribu\u00e9e<\/h3>\n<p><\/p>\n<p>Maintenant, notre plateforme est r\u00e9partie sur 6 r\u00e9gions \u2014 3 localement et 3 dans le cloud.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/jq\/c1\/mr\/jqc1mru36g5byams4wddzducauw.png\"><\/a><\/noindex><br \/>\n<em>D\u00e9ploiement distribu\u00e9<\/em><\/p>\n<p><\/p>\n<h3 id=\"globalnye-znacheniya-helm\">Valeurs globales Helm<\/h3>\n<p><\/p>\n<p>4 valeurs globales Helm permettent de d\u00e9finir les diff\u00e9rences entre les clusters. Pour tous nos charts, il existe des valeurs minimales par d\u00e9faut.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">global:\n  cloud: True\n  env: staging\n  region: us-central1\n  clusterName: staging-us-central1<\/code><\/pre>\n<p><\/p>\n<p><em>Valeurs globales<\/em><\/p>\n<p><\/p>\n<p>Ces valeurs aident \u00e0 d\u00e9finir le contexte de nos applications et sont utilis\u00e9es pour diff\u00e9rentes t\u00e2ches : surveillance, tra\u00e7age, journalisation, appels externes, mise \u00e0 l'\u00e9chelle, etc.<\/p>\n<p><\/p>\n<ul>\n<li>\"cloud\": nous avons une plateforme Kubernetes hybride. Par exemple, notre API est d\u00e9ploy\u00e9e dans des zones GCP et dans nos centres de donn\u00e9es.<\/li>\n<li>\"env\": certaines valeurs peuvent changer pour les environnements non op\u00e9rationnels. Par exemple, les d\u00e9finitions de ressources et la configuration de l'autoscaling.<\/li>\n<li>\"region\": cette information aide \u00e0 d\u00e9terminer l'emplacement du cluster et peut \u00eatre utilis\u00e9e pour d\u00e9finir les points d'extr\u00e9mit\u00e9 les plus proches pour les services externes.<\/li>\n<li>\"clusterName\": si et quand nous voulons d\u00e9finir une valeur pour un cluster sp\u00e9cifique.<\/li>\n<\/ul>\n<p><\/p>\n<p>Voici un exemple concret :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">{{\n\/* Retourne le nombre de r\u00e9plicas du Horizontal Pod Autoscaler pour GraphQL *\/}}\n{{- define \"graphql.hpaReplicas\" -}}\n{{- if eq .Values.global.env \"prod\" }}\n{{- if eq .Values.global.region \"europe-west1\" }}\nminReplicas: 40\n{{- else }}\nminReplicas: 150\n{{- end }}\nmaxReplicas: 1400\n{{- else }}\nminReplicas: 4\nmaxReplicas: 20\n{{- end }}\n{{- end -}}<\/code><\/pre>\n<p><\/p>\n<p><em>Exemple de mod\u00e8le Helm<\/em><\/p>\n<p><\/p>\n<p>Cette logique est d\u00e9finie dans un mod\u00e8le auxiliaire afin de ne pas encombrer le YAML de Kubernetes.<\/p>\n<p><\/p>\n<h3 id=\"obyavlenie-prilozheniya\">D\u00e9claration de l'application<\/h3>\n<p><\/p>\n<p>Nos outils de d\u00e9ploiement reposent sur plusieurs fichiers YAML. Voici un exemple de la fa\u00e7on dont nous d\u00e9clarons le service et sa topologie de mise \u00e0 l'\u00e9chelle (nombre de r\u00e9plicas) dans le cluster.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">releases:\n  - foo.world\n\nfoo.world:                # Nom de la version\n  services:               # Liste des applications\/projets de dailymotion\n    foobar:\n      chart_name: foo-foobar\n      repo: git@github.com:dailymotion\/foobar\n      contexts:\n        prod-europe-west1:\n          deployments:\n            - name: foo-bar-baz\n              replicas: 18\n            - name: another-deployment\n              replicas: 3<\/code><\/pre>\n<p><\/p>\n<p><em>D\u00e9finition du service<\/em><\/p>\n<p><\/p>\n<p>C'est le sch\u00e9ma de toutes les \u00e9tapes qui d\u00e9finissent notre flux de travail de d\u00e9ploiement. La derni\u00e8re \u00e9tape d\u00e9ploie l'application simultan\u00e9ment sur plusieurs clusters de travail.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/iu\/qh\/xk\/iuqhxki4nfqoi0mus258j0feylu.png\"><\/a><\/noindex><br \/>\n<em>\u00c9tapes de d\u00e9ploiement dans Jenkins<\/em><\/p>\n<p><\/p>\n<h3 id=\"a-sekrety\">Et les secrets ?<\/h3>\n<p><\/p>\n<p>En ce qui concerne la s\u00e9curit\u00e9, nous suivons tous les secrets provenant de diff\u00e9rents endroits et les stockons dans un d\u00e9p\u00f4t unique <noindex><a rel=\"nofollow\" href=\"https:\/\/www.vaultproject.io\/\">Vault<\/a><\/noindex> \u00e0 Paris.<\/p>\n<p><\/p>\n<p>Nos outils de d\u00e9ploiement extraient les valeurs des secrets \u00e0 partir de Vault et, lorsque vient le temps de d\u00e9ployer, les ins\u00e8rent dans Helm.<\/p>\n<p><\/p>\n<p>Pour cela, nous avons d\u00e9fini une correspondance entre les secrets dans Vault et les secrets dont nos applications ont besoin :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">secrets:                                                                                                                                                                                                        \n     - secret_id: \"stack1-app1-password\"                                                                                                                                                                                  \n       contexts:                                                                                                                                                                                                   \n         - name: \"default\"                                                                                                                                                                                         \n           vaultPath: \"\\\/kv\\\/dev\\\/stack1\\\/app1\\\/test\"                                                                                                                                                               \n           vaultKey: \"password\"                                                                                                                                                                                    \n         - name: \"cluster1\"                                                                                                                                                                           \n           vaultPath: \"\\\/kv\\\/dev\\\/stack1\\\/app1\\\/test\"                                                                                                                                                               \n           vaultKey: \"password\"<\/code><\/pre>\n<p><\/p>\n<ul>\n<li>Nous avons d\u00e9fini des r\u00e8gles g\u00e9n\u00e9rales \u00e0 suivre lors de l'enregistrement des secrets dans Vault.<\/li>\n<li>Si un secret se rapporte <strong>\u00e0 un contexte ou un cluster sp\u00e9cifique<\/strong>, il est n\u00e9cessaire d'ajouter une entr\u00e9e sp\u00e9cifique. (Ici, le contexte cluster1 a sa propre valeur pour le secret stack-app1-password).<\/li>\n<li>Dans le cas contraire, la valeur par d\u00e9faut est utilis\u00e9e <strong>par d\u00e9faut<\/strong>.<\/li>\n<li>Pour chaque \u00e9l\u00e9ment de cette liste, un <strong>secret Kubernetes<\/strong> est ins\u00e9r\u00e9 avec une paire cl\u00e9-valeur. C'est pourquoi le mod\u00e8le de secret dans nos charts est tr\u00e8s simple.<\/li>\n<\/ul>\n<p><\/p>\n<pre><code class=\"plaintext\">apiVersion: v1\ndata:\n{{- range $key,$value := .Values.secrets }}\n  {{ $key }}: {{ $value | b64enc | quote }}\n{{ end }}\nkind: Secret\nmetadata:\n  name: \"{{ .Chart.Name }}\"\n  labels:\n    chartVersion: \"{{ .Chart.Version }}\"\n    tillerVersion: \"{{ .Capabilities.TillerVersion.SemVer }}\"\ntype: Opaque<\/code><\/pre>\n<p><\/p>\n<h2 id=\"problemy-i-ogranicheniya\">Probl\u00e8mes et limitations<\/h2>\n<p><\/p>\n<h3 id=\"rabota-s-neskolkimi-repozitoriyami\">Travail avec plusieurs d\u00e9p\u00f4ts<\/h3>\n<p><\/p>\n<p>Actuellement, nous s\u00e9parons le d\u00e9veloppement des charts et des applications. Cela signifie que les d\u00e9veloppeurs doivent travailler dans deux d\u00e9p\u00f4ts git : un pour l'application et un autre pour d\u00e9finir son d\u00e9ploiement dans Kubernetes. 2 d\u00e9p\u00f4ts git signifient 2 flux de travail, et un nouveau peut facilement se perdre.<\/p>\n<p><\/p>\n<h3 id=\"upravlyat-obobschennymi-chartami-hlopotno\">G\u00e9rer des charts g\u00e9n\u00e9riques est p\u00e9nible<\/h3>\n<p><\/p>\n<p>Comme nous l'avons d\u00e9j\u00e0 dit, les charts g\u00e9n\u00e9riques sont tr\u00e8s pratiques pour d\u00e9finir les d\u00e9pendances et d\u00e9ployer rapidement plusieurs applications. Mais nous utilisons <code>--reuse-values<\/code>, pour \u00e9viter de transf\u00e9rer toutes les valeurs \u00e0 chaque fois que nous d\u00e9ployons une application faisant partie de ce chart g\u00e9n\u00e9rique.<\/p>\n<p><\/p>\n<p>Dans le processus de livraison continue, nous n\u2019avons que deux valeurs qui changent r\u00e9guli\u00e8rement : le nombre de r\u00e9pliques et l'\u00e9tiquette de l'image (version). D'autres valeurs, plus stables, sont modifi\u00e9es manuellement, et cela est assez compliqu\u00e9. De plus, une erreur dans le d\u00e9ploiement d\u2019un chart g\u00e9n\u00e9ralis\u00e9 peut entra\u00eener de graves pannes, comme nous l'avons constat\u00e9 par exp\u00e9rience.<\/p>\n<p><\/p>\n<h3 id=\"obnovlenie-neskolkih-faylov-konfiguracii\">Mise \u00e0 jour de plusieurs fichiers de configuration<\/h3>\n<p><\/p>\n<p>Lorsqu'un d\u00e9veloppeur ajoute une nouvelle application, il doit modifier plusieurs fichiers : la d\u00e9claration de l'application, la liste des secrets, l'ajout de l'application en tant que d\u00e9pendance si elle est incluse dans le chart g\u00e9n\u00e9ralis\u00e9.<\/p>\n<p><\/p>\n<h3 id=\"razresheniya-jenkins-slishkom-rasshireny-v-vault\">Les autorisations Jenkins sont trop \u00e9tendues dans Vault<\/h3>\n<p><\/p>\n<p>Nous avons actuellement un <noindex><a rel=\"nofollow\" href=\"https:\/\/www.vaultproject.io\/docs\/auth\/approle.html\">AppRole<\/a><\/noindex>, qui lit tous les secrets de Vault.<\/p>\n<p><\/p>\n<h3 id=\"process-otkata-ne-avtomatizirovan\">Le processus de rollback n'est pas automatis\u00e9<\/h3>\n<p><\/p>\n<p>Pour le rollback, il faut ex\u00e9cuter une commande sur plusieurs clusters, ce qui est sujet aux erreurs. Nous effectuons cette op\u00e9ration manuellement pour garantir que le bon identifiant de version est sp\u00e9cifi\u00e9.<\/p>\n<p><\/p>\n<h2 id=\"my-dvizhemsya-v-storonu-gitops\">Nous nous orientons vers GitOps<\/h2>\n<p><\/p>\n<h3 id=\"nasha-cel\">Notre objectif<\/h3>\n<p><\/p>\n<p>Nous souhaitons ramener le chart dans le d\u00e9p\u00f4t de l'application qu'il d\u00e9ploie.<\/p>\n<p><\/p>\n<p>Le processus de travail sera le m\u00eame que pour le d\u00e9veloppement. Par exemple, lorsque la branche est envoy\u00e9e vers la master, le d\u00e9ploiement se d\u00e9clenchera automatiquement. La principale diff\u00e9rence entre cette approche et le processus de travail actuel est que <strong>tout sera g\u00e9r\u00e9 dans git<\/strong> (l'application elle-m\u00eame et la mani\u00e8re dont elle est d\u00e9ploy\u00e9e dans Kubernetes).<\/p>\n<p><\/p>\n<p>Il y a plusieurs avantages :<\/p>\n<p><\/p>\n<ul>\n<li>C'est beaucoup <strong>plus clair<\/strong> pour le d\u00e9veloppeur. Il est plus facile d'apprendre \u00e0 appliquer des modifications dans le chart local.<\/li>\n<li>La d\u00e9finition du d\u00e9ploiement du service peut \u00eatre indiqu\u00e9e <strong>au m\u00eame endroit que le code<\/strong> du service.<\/li>\n<li><strong>Gestion de la suppression des charts g\u00e9n\u00e9ralis\u00e9s<\/strong>. Le service aura sa propre version Helm. Cela permettra de g\u00e9rer le cycle de vie de l'application (rollback, mise \u00e0 jour) \u00e0 un niveau tr\u00e8s fin, sans affecter les autres services.<\/li>\n<li><strong>Les avantages de git<\/strong> pour la gestion des charts : annulation des modifications, journal d'audit, etc. Si un changement de chart doit \u00eatre annul\u00e9, cela peut \u00eatre fait \u00e0 l'aide de git. Le d\u00e9ploiement se d\u00e9clenche automatiquement.<\/li>\n<li>On peut envisager d'am\u00e9liorer le processus de d\u00e9veloppement avec des outils comme <strong>Skaffold<\/strong>, avec lesquels les d\u00e9veloppeurs peuvent tester des modifications dans un contexte proche de la production.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"dvuhetapnaya-migraciya\">Migration en deux \u00e9tapes<\/h3>\n<p><\/p>\n<p>Nos d\u00e9veloppeurs utilisent ce workflow depuis 2 ans, donc nous avons besoin d'une migration aussi fluide que possible. C'est pourquoi nous avons d\u00e9cid\u00e9 d'ajouter une \u00e9tape interm\u00e9diaire vers notre objectif.<br \/>\nLa premi\u00e8re \u00e9tape est simple :<\/p>\n<p><\/p>\n<ul>\n<li>Nous conservons une structure similaire pour la configuration du d\u00e9ploiement des applications, mais dans un seul objet nomm\u00e9 DailymotionRelease.<\/li>\n<\/ul>\n<p><\/p>\n<pre><code class=\"plaintext\">apiVersion: \"v1\"\nkind: \"DailymotionRelease\"\nmetadata:\n  name: \"app1.ns1\"\n  environment: \"dev\"\n  branch: \"mybranch\"\nspec:\n  slack_channel: \"#admin\"\n  chart_name: \"app1\"\n  scaling:\n    - context: \"dev-us-central1-0\"\n      replicas:\n        - name: \"hermes\"\n          count: 2\n    - context: \"dev-europe-west1-0\"\n      replicas:\n        - name: \"app1-deploy\"\n          count: 2\n  secrets:\n    - secret_id: \"app1\"\n      contexts:\n        - name: \"default\"\n          vaultPath: \"\\\/kv\\\/dev\\\/ns1\\\/app1\\\/test\"\n          vaultKey: \"password\"\n        - name: \"dev-europe-west1-0\"\n          vaultPath: \"\\\/kv\\\/dev\\\/ns1\\\/app1\\\/test\"\n          vaultKey: \"password\"<\/code><\/pre>\n<p><\/p>\n<ul>\n<li>1 release par application (sans charts g\u00e9n\u00e9ralis\u00e9s).<\/li>\n<li>Charts dans le r\u00e9f\u00e9rentiel git de l'application.<\/li>\n<\/ul>\n<p><\/p>\n<p>Nous avons parl\u00e9 \u00e0 tous les d\u00e9veloppeurs, donc le processus de migration a d\u00e9j\u00e0 commenc\u00e9. La premi\u00e8re \u00e9tape est toujours contr\u00f4l\u00e9e \u00e0 l'aide de la plateforme CI. Je publierai bient\u00f4t un autre article sur la deuxi\u00e8me \u00e9tape : comment nous avons \u00e9volu\u00e9 vers un workflow GitOps avec <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/weaveworks\/flux\">Flux<\/a><\/noindex>. Je parlerai de la fa\u00e7on dont nous avons tout configur\u00e9 et des difficult\u00e9s que nous avons rencontr\u00e9es (plusieurs d\u00e9p\u00f4ts, secrets, etc.). Restez \u00e0 l'\u00e9coute.<\/p>\n<p><\/p>\n<p>Ici, nous avons tent\u00e9 de d\u00e9crire nos progr\u00e8s dans le workflow de d\u00e9ploiement des applications au cours des derni\u00e8res ann\u00e9es, ce qui nous a amen\u00e9 \u00e0 r\u00e9fl\u00e9chir \u00e0 l'approche GitOps. Nous n'avons pas encore atteint notre objectif et nous rendrons compte des r\u00e9sultats, mais nous sommes convaincus qu'il \u00e9tait juste d'avoir simplifi\u00e9 les choses et de les rapprocher des habitudes des d\u00e9veloppeurs.<\/p>\n<p>Source : <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/458934\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041a\u0430\u043a Dailymotion \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 Kubernetes: \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u041c\u044b \u0432 Dailymotion \u043d\u0430\u0447\u0430\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Kubernetes \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435 3 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434. \u041d\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430\u0445 \u0442\u043e \u0435\u0449\u0435 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043b\u0435\u0442 \u043c\u044b \u0441\u0442\u0430\u0440\u0430\u043b\u0438\u0441\u044c \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043d\u0430\u0448\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0440\u0430\u0431\u043e\u0447\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b. \u0421 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u043c, \u043a\u0430\u043a \u043c\u044b \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0448\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430\u0445 Kubernetes \u043f\u043e [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-35955","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041a\u0430\u043a Dailymotion \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 Kubernetes: \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u041c\u044b \u0432 Dailymotion \u043d\u0430\u0447\u0430\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Kubernetes \u0432.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/razvertyvanie-prilozhenij-na-neskolkih-klasterah-kubernetes-s-helm\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0420\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430\u0445 Kubernetes \u0441 Helm | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041a\u0430\u043a Dailymotion \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 Kubernetes: \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u041c\u044b \u0432 Dailymotion \u043d\u0430\u0447\u0430\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Kubernetes \u0432.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/razvertyvanie-prilozhenij-na-neskolkih-klasterah-kubernetes-s-helm\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:08:26+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:08:26+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47D\u00e9ploiement d'applications sur plusieurs clusters Kubernetes avec Helm | ProHoster","description":"Comment Dailymotion utilise Kubernetes : d\u00e9ploiement d'applications Nous chez Dailymotion avons commenc\u00e9 \u00e0 utiliser Kubernetes en.","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/razvertyvanie-prilozhenij-na-neskolkih-klasterah-kubernetes-s-helm","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0420\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430\u0445 Kubernetes \u0441 Helm | ProHoster","og:description":"\u041a\u0430\u043a Dailymotion \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 Kubernetes: \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u041c\u044b \u0432 Dailymotion \u043d\u0430\u0447\u0430\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Kubernetes \u0432.","og:url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/razvertyvanie-prilozhenij-na-neskolkih-klasterah-kubernetes-s-helm","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:08:26+00:00","article:modified_time":"2019-10-31T19:08:26+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"35955","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 01:25:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:53:31","updated":"2026-01-22 01:25:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/35955","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=35955"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/35955\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=35955"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=35955"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=35955"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}