Gestion de la configuration 101 : écriture de playbooks Ansible

De Get Docs
Aller à :navigation, rechercher

Introduction

En un mot, la gestion de la configuration du serveur (également appelée automatisation informatique) est une solution pour transformer l'administration de votre infrastructure en une base de code, décrivant tous les processus nécessaires au déploiement d'un serveur dans un ensemble de scripts de provisionnement qui peuvent être versionnés et facilement réutilisés. Il peut grandement améliorer l'intégrité de toute infrastructure de serveur au fil du temps.

Dans un guide précédent, nous avons parlé des principaux avantages de la mise en œuvre d'une stratégie de gestion de la configuration pour votre infrastructure de serveur, du fonctionnement des outils de gestion de la configuration et de ce que ces outils ont généralement en commun.

Cette partie de la série vous guidera tout au long du processus d'automatisation du provisionnement de serveurs à l'aide d'Ansible, un outil de gestion de la configuration qui fournit un cadre d'automatisation complet et des capacités d'orchestration, tout en maintenant un objectif de simplicité et de minimalisme ultimes. Nous nous concentrerons sur la terminologie, la syntaxe et les fonctionnalités du langage nécessaires à la création d'un exemple simplifié pour automatiser entièrement le déploiement d'un serveur Web Ubuntu 18.04 à l'aide d'Apache.

La liste suivante contient toutes les étapes que nous devons automatiser pour atteindre notre objectif :

  1. Mettre à jour le cache apt
  2. Installer Apache
  3. Créer un répertoire racine de document personnalisé
  4. Placez un fichier index.html dans la racine du document personnalisé
  5. Appliquer un modèle pour configurer notre hôte virtuel personnalisé
  6. Redémarrez Apache

Nous commencerons par examiner la terminologie utilisée par Ansible, suivi d'un aperçu des principales fonctionnalités du langage pouvant être utilisées pour écrire des playbooks. À la fin du guide, vous trouverez le contenu d'un exemple de provisionnement complet pour automatiser les étapes décrites pour la configuration d'Apache sur Ubuntu 18.04.

Remarque : ce guide est destiné à vous présenter le langage Ansible et à écrire des playbooks pour automatiser le provisionnement de votre serveur. Pour une vue plus introductive d'Ansible, y compris les étapes nécessaires à l'installation et à la mise en route de cet outil, ainsi que la façon d'exécuter les commandes et les playbooks Ansible, consultez notre guide Comment installer et configurer Ansible sur Ubuntu 18.04. .


Commencer

Avant de pouvoir passer à une vue plus pratique d'Ansible, il est important que nous nous familiarisions avec la terminologie et les concepts importants introduits par cet outil.

Terminologie

La liste suivante contient un aperçu rapide des termes les plus pertinents utilisés par Ansible :

  • Control Node : la machine sur laquelle Ansible est installé, responsable de l'exécution du provisionnement sur les serveurs que vous gérez.
  • Inventaire : un fichier INI qui contient des informations sur les serveurs que vous gérez.
  • Playbook : un fichier YAML contenant une série de procédures qui doivent être automatisées.
  • Task : un bloc qui définit une seule procédure à exécuter, par exemple : installer un package.
  • Module : un module résume généralement une tâche système, comme la gestion des packages ou la création et la modification de fichiers. Ansible a une multitude de modules intégrés, mais vous pouvez également en créer des personnalisés.
  • Role : un ensemble de playbooks, de modèles et d'autres fichiers associés, organisés de manière prédéfinie pour faciliter la réutilisation et le partage.
  • Play : un approvisionnement exécuté du début à la fin est appelé un play.
  • Facts : variables globales contenant des informations sur le système, telles que les interfaces réseau ou le système d'exploitation.
  • Handlers : utilisé pour déclencher des changements d'état de service, comme le redémarrage ou le rechargement d'un service.

Format de tâche

Une tâche définit une seule étape automatisée qui doit être exécutée par Ansible. Cela implique généralement l'utilisation d'un module ou l'exécution d'une commande brute. Voici à quoi ressemble une tâche :

- name: This is a task
  apt: name=vim state=latest

La partie name est en fait facultative, mais recommandée, car elle apparaît dans la sortie du provisionnement lorsque la tâche est exécutée. La partie apt est un module Ansible intégré qui résume la gestion des packages sur les distributions basées sur Debian. Cet exemple de tâche indique à Ansible que l'état du package vim doit être modifié en latest, ce qui obligera le gestionnaire de packages à installer ce package s'il n'est pas encore installé.

Format de livre de jeu

Les playbooks sont des fichiers YAML contenant une série de directives pour automatiser le provisionnement d'un serveur. L'exemple suivant est un playbook simple qui effectue deux tâches : met à jour le cache apt et installe ensuite vim :

---
- hosts: all
  become: true
  tasks:
     - name: Update apt-cache 
       apt: update_cache=yes

     - name: Install Vim
       apt: name=vim state=latest

YAML s'appuie sur l'indentation pour sérialiser les structures de données. Pour cette raison, lors de l'écriture de playbooks et en particulier lors de la copie d'exemples, vous devez faire très attention à maintenir l'indentation correcte.

Avant la fin de ce guide, nous verrons un exemple plus réel d'un playbook, expliqué en détail. La section suivante vous donnera un aperçu des éléments et fonctionnalités les plus importants pouvant être utilisés pour écrire des playbooks Ansible.

Rédaction de manuels

Maintenant que vous connaissez la terminologie de base et le format général des playbooks et des tâches dans Ansible, nous allons découvrir certaines fonctionnalités du playbook qui peuvent nous aider à créer des automatisations plus polyvalentes.

Travailler avec des variables

Il existe différentes manières de définir des variables dans Ansible. Le moyen le plus simple consiste à utiliser la section vars d'un playbook. L'exemple ci-dessous définit une variable package qui est ensuite utilisée dans une tâche :

---
- hosts: all
  become: true
  vars:
     package: vim
  tasks:
     - name: Install Package
       apt: name={{ package }} state=latest

La variable package a une portée globale, ce qui signifie qu'elle est accessible à partir de n'importe quel point du provisionnement, même à partir des fichiers et modèles inclus.

Utiliser des boucles

Les boucles sont généralement utilisées pour répéter une tâche en utilisant différentes valeurs d'entrée. Par exemple, au lieu de créer 10 tâches pour installer 10 packages différents, vous pouvez créer une seule tâche et utiliser une boucle pour répéter la tâche avec tous les différents packages que vous souhaitez installer.

Pour créer une boucle dans une tâche, incluez l'option with_items avec un tableau de valeurs. Le contenu est accessible via la variable de boucle item, comme illustré dans l'exemple ci-dessous :

- name: Install Packages
  apt: name={{ item }} state=latest
  with_items:
     - vim
     - git
     - curl  

Vous pouvez également utiliser une variable de tableau pour définir vos éléments :

---
- hosts: all
  become: true
  vars:
     packages: [ 'vim', 'git', 'curl' ]
  tasks:
     - name: Install Package
       apt: name={{ item }} state=latest
       with_items: "{{ packages }}"

Utiliser des conditions

Les conditions peuvent être utilisées pour décider dynamiquement si une tâche doit être exécutée ou non, en fonction d'une variable ou d'une sortie d'une commande, par exemple.

L'exemple suivant n'arrêtera que les systèmes basés sur Debian :

- name: Shutdown Debian Based Systems
  command: /sbin/shutdown -t now
  when: ansible_os_family == "Debian"

Le conditionnel when reçoit en argument une expression à évaluer. La tâche n'est exécutée que si l'expression est évaluée à true. Dans notre exemple, nous avons testé un fact pour vérifier si le système d'exploitation est de la famille Debian.

Un cas d'utilisation courant des conditions dans l'automatisation informatique est lorsque l'exécution d'une tâche dépend de la sortie d'une commande. Avec Ansible, nous implémentons cela en enregistrant une variable pour contenir les résultats d'une exécution de commande, puis en testant cette variable dans une tâche ultérieure. Nous pouvons tester l'état de sortie de la commande (en cas d'échec ou de réussite). Nous pouvons également rechercher des contenus spécifiques dans la sortie, bien que cela puisse nécessiter l'utilisation d'expressions régulières et de commandes d'analyse de chaînes.

L'exemple suivant montre deux tâches conditionnelles basées sur la sortie d'une commande php -v. Nous allons tester l'état de sortie de la commande, car nous savons qu'elle ne s'exécutera pas si PHP n'est pas installé sur ce serveur. La partie ignore_errors de la tâche est importante pour s'assurer que le provisionnement continue même lorsque l'exécution de la commande échoue.

- name: Check if PHP is installed
  register: php_installed
  command: php -v
  ignore_errors: true

- name: This task is only executed if PHP is installed
  debug: var=php_install
  when: php_installed|success
  
- name: This task is only executed if PHP is NOT installed
  debug: msg='PHP is NOT installed'
  when: php_installed|failed

Le module debug utilisé ici est un module utile pour afficher le contenu des variables ou des messages de débogage. Il peut soit imprimer une chaîne (lors de l'utilisation de l'argument msg) ou imprimer le contenu d'une variable (lors de l'utilisation de l'argument var).

Travailler avec des modèles

Les modèles sont généralement utilisés pour configurer des fichiers de configuration, permettant l'utilisation de variables et d'autres fonctionnalités destinées à rendre ces fichiers plus polyvalents et réutilisables. Ansible utilise le moteur de template Jinja2.

L'exemple suivant est un modèle pour configurer un hôte virtuel Apache, en utilisant une variable pour configurer la racine du document pour cet hôte :

<VirtualHost *:80>
    ServerAdmin [email protected]
    DocumentRoot {{ doc_root }}

    <Directory {{ doc_root }}>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Le module intégré template est utilisé pour appliquer le modèle à partir d'une tâche. Si vous avez nommé le fichier de modèle ci-dessus vhost.tpl et que vous l'avez placé dans le même répertoire que votre playbook, voici comment appliquer le modèle pour remplacer l'hôte virtuel Apache par défaut :

- name: Change default Apache virtual host
  template: 
    src: vhost.tpl
    dest: /etc/apache2/sites-available/000-default.conf

Définir et déclencher des gestionnaires

Les gestionnaires sont utilisés pour déclencher un changement d'état dans un service, tel qu'un restart ou un stop. Même s'ils peuvent sembler assez similaires aux tâches normales, les gestionnaires ne sont exécutés que lorsqu'ils ont été précédemment déclenchés à partir d'une directive notify dans une tâche. Ils sont généralement définis comme un tableau dans une section handlers du playbook, mais ils peuvent également vivre dans des fichiers séparés.

Prenons en considération notre exemple d'utilisation de modèle précédent, où nous avons configuré un hôte virtuel Apache. Si vous voulez vous assurer qu'Apache est redémarré après un changement d'hôte virtuel, vous devez d'abord créer un gestionnaire pour le service Apache. Voici comment les gestionnaires sont définis dans un playbook :

handlers:
    - name: restart apache
      service: name=apache2 state=restarted
    
    - name: other handler
      service: name=other state=restarted

La directive name ici est importante car ce sera l'identifiant unique de ce gestionnaire. Pour déclencher ce gestionnaire à partir d'une tâche, vous devez utiliser l'option notify :

- name: Change default Apache virtual host
  template: 
    src: vhost.tpl
    dest: /etc/apache2/sites-available/000-default.conf
  notify: restart apache

Nous avons vu certaines des fonctionnalités les plus importantes que vous pouvez utiliser pour commencer à écrire des playbooks Ansible. Dans la section suivante, nous allons plonger dans un exemple plus réel d'un playbook qui automatisera l'installation et la configuration d'Apache sur Ubuntu.

Exemple de livre de jeu

Examinons maintenant un playbook qui automatisera l'installation d'un serveur Web Apache dans un système Ubuntu 18.04, comme indiqué dans l'introduction de ce guide.

L'exemple complet, y compris le fichier modèle pour la configuration d'Apache et un fichier HTML devant être servi par le serveur Web, peut être trouvé sur Github. Le dossier contient également un Vagrantfile qui vous permet de tester le playbook dans une configuration simplifiée, à l'aide d'une machine virtuelle gérée par Vagrant.

Contenu du livret

Le contenu complet du playbook est disponible ici pour votre commodité:

playbook.yml

---
- hosts: all
  become: true
  vars:
    doc_root: /var/www/example
  tasks:
    - name: Update apt
      apt: update_cache=yes

    - name: Install Apache
      apt: name=apache2 state=latest

    - name: Create custom document root
      file: path={{ doc_root }} state=directory owner=www-data group=www-data

    - name: Set up HTML file
      copy: src=index.html dest={{ doc_root }}/index.html owner=www-data group=www-data mode=0644

    - name: Set up Apache virtual host file
      template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf
      notify: restart apache
  handlers:
    - name: restart apache
      service: name=apache2 state=restarted

Examinons chaque partie de ce playbook plus en détail :

Hôtes  : tous Le playbook commence par indiquer qu'il doit être appliqué aux hôtes all de votre inventaire (hosts: all). Il est possible de restreindre l'exécution du playbook à un hôte spécifique ou à un groupe d'hôtes. Cette option peut être écrasée au moment de l'exécution.

become : true La partie become: true indique à Ansible d'utiliser l'élévation de privilèges (sudo) pour exécuter toutes les tâches de ce playbook. Cette option peut être remplacée tâche par tâche.

vars Définit une variable, doc_root, qui est ensuite utilisée dans une tâche. Cette section peut contenir plusieurs variables.

tâches La section où les tâches réelles sont définies. La première tâche met à jour le cache apt et la deuxième tâche installe le package apache2.

La troisième tâche utilise le module intégré fichier pour créer un répertoire qui servira de racine de document. Ce module peut être utilisé pour gérer des fichiers et des répertoires.

La quatrième tâche utilise le module copy pour copier un fichier local sur le serveur distant. Nous copions un simple fichier HTML à servir comme notre site Web hébergé par Apache.

handlers Enfin, nous avons la section handlers, où les services sont déclarés. Nous définissons le gestionnaire restart apache qui est notifié à partir de la quatrième tâche, où le modèle Apache est appliqué.

Exécuter un Playbook

Une fois que vous avez téléchargé le contenu de ce playbook sur votre nœud de contrôle Ansible, vous pouvez utiliser ansible-playbook pour l'exécuter sur un ou plusieurs nœuds de votre inventaire. La commande suivante exécutera le playbook sur tous les hôtes à partir de votre fichier d'inventaire par défaut, en utilisant l'authentification par paire de clés SSH pour se connecter en tant qu'utilisateur système actuel :

ansible-playbook playbook.yml

Vous pouvez également utiliser -l pour limiter l'exécution à un seul hôte ou à un groupe d'hôtes de votre inventaire :

ansible-playbook -l host_or_group playbook.yml

Si vous devez spécifier un autre utilisateur SSH pour vous connecter au serveur distant, vous pouvez inclure l'argument -u user à cette commande :

ansible-playbook -l host_or_group playbook.yml -u remote-user

Pour plus d'informations sur l'exécution des commandes et des playbooks Ansible, veuillez consulter notre guide sur Comment installer et configurer Ansible sur Ubuntu 18.04.

Conclusion

Ansible est un outil d'automatisation informatique minimaliste qui a une faible courbe d'apprentissage, utilisant YAML pour ses scripts de provisionnement. Il possède un grand nombre de modules intégrés qui peuvent être utilisés pour des tâches abstraites telles que l'installation de packages et l'utilisation de modèles. Ses exigences d'infrastructure simplifiées et son langage simple peuvent convenir à ceux qui débutent avec la gestion de la configuration. Cependant, il peut manquer certaines fonctionnalités avancées que vous pouvez trouver avec des outils plus complexes tels que Puppet et Chef.

Dans la prochaine partie de cette série, nous verrons un aperçu pratique de Puppet, un outil de gestion de configuration populaire et bien établi qui utilise un DSL personnalisé expressif et puissant basé sur Ruby pour écrire des scripts de provisionnement.