Gestion de la configuration 101 : écriture de playbooks Ansible
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 :
- Mettre à jour le cache
apt
- Installer Apache
- Créer un répertoire racine de document personnalisé
- Placez un fichier
index.html
dans la racine du document personnalisé - Appliquer un modèle pour configurer notre hôte virtuel personnalisé
- 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.