Assembler et exécuter un playbook avec des rôles personnalisés, Git et système
Dans cette étape, vous allez rassembler tous les composants que vous avez préparés : votre rôle personnalisé, la dépendance depuis Git et le rôle système RHEL. Vous allez créer un playbook principal qui orchestrera ces rôles pour configurer entièrement le serveur web de développement.
Considérez cette étape comme l'assemblage d'une machine complexe à partir de différentes pièces : chaque rôle remplit un objectif spécifique, et ils travaillent ensemble pour créer un environnement de serveur web complet. Décomposons cela en morceaux gérables :
Tout d'abord, assurez-vous d'être dans le répertoire principal du projet.
cd ~/project
Avant de plonger dans la configuration, comprenons ce que nous créons :
- Configuration Ansible : Définit le comportement d'Ansible et où il trouve les fichiers.
- Inventaire : Définit quels serveurs gérer (dans notre cas, localhost).
- Variables : Stockent les données que nos rôles utiliseront (informations développeur, paramètres SELinux).
- Contenu du rôle personnalisé : Les tâches réelles qui configureront les environnements de développement.
- Playbook principal : L'orchestrateur qui exécute tout dans le bon ordre.
1. Créer la configuration et l'inventaire Ansible
Le fichier ansible.cfg est comme un fichier de configuration qui indique à Ansible comment se comporter. Sans lui, vous devriez spécifier les chemins et les options dans chaque commande. Avec lui, Ansible sait automatiquement où trouver vos rôles, collections et inventaire.
Créez le fichier ansible.cfg en utilisant nano. Ce fichier indique à Ansible où trouver vos rôles, collections et inventaire.
nano ansible.cfg
Ajoutez le contenu suivant. Comprenons chaque ligne :
[defaults]
inventory = inventory
roles_path = roles
collections_paths = collections
host_key_checking = False
[privilege_escalation]
become = True
Ce que fait chaque paramètre :
inventory = inventory : Au lieu de taper -i inventory à chaque fois, Ansible utilisera automatiquement ce fichier.
roles_path = roles : Ansible recherchera les rôles dans le répertoire roles.
collections_paths = collections : Ansible trouvera vos collections installées ici.
host_key_checking = False : Empêche les erreurs de vérification de clé SSH dans les environnements de laboratoire.
become = True : Exécute automatiquement les tâches avec des privilèges élevés lorsque nécessaire.
Enregistrez et quittez nano (Appuyez sur Ctrl+X, puis Y, puis Entrée).
Le fichier d'inventaire indique à Ansible quelles machines gérer. Dans notre cas, nous configurons la machine locale.
nano inventory
Ajoutez la ligne suivante :
localhost ansible_connection=local
Ce que cela signifie :
localhost : Le nom de notre hôte cible.
ansible_connection=local : Au lieu de SSH, utilisez des connexions locales (puisque nous gérons la même machine sur laquelle nous exécutons Ansible).
Enregistrez et quittez nano.
2. Définir les variables de rôle
Les variables dans Ansible sont comme des paramètres que vos rôles peuvent utiliser. Au lieu de coder en dur des valeurs comme les noms d'utilisateur ou les numéros de port dans vos tâches, vous les définissez dans des fichiers de variables. Cela rend votre automatisation flexible et réutilisable.
Le répertoire group_vars/all est un emplacement spécial où Ansible charge automatiquement les variables pour tous les hôtes. Tout fichier YAML dans ce répertoire devient disponible pour vos playbooks et rôles.
Créez la structure de répertoires pour les variables qui s'appliquent à tous les hôtes :
mkdir -p group_vars/all
Maintenant, créez un fichier pour définir les informations du développeur. Ces données seront utilisées par votre rôle personnalisé pour créer des comptes utilisateur et des configurations web.
nano group_vars/all/developers.yml
Ajoutez le contenu suivant :
---
web_developers:
- username: jdoe ## Premier développeur
port: 9081 ## Port personnalisé pour le site web de ce développeur
- username: jdoe2 ## Deuxième développeur
port: 9082 ## Port personnalisé pour le site web de ce développeur
Ce que signifie cette structure de données :
web_developers : Une liste contenant les informations des développeurs.
- Chaque développeur a un
username et un port.
- Votre rôle personnalisé parcourra cette liste pour créer des configurations pour chaque développeur.
Enregistrez et quittez.
Ensuite, créez un fichier de variables pour la configuration SELinux. SELinux (Security-Enhanced Linux) est un module de sécurité qui contrôle ce que les applications peuvent faire.
nano group_vars/all/selinux.yml
Ajoutez le contenu suivant :
---
selinux_state: enforcing ## Définit SELinux en mode enforcing (sécurité maximale)
selinux_ports: ## Liste des ports à autoriser pour Apache
- ports: "9081" ## Autoriser le port 9081
proto: "tcp" ## Protocole : TCP
setype: "http_port_t" ## Type SELinux : port HTTP
state: "present" ## Ajouter cette règle
- ports: "9082" ## Autoriser le port 9082
proto: "tcp" ## Protocole : TCP
setype: "http_port_t" ## Type SELinux : port HTTP
state: "present" ## Ajouter cette règle
Comprendre les paramètres SELinux :
selinux_state: enforcing : SELinux bloquera activement les actions non autorisées.
selinux_ports : Une liste de configurations de ports.
http_port_t : Le type SELinux qui permet à Apache de se lier aux ports.
- Par défaut, Apache ne peut utiliser que les ports 80 et 443 ; nous devons explicitement autoriser les ports 9081 et 9082.
Enregistrez et quittez.
3. Remplir le rôle personnalisé
Votre rôle apache.developer_configs a actuellement la structure de répertoire mais aucun contenu réel. Nous devons ajouter :
- Templates : Fichiers qui peuvent inclure des variables (en utilisant la syntaxe Jinja2).
- Tâches : Le travail réel qu'Ansible effectuera.
- Handlers : Tâches spéciales qui ne s'exécutent que lorsqu'elles sont notifiées (comme le redémarrage des services).
- Métadonnées : Informations sur les dépendances du rôle.
Les templates vous permettent de créer des fichiers de configuration qui s'adaptent en fonction de vos variables. L'extension .j2 indique qu'il s'agit d'un template Jinja2.
nano roles/apache.developer_configs/templates/developer.conf.j2
Ajoutez le contenu suivant :
{% for dev in web_developers %}
Listen {{ dev.port }}
<VirtualHost *:{{ dev.port }}>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/{{ dev.username }}
<Directory /var/www/{{ dev.username }}>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
{% endfor %}
Comprendre la syntaxe du template :
{% for dev in web_developers %} : Commence une boucle à travers la liste des développeurs.
{{ dev.port }} : Insère le numéro de port pour ce développeur.
{{ dev.username }} : Insère le nom d'utilisateur pour ce développeur.
{% endfor %} : Termine la boucle.
- Le résultat sera des configurations de virtual host séparées pour chaque développeur.
Ce que cela crée : Pour nos deux développeurs, ce template générera une configuration Apache qui :
- Fait écouter Apache sur les ports 9081 et 9082.
- Crée des virtual hosts qui servent du contenu depuis
/var/www/jdoe et /var/www/jdoe2.
- Définit les permissions appropriées pour chaque répertoire.
Enregistrez et quittez.
Les tâches sont le travail réel qu'Ansible effectue. Chaque tâche utilise un module Ansible pour accomplir quelque chose de spécifique.
nano roles/apache.developer_configs/tasks/main.yml
Ajoutez le contenu suivant et comprenons chaque tâche :
---
## Tâche 1 : Créer des comptes utilisateur pour chaque développeur
- name: Create developer user accounts
ansible.builtin.user: ## Utilise le module 'user'
name: "{{ item.username }}" ## Crée l'utilisateur avec ce nom
state: present ## Assure que l'utilisateur existe
loop: "{{ web_developers }}" ## Fait cela pour chaque développeur dans la liste
## Tâche 2 : Créer des répertoires web pour chaque développeur
- name: Create developer web root directories
ansible.builtin.file: ## Utilise le module 'file'
path: "/var/www/{{ item.username }}" ## Crée ce répertoire
state: directory ## Assure que c'est un répertoire
owner: "{{ item.username }}" ## Définit le propriétaire
group: "{{ item.username }}" ## Définit le groupe
mode: "0755" ## Définit les permissions (rwxr-xr-x)
loop: "{{ web_developers }}"
## Tâche 3 : Créer une page web d'exemple pour chaque développeur
- name: Create a sample index.html for each developer
ansible.builtin.copy: ## Utilise le module 'copy'
content: "Welcome to {{ item.username }}'s dev space\n" ## Contenu du fichier
dest: "/var/www/{{ item.username }}/index.html" ## Où placer le fichier
owner: "{{ item.username }}" ## Propriétaire du fichier
group: "{{ item.username }}" ## Groupe du fichier
mode: "0644" ## Permissions du fichier (rw-r--r--)
loop: "{{ web_developers }}"
## Tâche 4 : Déployer le fichier de configuration Apache
- name: Deploy developer apache configs
ansible.builtin.template: ## Utilise le module 'template'
src: developer.conf.j2 ## Fichier template source
dest: /etc/httpd/conf.d/developer.conf ## Destination sur le serveur
mode: "0644" ## Permissions du fichier
notify: restart apache ## Déclenche le handler de redémarrage lorsqu'il y a un changement
Comprendre les concepts clés :
loop : Répète la tâche pour chaque élément de la liste.
{{ item.username }} : Fait référence au nom d'utilisateur de l'élément actuel dans la boucle.
notify: restart apache : Lorsque cette tâche apporte des modifications, elle déclenchera un handler nommé "restart apache".
- Permissions de fichier :
0755 signifie que le propriétaire peut lire/écrire/exécuter, les autres peuvent lire/exécuter ; 0644 signifie que le propriétaire peut lire/écrire, les autres peuvent seulement lire.
Enregistrez et quittez.
Les handlers sont des tâches spéciales qui ne s'exécutent que lorsqu'elles sont notifiées par d'autres tâches. Ils sont généralement utilisés pour des actions comme le redémarrage des services.
nano roles/apache.developer_configs/handlers/main.yml
Ajoutez le contenu suivant :
---
- name: restart apache ## Ce nom doit correspondre à l'instruction notify:
ansible.builtin.service: ## Utilise le module 'service'
name: httpd ## Le nom du service (Apache est appelé 'httpd' sur RHEL)
state: restarted ## Redémarre le service
Pourquoi utiliser des handlers ?
- Efficacité : Le service ne redémarre que si la configuration a réellement changé.
- Ordre : Toutes les tâches s'exécutent d'abord, puis tous les handlers s'exécutent à la fin.
- Idempotence : Plusieurs tâches peuvent notifier le même handler, mais il ne s'exécute qu'une seule fois.
Enregistrez et quittez.
Enfin, nous devons indiquer à Ansible que notre rôle personnalisé dépend du rôle infra.apache que nous avons installé précédemment.
nano roles/apache.developer_configs/meta/main.yml
Remplacez le contenu du fichier par :
---
dependencies:
- role: infra.apache ## Ce rôle doit s'exécuter avant notre rôle personnalisé
Ce que cela fait :
- Lorsque Ansible exécute
apache.developer_configs, il exécutera automatiquement infra.apache en premier.
- Cela garantit qu'Apache est installé et configuré avant que nous ajoutions nos configurations personnalisées.
- Les dépendances s'exécutent dans l'ordre où elles sont listées.
Enregistrez et quittez.
4. Assembler et exécuter le playbook principal
Un playbook est comme une recette qui indique à Ansible quoi faire et dans quel ordre. Notre playbook va :
- Configurer les paramètres SELinux (pre_tasks).
- Exécuter nos rôles (qui incluent la chaîne de dépendances).
Créez le fichier du playbook principal :
nano web_dev_server.yml
Ajoutez le contenu suivant avec des explications détaillées :
---
- name: Configure Dev Web Server ## Nom du playbook
hosts: localhost ## Exécuter sur localhost
pre_tasks: ## Tâches qui s'exécutent avant les rôles
## Tâche 1 : Configurer le mode SELinux
- name: Set SELinux to enforcing mode
ansible.posix.selinux: ## Module de la collection ansible.posix
policy: targeted ## Utiliser la politique SELinux 'targeted'
state: "{{ selinux_state }}" ## Utiliser la variable que nous avons définie
when: selinux_state is defined ## S'exécuter uniquement si la variable existe
## Tâche 2 : Configurer les ports SELinux
- name: Configure SELinux ports for Apache
community.general.seport: ## Module de la collection community.general
ports: "{{ item.ports }}" ## Numéro de port
proto: "{{ item.proto }}" ## Protocole (tcp)
setype: "{{ item.setype }}" ## Type SELinux (http_port_t)
state: "{{ item.state }}" ## present ou absent
loop: "{{ selinux_ports }}" ## Boucler à travers notre liste de ports
when: selinux_ports is defined ## S'exécuter uniquement si la variable existe
roles: ## Rôles à exécuter
- apache.developer_configs ## Notre rôle personnalisé (qui déclenchera infra.apache)
Comprendre l'ordre d'exécution :
pre_tasks : La configuration SELinux s'exécute en premier.
roles : Les dépendances des rôles s'exécutent (infra.apache), puis notre rôle personnalisé.
handlers : Tous les handlers notifiés s'exécutent en dernier.
Pourquoi cet ordre est important :
- SELinux doit être configuré avant qu'Apache n'essaie de se lier à des ports personnalisés.
- Apache doit être installé avant que nous puissions configurer des virtual hosts.
- Les redémarrages de service se produisent après la fin de toute la configuration.
Enregistrez et quittez.
Vous êtes maintenant prêt à exécuter votre automatisation complète :
ansible-playbook web_dev_server.yml
Le playbook s'exécutera et vous verrez une sortie détaillée. Voici ce à quoi vous attendre (par exemple) :
PLAY [Configure Dev Web Server] *************************************************
TASK [Gathering Facts] **********************************************************
ok: [localhost] ## Ansible collecte des informations système
TASK [Set SELinux to enforcing mode] *******************************************
changed: [localhost] ## Le mode SELinux a été modifié
TASK [Configure SELinux ports for Apache] **************************************
changed: [localhost] => (item={'ports': '9081', 'proto': 'tcp', 'setype': 'http_port_t', 'state': 'present'})
changed: [localhost] => (item={'ports': '9082', 'proto': 'tcp', 'setype': 'http_port_t', 'state': 'present'})
TASK [infra.apache : Ensure Apache is installed.] *******************************
changed: [localhost] ## Le paquet Apache a été installé
TASK [apache.developer_configs : Create developer user accounts] ****************
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})
TASK [apache.developer_configs : Create developer web root directories] *********
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})
TASK [apache.developer_configs : Create a sample index.html for each developer] *
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})
TASK [apache.developer_configs : Deploy developer apache configs] ***************
changed: [localhost] ## Le fichier de configuration a été créé
RUNNING HANDLER [apache.developer_configs : restart apache] *********************
changed: [localhost] ## Apache a été redémarré
PLAY RECAP **********************************************************************
localhost : ok=17 changed=12 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
Vous avez assemblé et exécuté avec succès un playbook complexe qui combine plusieurs rôles provenant de différentes sources pour créer un environnement de développement web complet !