Possibilité de gérer la configuration de Windows. Histoire de réussite

Lors d'une des réunions de la communauté .Net de Saint-Pétersbourg des développeurs de la communauté SpbDotNet, nous avons fait une expérience et décidé de discuter de la façon dont vous pouvez appliquer des approches qui sont depuis longtemps devenues la norme dans le monde Linux pour automatiser les infrastructures Windows. Mais afin de ne pas tout mettre au point de marquer le drapeau Ansible, il a été décidé de le montrer par l'exemple du déploiement d'une application ASP.Net.


Aleksey Chernov, développeur principal de l'équipe de développement de la bibliothèque de composants d'interface utilisateur pour nos projets, s'est porté volontaire pour être conférencier. Et oui, cela ne vous a pas semblé: un développeur JavaScript s'est présenté devant un public .Net.


Quiconque est intéressé par le résultat d'une telle expérience, bienvenue, sous la coupe du décodage.



Salut) Ils se sont déjà un peu gâtés et ont dit que je suis un front-end, donc vous pouvez déjà diverger =) Je m'appelle Alexey, je fais toutes sortes de choses sur le développement web depuis un certain temps. J'ai commencé avec Perl, puis il y avait PHP, un petit RoR, un peu, un peu de ça. Et puis JavaScript a fait irruption dans ma vie, et depuis lors, je fais presque tout cela.


En plus de JS, j'ai récemment écrit pas mal d'autotests (en plus, sur le même JS), et je dois donc m'occuper de l'automatisation du déploiement des bancs de test et de l'infrastructure pour eux.


Contexte


Il y a deux ans, je me suis retrouvé chez Veeam, où ils développent des produits pour Windows. À ce moment, j'ai été très surpris, mais il s'est avéré que cela se produit =). Mais surtout, j'ai été surpris par le niveau inhabituellement bas d'automatisation de tout ce qui est lié au déploiement, au déploiement d'applications, aux tests, etc.


Nous, ceux qui développons pour Linux, sommes habitués depuis longtemps au fait que tout devrait être dans Docker, il y a Kubernetes, et tout se déroule en un seul clic. Et quand je me suis retrouvé dans un environnement où tout cela n'est pas là, ça a choqué. Et quand j'ai commencé à faire des tests automatiques, j'ai réalisé que ce n'était que 20% de réussite, et tout le reste préparait l'infrastructure pour eux.



Mes sentiments au début


Conditions actuelles


Je vais vous expliquer comment tout est organisé avec nous, ce que nous devons automatiser et ce que nous faisons.


Nous avons un tas de produits différents, la plupart sous Windows, il y en a plusieurs sous Linux et même quelque chose sous Solaris. Un grand nombre de versions sont collectées quotidiennement pour tous les produits. En conséquence, il est nécessaire de tout déployer dans les laboratoires de test, à la fois pour l'AQ et pour les développeurs eux-mêmes, afin qu'ils puissent vérifier l'intégration des applications. Tout cela nécessite une énorme infrastructure de nombreux serveurs et machines virtuelles Iron. Et parfois, nous effectuons des tests de performances, lorsque nous devons élever immédiatement un millier de machines virtuelles et voir à quelle vitesse nos applications fonctionneront.


Les problèmes


Bien sûr, dans les premières étapes (lire, il y a longtemps), lors de la tentative d'automatisation directe, PowerShell a été utilisé. L'outil est puissant, mais les scripts de déploiement sont extrêmement compliqués. Un autre problème était le manque de gestion centralisée de ce processus. Certains scripts ont été exécutés localement par des développeurs, d'autres sur des machines virtuelles créées à l'époque des mammouths, etc. Résultat: il était difficile d'obtenir un seul résultat et de comprendre ce qui fonctionne et ce qui ne fonctionne pas. Vous venez travailler, ouvrez le navigateur - le serveur n'est pas disponible. Pourquoi il n'est pas disponible, ce qui s'est passé, où il s'est cassé - ce n'était absolument pas clair. Il n’y avait pas de point d’entrée unique, et j’ai dû chercher la vérité sur les forums de discussion, et c’est bien si quelqu'un répondait.


Un autre problème, moins évident, est celui des débutants. C'était difficile pour eux. La première semaine de travail, ils se sont plongés dans ce qui se passait. Nous vivions habituellement avec cela, nous assurant que la vie est une chose difficile et que nous devons l'accepter. Comprendre et pardonner, pour ainsi dire.


Mais à un moment donné, ils ont trouvé la force intérieure pour la surmonter et regarder autour de eux. D'une manière ou d'une autre, vous pouvez probablement le gérer.



La première étape vers la résolution du problème est de l'accepter.


Sélection de la solution


Lorsque vous ne savez pas quoi faire, voyez ce que font les autres.


Et pour commencer, nous avons fait notre liste d'exigences pour ce que nous voulons obtenir à la fin.


  • Base de code unifiée. Tous les scripts de déploiement doivent être au même endroit. Vous souhaitez déployer quelque chose ou voir comment cela se déroule: voici un référentiel pour vous, allez-y.
  • Tout le monde sait comment cela fonctionne. Les questions devraient disparaître "Je ne comprends pas comment le déployer, donc le deuxième jour je ne pourrai pas fermer le bogue".
  • Possibilité de démarrer par bouton. Nous devons pouvoir contrôler les déploiements. Par exemple, une sorte d'interface Web, où vous allez, appuyez sur un bouton et le produit souhaité est déployé sur l'hôte souhaité.

Après nous être assurés que cette liste couvre le minimum d'exigences nécessaires et suffisantes pour notre bonheur, nous avons commencé à essayer. Traditionnellement, la première chose qu'ils essayaient de résoudre était la méthode d'attaque frontale. Avons-nous de nombreux scripts PowerShell? Alors combinons-les dans un référentiel. Mais le problème n'est pas qu'il y avait trop de scripts, mais que différentes équipes ont fait la même chose avec différents scripts. J'ai parcouru différentes équipes, écouté leurs besoins, collecté les mêmes scripts, essayé de les combiner et de les paramétrer d'une manière ou d'une autre, puis de les placer dans un référentiel unique.


Échec: la tentative a échoué. Premièrement, nous avons commencé à nous disputer beaucoup sur les raisons pour lesquelles nous procédons ainsi et non de cette façon. Pourquoi cette méthode a-t-elle été utilisée, et pas une autre, etc. Et par conséquent, nombreux étaient ceux qui voulaient tout refaire "comme il se doit", sur le principe "Je vais tout bifurquer et tout réécrire pour vous". Et, bien sûr, il ne sera pas possible de combiner les branches avec cette approche.


Tentative numéro deux: il était censé prendre notre serveur CI (TeamCity), faire des modèles dessus et, en utilisant l'héritage, fermer le problème principal dès la première tentative. Mais, comme vous l'avez peut-être deviné tout de suite, Fail nous attendait également : vous ne pouvez utiliser le modèle que pour la dernière version, ce qui signifie que nous n'obtiendrons pas le versioning nécessaire. Et la conséquence d'un grand nombre d'équipes - les modèles sont devenus très nombreux, il est devenu plus difficile de les gérer, et à l'horizon un nouveau marais était clairement visible.



Fatigué de tomber face cachée à toute tentative de décollage, il a été décidé de se rasseoir et de réfléchir sérieusement. Nous avons donc un grand nombre de ps-scripts d'une part et un grand nombre de virtuels d'autre part. Mais nous avions tort, car ce n'était pas la racine du problème. Le problème était qu'il y avait toujours une personne entre ces choses. Peu importe qu'il s'agisse d'un développeur, d'un testeur ou de quelqu'un d'autre, la chaîne logique a toujours été comme ceci:


  • J'ai donc besoin d'une machine virtuelle pour les tests
  • Oui, nous avons ici un pool d'hôtes
  • Et voici le script dont j'ai besoin, maintenant je vais l'exécuter, et tout se passera

Avec la réalisation d'une chose aussi simple en apparence, le problème général a commencé à jouer avec de nouvelles couleurs. Il s'est avéré que toutes nos peines sont dues à l'absence d'une description unique de notre infrastructure. C'était dans l'esprit des gens qui l'ont créé, ils ont siégé dans différents départements, n'ont pas essayé de le documenter d'une manière ou d'une autre et, généralement, chacun vivait dans son propre état.
En ce moment, nous sommes arrivés à la conclusion que la réponse à tous nos problèmes est:


L'infrastructure comme code


C'est précisément que toute notre infrastructure doit être décrite dans le code et se trouver dans le référentiel. Toutes les machines virtuelles, tous leurs paramètres, tout ce qui y est installé - tout doit être décrit dans le code.


Une question légitime se pose - pourquoi?


Nous répondons: cette approche nous donnera l'occasion d'appliquer les meilleures pratiques du monde du développement, auxquelles nous sommes tous si habitués:


  • Contrôle de version. Nous pouvons toujours comprendre ce qui a changé et quand. Plus d'hôte sortant de nulle part ou parti nulle part. Il sera toujours clair qui a apporté les modifications.
  • Révision du code. Nous pourrons contrôler les processus de déploiement afin que certains ne portent pas atteinte aux autres.
  • Intégration continue.

Sélection d'outils


Comme nous le savons tous, il existe de nombreux outils de gestion de configuration. Nous avons opté pour Ansible, car il contient un ensemble de fonctionnalités dont nous avons besoin.
Tout d'abord, nous voulons que le système d'automatisation ne lance aucun programme d'installation, que quelque chose migre quelque part, etc. Tout d'abord, à partir d'un tel système, nous voulons qu'après avoir appuyé sur un bouton, nous verrons l'interface utilisateur de l'application dont nous avons besoin.


Par conséquent, la caractéristique clé pour nous est l'idempotence. Ansible n'a pas d'importance ce qui s'est passé avant. Après avoir démarré le playbook souhaité, nous obtenons toujours le même résultat. Ceci est très important lorsque vous dites non pas "Installer IIS", mais "Il devrait y avoir IIS", et vous n'avez pas à vous demander s'il était là avant ou non. Il est très difficile d'y parvenir avec des scripts, et les playbooks Ansible offrent une telle opportunité.


Il convient également de mentionner l'absence d'agent d'Ansible. La plupart des systèmes d'automatisation fonctionnent via des agents. Il y a de nombreux avantages à cela - par exemple, les meilleures performances - mais il était important pour nous qu'il n'y ait pas d'agent pour que le système n'ait pas à être préparé en plus d'une manière ou d'une autre.


PowerShell:


$url = "http://buildserver/build.msi" $output = "$PSSscriptRoot\build.msi" Invoke-WebRequest -Uri $url -OutFile $output 

Ansible:


 name: Download build hosts: all tasks: name: Download installer win_get_url: url: "http://buildserver/build.msi" dest: "build.msi" force: no 

Ici, nous voyons que dans l'exemple de base, le ps-script sera encore plus concis que le playbook Ansible. 3 lignes de script contre 7 lignes de playbook pour télécharger un fichier.


Mais, Petka, il y a une nuance. Dès que nous voulons adhérer au principe d'idempotence et, par exemple, pour être sûr que le fichier sur le serveur n'a pas changé et qu'il n'a pas besoin d'être téléchargé, vous devrez implémenter une requête HEAD dans le script, ce qui ajoute environ 200 lignes. Et dans le playbook - un. Le module Ansible win_get_url, qui effectue toutes les vérifications pour vous, contient 257 lignes de code que vous n’avez pas à insérer dans chaque script.


Et ce n'est là qu'un exemple d'une tâche très simple.



Et si vous y réfléchissez, nous avons besoin d'idempotence partout:


  • Vérifiez l'existence d'une machine virtuelle. Dans le cas des scripts, nous risquons soit d'en produire un nombre infini, soit le script plantera au tout début.
  • Quels packages msi existe-t-il sur la machine? Dans le meilleur des cas, rien ne tombera ici; dans le pire, la machine cessera de fonctionner correctement.
  • Dois-je télécharger à nouveau des artefacts de build? C'est bien si vos builds pèsent une douzaine de mégaoctets. Et qu'en est-il de ceux qui ont quelques gigaoctets?

Et d'autres exemples, où la solution consiste à gonfler les scripts avec une ramification sans fin des ifs qui ne peuvent pas être correctement débogués et impossibles à gérer.


Entre autres choses qui sont importantes pour nous, Ansible n'utilise pas d'agents pour gérer vos hôtes et machines. Sous Linux, bien sûr, il fonctionne sur ssh, tandis que pour Windows, WinRM est utilisé. D'où la conséquence évidente: Ansible est multi-plateforme. Il prend en charge un nombre fantastique de plates-formes, jusqu'aux équipements réseau.


Et le dernier, mais non moins important, est le format d'enregistrement de configuration YAML. Tout le monde y est habitué, il est facile à lire et il est facile de comprendre ce qui s'y passe.


Mais tout n'est pas si doux, il y a des problèmes:


  • Le problème est douteux: pour exécuter des playbooks, vous avez toujours besoin d'une machine Linux, même si l'ensemble de votre infrastructure est exclusivement Windows. Bien que ce ne soit pas un si gros problème dans le monde moderne, car sur Windows 10, il y a maintenant WSL, où vous pouvez exécuter Ubuntu, sous lequel piloter des playbooks.
  • Parfois, les playbooks sont vraiment difficiles à déboguer. Ansible est écrit en python, et la dernière chose que je veux voir est une feuille de pile de pile python à cinq écrans. Et une faute de frappe dans le nom du module

Comment ça marche?
Tout d'abord, nous avons besoin d'une machine Linux. Dans la terminologie Ansible, cela s'appelle la machine de contrôle.
Les playbooks vont commencer à partir de là, et toute la magie se produit dessus.


Sur cette machine, nous aurons besoin de:


  • Python et le gestionnaire de paquets python pip. De nombreuses distributions sont prêtes à l'emploi, donc pas de surprise ici.
  • Installez Ansible via pip, comme le moyen le plus universel: pip install ansible
  • Ajouter un module winrm pour accéder aux machines Windows: pip install pywinrm [credssp]
  • Et sur les machines que nous voulons contrôler, nous devons activer winrm, car il est désactivé par défaut. Il existe de nombreuses façons de procéder, et elles sont toutes décrites dans la documentation Ansible. Mais le plus simple consiste à extraire le script terminé du référentiel Ansible et à l'exécuter avec l'option d'autorisation requise: ConfigureRemotingForAnsible.ps1 -EnableCredSSP

La partie la plus importante dont nous avions besoin pour arrêter de souffrir avec les scripts ps était Inventory. Un fichier YAML (dans notre cas), qui décrit notre infrastructure et où vous pouvez toujours chercher à comprendre où cela est déployé. Et, bien sûr, les playbooks eux-mêmes. À l'avenir, le travail ressemble à lancer un playbook avec le fichier d'inventaire nécessaire et des paramètres supplémentaires.


 all: children: webservers: hosts: spbdotnet-test-host.dev.local: dbservers: hosts: spbdotnet-test-host.dev.local: vars: ansible_connection: winrm ansible_winrm_transport: credssp ansible_winrm_server_cert_validation: ignore ansible_user: administrator ansible_password: 123qweASD 

Ici, tout est simple: le groupe racine est all et deux sous-groupes, les webserves et les dbservers. Tout le reste est intuitif, mais j'attirerai votre attention sur le fait qu'Ansible, par défaut, croit que Linux est partout, donc pour Windows, vous devez absolument spécifier winrm et le type d'autorisation.


Le mot de passe sous forme claire, bien sûr, n'a pas besoin d'être stocké dans le playbook, voici juste un exemple. Les mots de passe peuvent être stockés, par exemple, dans Ansible-Vault. Nous utilisons TeamCity pour cela, qui transmet des secrets à travers des variables d'environnement et ne déclenche rien.


Modules


Tout ce que fait Ansible, il le fait à l'aide de modules. Les modules pour Linux sont écrits en python, pour Windows dans PowerShell. Et une vénération pour l'idempotence: le résultat du module se présente toujours sous la forme d'un fichier json, qui indique s'il y a eu des changements sur l'hôte ou non.


Dans le cas général, nous exécuterons une construction de la forme liste de modules du fichier d'inventaire du groupe d'hôtes ansible:



Playbooks


Un playbook est une description de comment et où nous exécuterons les modules Ansible.


 - name: Install AWS CLI hosts: all vars: aws_cli_download_dir: c:\downloads aws_cli_msi_url: https://s3.amazonaws.com/aws-cli/AWSCLI32PY3.msi tasks: - name: Ensure target directory exists win_file: path: "{{ aws_cli_download_dir }}" state: directory - name: Download installer win_get_url: url: "{{ aws_cli_msi_url }}" dest: "{{ aws_cli_download_dir }}\\awscli.msi" force: no - name: Install AWS CLI win_package: path: "{{ aws_cli_download_dir }}\\awscli.msi" state: present 

Dans cet exemple, nous avons trois tâches. Chaque tâche est un appel de module. Dans ce manuel, nous créons d'abord un répertoire (assurez-vous qu'il existe), puis téléchargez-y l'AWS CLI et utilisez le module win_packge pour l'installer.


En exécutant ce playbook, nous obtenons ce résultat.



Le rapport montre que quatre tâches ont été menées à bien et trois des quatre ont apporté des modifications à l'hôte.


Mais que se passe-t-il si vous exécutez à nouveau ce manuel? Nous n'avons écrit nulle part où créer le répertoire, télécharger le fichier d'installation et l'exécuter. Nous vérifions simplement la disponibilité de chaque article et sautons si disponible.



C'est l'idempotence que nous ne pouvions pas atteindre avec PowerShell.


Pratique


Il s'agit d'un exemple légèrement simplifié, mais, en principe, c'est exactement ce que nous faisons tous les jours.
Nous déploierons une application composée d'un service Windows et d'une application Web sous IIS.


 - name: Setup App hosts: webservers tasks: - name: Install IIS win_feature: name: - Web-Server - Web-Common-Http include_sub_features: True include_management_tools: True state: present register: win_feature - name: reboot if installing Web-Server feature requires it win_reboot: when: win_feature.reboot_required 

Tout d'abord, nous devons voir s'il existe un IIS sur l'hôte et l'installer sinon. Et ce serait bien d'ajouter immédiatement des outils de gestion et toutes les fonctionnalités dépendantes. Et c'est très bien si l'hôte est redémarré si nécessaire.


La première tâche que nous résolvons est le module win_feature, qui est engagé dans la gestion des fonctionnalités de Windows. Et ici, pour la première fois, nous avons les variables d'environnement Ansible, dans l'élément de registre. Rappelez-vous, j'ai dit que les tâches retournent toujours un objet json? Maintenant, après avoir terminé la tâche Installer IIS, la sortie du module win_feature se trouve dans la variable win_feature (excusez-moi pour la tautologie).


Dans la tâche suivante, nous appelons le module win_reboot. Mais nous n'avons pas besoin de redémarrer notre serveur à chaque fois. Nous ne le rechargerons que si le module win_feature nous renvoie cette exigence sous forme de variable.


L'étape suivante consiste à installer SQL. Un million de façons ont déjà été inventées pour ce faire. J'utilise le module win_chocolatey ici. Il s'agit d'un gestionnaire de packages pour Windows. Oui, c'est exactement ce à quoi nous sommes habitués sous Linux. Les modules sont soutenus par la communauté, et maintenant il y en a déjà plus de six mille. Je vous conseille fortement d'essayer.


 - name: SQL Server hosts: dbservers tasks: - name: Install MS SQL Server 2014 win_chocolatey: name: mssqlserver2014express state: present 

Nous avons donc préparé l'hôte pour le lancement de l'application, déployons-le!


 - name: Deploy binaries hosts: webservers vars: myapp_artifacts: files/MyAppService.zip myapp_workdir: C:\myapp tasks: - name: Remove Service if exists win_service: name: MyAppService state: absent path: "{{ myapp_workdir }}\\MyAppService.exe" 

Au cas où, la première chose que nous faisons est de supprimer le service existant.


 - name: Delete old files win_file: path: "{{ myapp_workdir }}\\" state: absent - name: Copy artifacts to remote machine win_copy: src: "{{ myapp_artifacts }}" dest: "{{ myapp_workdir }}\\" - name: Unzip build artifacts win_unzip: src: "{{ myapp_workdir }}\\MyAppService.zip" dest: "{{ myapp_workdir }}" 

L'étape suivante consiste à télécharger de nouveaux artefacts sur l'hôte. Ce playbook implique qu'il s'exécute sur un serveur de build, toutes les archives sont dans un dossier connu, et nous leur indiquons le chemin avec des variables. Après la copie (win_copy), les archives sont décompressées (win_unzip). Ensuite, nous enregistrons simplement le service, disons le chemin vers exe et qu'il doit être démarré.


  - name: Register and start the service win_service: name: ReporterService start_mode: auto state: started path: "{{ myapp_workdir }}\\MyAppService.exe" 

Terminé!?


Il semble que notre service soit prêt pour le travail et la défense, cependant, il y a un «mais» - nous n'avons pas observé le principe de l'idempotence. Nous supprimons toujours le code existant, puis déployons le nouveau.


Et c'est ça le problème. Si nous supprimions l'ancien service hors service, et après qu'une sorte d'erreur s'est produite et que le playbook n'a pas terminé son travail, nous aurons un hôte cassé. Ou, par exemple, nous déployons plusieurs applications en même temps, dont une n'a pas changé, alors nous n'avons pas besoin de la déployer aussi.


Que peut-on faire? Alternativement, vous pouvez vérifier la somme de contrôle de nos artefacts et les comparer avec ceux du serveur.


  - name: Get arifacts checksum stat: path: "{{ myapp_artifacts }}" delegate_to: localhost register: myapp_artifacts_stat - name: Get remote artifacts checksum win_stat: path: "{{ myapp_workdir }}\\MyAppService.zip" register: myapp_remote_artifacts_stat 

Nous utilisons le module stat, qui fournit toutes sortes d'informations sur les fichiers, y compris la somme de contrôle. Ensuite, en utilisant le registre de directives familier, nous écrivons le résultat dans une variable. D'intéressant: delegate_to indique que cela doit être fait sur la machine locale où le playbook est démarré.


  - name: Stop play if checksums match meta: end_play when: - myapp_artifacts_stat.stat.checksum is defined - myapp_remote_artifacts_stat.stat.checksum is defined - myapp_artifacts_stat.stat.checksum == myapp_remote_artifacts_stat.stat.checksum 

Et avec l'aide du méta-module, nous disons que nous devons terminer le playbook si les sommes de contrôle des artefacts sur les machines locales et distantes correspondent. C'est ainsi que nous avons observé le principe de l'idempotence.


  - name: Ensure that the WebApp application exists win_iis_webapplication: name: WebApp physical_path: c:\webapp site: Default Web Site state: present 

Voyons maintenant notre application Web. Nous omettons la partie sur la copie de fichiers, allons droit au but. Notre serveur de build a créé l'éditeur, téléchargé tous les fichiers en vrac sur l'hôte et utilisé le module intégré pour travailler avec les applications IIS. Il créera l'application et l'exécutera.


Réutilisation du code


L'une des tâches que nous nous étions fixées était de permettre à tout ingénieur de l'entreprise de lancer facilement un déploiement. Il écrit son livre de jeu à partir de modules prêts à l'emploi, dit qu'il doit exécuter tel ou tel produit sur tel ou tel hôte.


Pour cela, Ansible a des rôles. Il s'agit essentiellement d'une convention. Nous créons un dossier / rôles / sur le serveur et y mettons nos rôles. Chaque rôle est un ensemble de fichiers de configuration: une description de nos appareils, variables, fichiers de service, etc. Habituellement, une entité isolée joue un rôle. L'installation d'IIS est un excellent exemple si nous devons non seulement l'installer, mais aussi le configurer d'une manière ou d'une autre avec des tâches supplémentaires. Nous créons un rôle distinct et isolons ainsi tous les playbooks liés à IIS dans le dossier de rôles. À l'avenir, nous appellerons simplement ce rôle avec la directive include_role% role_name%.


Naturellement, nous avons créé des rôles pour toutes les applications, laissant aux ingénieurs la possibilité de personnaliser le processus à l'aide de paramètres de configuration.


 - name: Run App hosts: webservers tasks: - name: "Install IIS" include_role: name: IIS - name: Run My App include_role: name: MyAppService vars: myapp_artifacts: ./buld.zip 

Dans cet exemple, le rôle Exécuter mon application a la capacité de transférer un chemin d'accès aux artefacts.


Ici, vous devez mettre un mot sur Ansible Galaxy - un référentiel de solutions standard couramment disponibles. Comme d'habitude dans une société décente, de nombreux problèmes ont déjà été résolus devant nous. Et s'il y a un sentiment que maintenant nous allons commencer à réinventer la roue, alors vous devez d'abord regarder la liste des modules intégrés, puis plonger dans Ansible Galaxy. Il est probable que le playbook dont vous avez besoin ait déjà été créé par quelqu'un d'autre. Il existe un grand nombre de modules pour toutes les occasions.


Plus de flexibilité


Mais que faire s'il n'y a pas de module intégré ou un rôle approprié dans Galaxy? Il y a deux options: soit nous faisons quelque chose de mal, soit nous avons vraiment une tâche unique.


Dans le cas de la deuxième option, nous pouvons toujours écrire notre module. Comme je l'ai montré au début, Ansible permet d'écrire le module le plus simple en 10 minutes, et lorsque vous approfondissez, une documentation assez détaillée vient à votre aide, couvrant de nombreuses questions.


Ci
Dans notre département, nous aimons vraiment TeamCity, mais il peut y avoir tout autre serveur CI de votre choix. Pourquoi devons-nous les partager?


Premièrement, nous pouvons toujours vérifier la syntaxe de nos playbooks. Bien que YAML considère les onglets comme une erreur de syntaxe, il s'agit d'une fonctionnalité très utile.


Également sur le serveur CI, nous exécutons ansible-lint. Il s'agit d'un analyseur statique de configurations ansibles, qui donne une liste de recommandations.



Par exemple, ici, il dit que nous avons un espace supplémentaire à la fin de la ligne, et pour une tâche, aucun nom n'est donné. Ceci est important car le nom du module peut apparaître plusieurs fois dans le même playbook et toutes les tâches doivent être nommées.


Bien sûr, vous pouvez toujours écrire des tests pour les playbooks. Nous pouvons nous permettre de ne pas le faire parce que nous allons déployer dans l'environnement de test et rien de critique ne se produira. Mais si vous déployez sur le prod, il serait préférable de tout vérifier. L'avantage d'ansible vous permet de tester non seulement des playbooks, mais aussi des modules individuels. Assurez-vous donc d'y prêter attention.


Et la deuxième raison principale d'utiliser le serveur CI est de lancer des playbooks. C'est le même bouton magique "Bien faire", qui nous donne TeamCity. Nous créons simplement des configurations simples pour différents produits, où nous disons: ansible-playbook reporter_vm.yml -i inventaire.yml -vvvv et obtenez le bouton Déployer.


Bonus supplémentaire: vous pouvez construire des builds en fonction des builds. Dès que quelque chose s'est consolidé, TeamCity démarre le processus de redéploiement, après quoi nous ne pouvons consulter les journaux que si quelque chose se casse soudainement.


Total


  • Scripts PowerShell confus et disparates que nous avons remplacés par des configurations YAML.
  • Nous avons remplacé diverses implémentations des mêmes problèmes par des rôles communs qui peuvent être réutilisés. Un référentiel a été créé où se trouvent les rôles. Si le rôle vous convient, il vous suffit de l'utiliser. Si cela ne vous convient pas, il vous suffit d'envoyer la demande de pool, et cela vous convient =)
  • Vous pouvez désormais vérifier le succès du déploiement en un seul endroit.
  • Tout le monde sait où chercher les journaux.
  • Les problèmes de communication ont également été résolus via un référentiel commun et TeamCity. Toutes les personnes intéressées savent où se trouvent les playbooks et comment ils fonctionnent.

PS Tous les exemples de l'article peuvent être pris sur github .

Source: https://habr.com/ru/post/fr455604/


All Articles