Comment structurer le code et les configurations liés à DevOps dans un référentiel de code?


10

Nous avons grandi en tant qu'entreprise, nos produits se développent et nos activités et efforts liés à DevOps se développent également - nous sommes passés de Bamboo à un Jenkins plus flexible et configurable, en utilisant des pipelines de déploiement et d'autres plugins; passé à Ansible et commencer à utiliser Docker ici et là en interne.

Toutes ces choses nécessitent un certain niveau de codage ou de configuration: scripts et configurations Ansible, scripts groovy Jenkins, Dockerfiles et configurations YAML.

Pour l' instant, nous avons créé un dépôt séparé « ops » avec des répertoires de haut niveau pour jenkins, ansible, dockeret other( ce qui est un nom terrible, mais pour l' instant tous les « autres » choses d'automatisation de DevOps sont là).

Notre approche ne semble pas correcte et peut ne pas évoluer, mais quelles sont les meilleures pratiques et recommandations pour conserver le code lié à DevOps dans un référentiel de code ou des référentiels?


6
Je vais avec la méthode "chaque partie est une application, un repo par application", en chef cela signifie 1 repo par livre de cuisine.
Tensibai

@Tensibai à droite, j'avais peur qu'un seul repo "ops" devienne rapidement impraticable. Merci.
alecxe

1
Cela a été la forme héritée de la gestion des livres de cuisine dans le chef, 1 repo avec tous les livres de cuisine et a prouvé une arme de poing dans la plupart des cas, d'où le changement, mais je suis moins à l'aise avec ansible pour dire qu'il conviendrait également, Jenkins pipelines (si v2) et les fichiers docker devraient vivre avec le projet qu'ils gèrent IMO, et je n'ai aucune idée de ce que vous mettez sous d'autres donc je ne peux pas vraiment donner de conseils ici
Tensibai

@Tensibai l'a compris! L'autre se compose principalement d'utilitaires bash et python ou de scripts exécutés périodiquement pour plusieurs outils internes .. ils ne correspondent pas vraiment n'importe où et nous ne pouvions pas penser à un meilleur endroit que "autre" .. Je vais voir si je peux poster le contenu des répertoires dans la question aussi. Merci.
alecxe

1
Je les diviserais en plusieurs repo par `` affinité '' de travail, les scripts travaillant ensemble sur l'application X, vous pouvez avoir un script utilisé sur deux applications, mais si l'application A change d'une manière, le script doit gérer l'application à laquelle il parle , il est préférable d'avoir deux versions séparées, donc ATEOTD je les stocke avec l'application à laquelle elles se rapportent ou si elles s'étendent sur plusieurs applications dans un référentiel spécifique par tâche, vous avez donc toujours une version en ligne avec les applications déployées et vous ne pas besoin de baliser un script non lié en même temps.
Tensibai

Réponses:


3

L'organisation actuelle du code et de la configuration que vous décrivez est structurée par les solutions techniques impliquées. C'est une mauvaise conception qui ajoutera beaucoup de frais généraux dans nos activités de maintenance et ajoutera également beaucoup de pièges sur notre chemin. Au lieu de cela, cette organisation devrait être structurée autour des artefacts que nous déployons.

La raison en est que nous voulons considérer les artefacts ( par exemple une image docker ou un progiciel) comme les objets des verbes suivants:

  • construire
  • tester
  • déployer

pour considérer un ensemble minimal de tâches automatisées que nous voulons effectuer. Si nous voulons changer quelque chose sur la façon dont le verbe de test est implémenté, il est facile de visiter le dossier correspondant à cet artefact dans le référentiel approprié, puis de découvrir les éléments d'automatisation spécifiques à jenkins qui doivent être mis à jour. Au lieu de cela, si les recettes d'automatisation sont structurées autour de solutions techniques, nous devons comprendre à l'improviste que jenkins est impliqué dans les procédures de test et y trouver les éléments d'automatisation liés à l'artefact. Dans des situations complexes, l'organisation autour des solutions techniques rend les mises à jour très difficiles, car nous devons connaître a priori toutes les solutions techniques impliquées dans certains services pour les mettre à jour en conséquence.

Par exemple, un référentiel contenant le code d'un site Web et un micro-service «a» pourrait avoir les sous-répertoires suivants dédiés aux opérations:

./ops/website
./ops/micro-service-a

chacun ayant trois scripts appelés build, testet deploy. Maintenant que l'organisation des éléments d'automatisation a été clarifiée, tournons notre attention vers la configuration.

Les principales conditions et exigences relatives à l'organisation de la configuration sont définies par le deployverbe lorsqu'il est appliqué sur un artefact de type service. Le deployverbe doit avoir les paramètres suivants:

  • la version de l'artefact à déployer,
  • la cible de déploiement de l'artefact, qui décrit l'environnement concret dans lequel l'artefact déployé s'exécutera ( par exemple, un cluster et des points de terminaison avec lesquels il devrait parler)
  • les informations d'identification qu'il doit utiliser pour se connecter à d'autres points de terminaison ( par exemple, des bases de données)
  • la configuration d'exécution de (comme la durée de vie des entrées de cache, etc.)

Du point de vue opérationnel, cette ventilation de la paramétrisation correspond aux degrés de liberté naturels du problème de déploiement - en dehors des informations d'identification qui pourraient être regroupées avec la configuration d'exécution, mais il est préférable de les séparer pour éviter de les diffuser négligemment.


5

Je peux répondre à Docker, l'une des meilleures pratiques pour utiliser Docker est de conserver le fichier Docker et les fichiers de composition dans le même référentiel du projet, donc où que vous cloniez le projet, vous pouvez créer l'image Docker, et il est bon de conserver plusieurs versions de docker composer des fichiers par exemple (prod, staging, dev) afin que vous puissiez créer l'image et exécuter le conteneur avec une option spécifique pour chaque env, par exemple pour une machine de développement, vous pouvez utiliser un réseau spécifique et exécuter plus de conteneurs de dépendances ou autre.


4

Le code de chaque outil va dans son propre référentiel. par exemple

  1. Modèle Jenkins Groovy dans un repo Jenkins
  2. Playbooks Ansible YAML dans son propre référentiel (avec les rôles, les tâches, les sous-répertoires d'inventaire
  3. Modèles Cloudformation / Terrform dans son propre référentiel
  4. Fichiers Docker dans son propre 5 .. Et ainsi de suite

Cela vous aiderait à mieux évoluer en termes d'orchestration des processus et à maintenir diverses branches pour chaque environnement

Cela vous donnerait un contrôle plus granulaire et déchargerait tous vos frais de gestion des versions vers les systèmes de contrôle de version. Créez également des branches distinctes pour chaque environnement et étiquetez le code pour chaque version de production (comme nous le faisons pour la base de code d'application). Pensez Infra et traitez en termes de code. (Tout changement de processus doit être codifié et envoyé à QA, SIT, UAT puis à PROD) similaire à l'application.

Par exemple, vous pouvez avoir la version 2.1 d'Ansible exécutée dans Production (branche principale) mais la version 2.0 des conteneurs de docker fonctionnant dans Prod (branche principale)

De même, conservez vos scripts DB / scripts bash dans leurs propres référentiels et peut-être pouvez-vous avoir un fichier de contrôle de santé (JSON / YAML) configuré pour afficher les versions de tous les outils / pièces dans chaque URL déployée à des fins de suivi et d'automatisation. (Pour que vos webhooks lisent l'URL et automatisent les déploiements)


2
Le piège de cette approche est que la v2.1 est en qa et non validée et que vous devez patcher la production de toute urgence, vous ne pouvez pas modifier la v2.0 et si vous créez une v2.2 pour ce patch, il y a un risque élevé qu'elle soit perdu ou écrasé lors de la mise en production de la v2.1, multipliez par la quantité de code séparé dans un dépôt et vous avez bientôt un cauchemar de rétroportages (cela fonctionne, mais j'ai dû ajouter cet avertissement :))
Tensibai

3
L'utilisation de branches pour suivre les informations spécifiques à l'environnement / au déploiement me semble être un modèle de fourmi: si nous avons 20 environnements, cela signifie que nous avons 20 branches à synchroniser… une source probable d'erreurs et de confusion. Pourriez-vous expliquer pourquoi vous n'utilisez pas de fichiers de configuration pour suivre les informations spécifiques à l'environnement / au déploiement et quel est votre flux de travail avec ces branches? Ce ne sont pas des problèmes triviaux!
Michael Le Barbier Grünewald

3

Faire une distinction entre Ops, Dev et DevOps favorise l'isolement et impose un état d'esprit de «jeter par-dessus le mur». Pour accroître la coopération entre les équipes, il faut tout mettre dans un référentiel nécessaire à la construction et au déploiement du projet.

Cela dit, la réponse à la question:

Comment structurer le code et les configurations liés à DevOps dans un référentiel de code?

est que si config est requis pour exécuter le projet, alors il faut le mettre dans le même répertoire.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.