Regrouper une automatisation réutilisable dans un rôle

AnsibleBeginner
Pratiquer maintenant

Introduction

Les rôles regroupent une unité d'automatisation fonctionnelle afin que les consommateurs puissent fournir des données sans dupliquer l'implémentation. Vous créerez un rôle avec des valeurs par défaut publiques, produirez des pages propres aux hôtes, conserverez la validation de configuration et le rechargement dans le rôle et le réutiliserez dans deux groupes d'inventaire. Les fichiers réellement gérés et les réponses HTTP vérifieront que le rôle est effectivement invoqué.

Créer et invoquer un rôle avec des valeurs par défaut

Dans cette étape, vous déplacerez l'automatisation du site dans un rôle et l'invoquerez au moyen d'un court playbook avec des entrées par défaut réutilisables.

Un rôle regroupe les tâches associées, les variables par défaut, les modèles et les handlers dans un répertoire standard. Son tasks/main.yml est le point d'entrée des tâches ; defaults/main.yml fournit des valeurs de faible priorité que les consommateurs peuvent remplacer. Les sources de modèles vont dans templates, et handlers/main.yml contiendra ensuite les actions de service déclenchées par les changements.

L'inventaire préparé place déjà web1 dans canary et web2 dans stable, sous le groupe parent sites. Nginx est installé comme prérequis. Examinez les groupes :

cd /home/labex/project
ansible-inventory --graph

Créez les répertoires du rôle avec mkdir -p. Plusieurs arguments de chemin créent chaque répertoire nommé :

mkdir -p roles/managed_site/tasks roles/managed_site/defaults roles/managed_site/templates roles/managed_site/handlers

Préfixez les variables publiques du rôle avec site_ pour rendre leur but clair. Commencez par des valeurs par défaut communes utilisables par tout consommateur :

cat > roles/managed_site/defaults/main.yml <<'YAML'
site_environment: training
site_port: 8080
site_maintenance: false
YAML

Le modèle de page utilise l'entrée du rôle avec le nom de chaque cible et sa distribution collectée :

cat > roles/managed_site/templates/page.txt.j2 <<'JINJA'
host={{ inventory_hostname }}
environment={{ site_environment }}
distribution={{ ansible_facts.distribution }}
JINJA

Créez le point d'entrée des tâches du rôle. Dans un rôle, src: page.txt.j2 est résolu dans le répertoire templates de ce rôle ; la destination reste un chemin géré absolu :

cat > roles/managed_site/tasks/main.yml <<'YAML'
- name: Prepare the role-managed website directory
  ansible.builtin.file:
    path: /var/www/role-site
    state: directory
    owner: root
    group: root
    mode: "0755"

- name: Render the role-managed page
  ansible.builtin.template:
    src: page.txt.j2
    dest: /var/www/role-site/index.html
    owner: root
    group: root
    mode: "0644"
YAML

Invoquez le rôle avec le mot-clé roles. Le play englobant sélectionne les cibles, collecte les faits et demande become ; le rôle fournit les tâches réutilisables :

cat > site.yml <<'YAML'
- name: Apply the managed site role with defaults
  hosts: sites
  gather_facts: true
  become: true
  roles:
    - managed_site
YAML

Validez et exécutez le rôle via son playbook consommateur :

ansible-playbook site.yml --syntax-check
ansible-playbook site.yml

Examinez les pages réellement créées par le rôle :

ansible sites -m ansible.builtin.command -a 'cat /var/www/role-site/index.html'

Les deux doivent montrer environment=training issu de la valeur par défaut, avec leurs propres noms d'hôte et distribution=Ubuntu. Créer simplement les répertoires du rôle n'exécuterait pas celui-ci et ne créerait pas ces fichiers gérés.

Conserver les modèles et les handlers dans le rôle réutilisable

Dans cette étape, vous ferez configurer et exécuter le site par le rôle, avec validation du candidat et son propre handler de rechargement.

Placez le modèle nginx complet à côté de la source de page. Il utilise les entrées site_ du rôle, le filtre upper déjà pratiqué et une branche booléenne :

cat > roles/managed_site/templates/nginx.conf.j2 <<'JINJA'
events {}
http {
    server_tokens off;
    server {
        listen {{ site_port }};
        root /var/www/role-site;
        index index.html;
        add_header X-Environment "{{ site_environment | upper }}" always;
{% if site_maintenance %}
        add_header X-Maintenance "enabled" always;
{% else %}
        add_header X-Maintenance "disabled" always;
{% endif %}
    }
}
JINJA

Ajoutez des tâches au rôle pour valider la configuration produite avant remplacement et maintenir explicitement nginx démarré. La configuration modifiée notifie le handler nommé du rôle :

cat >> roles/managed_site/tasks/main.yml <<'YAML'

- name: Render and validate the role-managed nginx configuration
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: "0644"
    validate: /usr/sbin/nginx -t -c %s
  notify: Reload managed site

- name: Keep the role-managed service running
  ansible.builtin.service:
    name: nginx
    state: started
YAML

Écrivez le handler dans le point d'entrée des handlers du rôle au lieu de le dupliquer dans chaque playbook consommateur :

cat > roles/managed_site/handlers/main.yml <<'YAML'
- name: Reload managed site
  ansible.builtin.service:
    name: nginx
    state: reloaded
YAML

Exécutez le playbook consommateur inchangé. Le rôle fournit maintenant son comportement de déploiement complet :

ansible-playbook site.yml

Les deux hôtes doivent démarrer leur propre site sur le port par défaut 8080. Examinez chaque cible via son propre point d'accès de bouclage :

ansible sites -m ansible.builtin.command -a 'curl --fail --silent --show-error -i http://127.0.0.1:8080/'

Chaque corps doit identifier son propre hôte et environment=training. Les en-têtes doivent inclure X-Environment: TRAINING et X-Maintenance: disabled. La sortie provient de services en cours configurés par le rôle, plutôt que d'une démonstration uniquement sur le contrôleur.

Réutiliser le même rôle avec des remplacements par variables de groupe

Dans cette étape, vous appliquerez le même rôle à deux contextes de groupe sans modifier ses valeurs par défaut ni ses fichiers de tâches réutilisables.

Les valeurs par défaut des rôles ont volontairement une faible priorité. Les variables de groupe d'inventaire peuvent remplacer ces entrées publiques tout en conservant la même implémentation. Gardez defaults/main.yml inchangé et créez les données consommatrices de chaque groupe :

cat > group_vars/canary.yml <<'YAML'
site_environment: development
site_port: 8081
site_maintenance: true
YAML
cat > group_vars/stable.yml <<'YAML'
site_environment: production
site_port: 8082
site_maintenance: false
YAML

Remplacez le playbook consommateur par deux plays invoquant le même rôle managed_site. Chaque groupe reçoit ses propres entrées résolues. Ne dupliquez pas le répertoire du rôle pour chaque environnement :

cat > site.yml <<'YAML'
- name: Apply the shared role to canary
  hosts: canary
  gather_facts: true
  become: true
  roles:
    - managed_site

- name: Apply the shared role to stable
  hosts: stable
  gather_facts: true
  become: true
  roles:
    - managed_site
YAML

Validez et appliquez les deux contextes :

ansible-playbook site.yml --syntax-check
ansible-playbook site.yml

Les deux environnements doivent charger leur configuration modifiée par le handler interne au rôle. Examinez les véritables points d'accès sur leurs nouveaux ports configurés :

ansible canary -m ansible.builtin.command -a 'curl --fail --silent --show-error -i http://127.0.0.1:8081/'
ansible stable -m ansible.builtin.command -a 'curl --fail --silent --show-error -i http://127.0.0.1:8082/'

Canary doit identifier web1 et development, avec les en-têtes DEVELOPMENT/enabled. Stable doit identifier web2 et production, avec PRODUCTION/disabled. Ces différences proviennent des entrées de groupe, tandis qu'un rôle commun unique possède toujours les valeurs par défaut, les tâches, les modèles et les handlers.

Répétez le même playbook consommateur :

ansible-playbook site.yml

Les deux lignes du récapitulatif doivent indiquer changed=0, unreachable=0 et failed=0, sans handler programmé. Un rôle réutilisable doit être invoqué et produire un état géré convergé correct ; une simple arborescence de répertoires n'est pas un déploiement.

Résumé

Vous avez organisé les valeurs par défaut, les tâches, les modèles et les handlers dans un rôle unique invoqué. Des valeurs par défaut de faible priorité ont permis les remplacements des consommateurs, et deux groupes d'inventaire ont réutilisé la même implémentation pour produire des services réels distincts. La validation du candidat, les rechargements déclenchés par changement et la répétition inchangée sont restés intégrés à l'unité réutilisable.