Moment informel durant lequel on exprime en peu de mots comment on se sent et si on a une attente forte pour la réunion. Ce n'est pas un moment de discussion mais d'expression individuelle et ce n'est pas obligatoire
Si l'une ou l'autre personne exprime une attente forte, merci de vous en occuper en priorité ou de la noter dans le hub ou dans un point approprié.
On a vu comment créer des VM via Vagrant, comment exécuter des commandes ansible sur ces VMs. Et on a joué avec l'inventaire, notamment on a vu qu'on pouvait grouper des VMs en groupes et sous-groupes, et qu'on pouvait y associer des variables. Les variables pouvant ainsi être séparées de l'inventaire.
À la fin, on avait quelque chose comme:
.venv/ inventories/ - group_vars/ - all.yml - debian.yml - host_vars/ - debian1.yml - ubuntu1.yml - hosts.ini ansible.cfg Vagrantfile
On commence donc par réactiver le virtualenv de python:
source .venv/bin/activate
Note: Pour quitter un virtualenv, il suffit d'exécuter la commande deactivate
, c'est plus simple que de quitter bash.
Donc normalement, on a un préfixe (.venv)
avant le prompt bash. Si on n'est pas sûr, on peut vérifier d'où vient pip: pip --version
À présent, on va créer un fichier playbook.yml, qui va exécuter différentes tâches.
Playbook viendrait du rugby. Quand les joueurs·euses y jouent, ils ont un livret de jeu sur la manière dont l'équipe va se comporter. Ici, c'est pareil, sauf qu'on ne joue pas au rugby.
On peut le voir plutôt comme un livret de cuisine. On a une liste de tâche qui s'appliquent à un ou un ensemble d'hôtes.
On peut avoir des variables spécifiques à un inventaire mais aussi à un playbook.
La structure d'un playbook ressemble à ceci (cf. https://supports.uptime-formation.fr/06-ansible/cours2/#structure-dun-playbook) :
Un playbook commence par un tiret. En Yaml, ça indique qu'on a à faire à une liste. Ici c'est une liste de tâches qui seront effectuées sur des hosts.
Puis une liste de hosts (ça peut en être un seul host ou un groupe de hosts). En général, on configure notre inventaire pour avoir un seul groupe pour ce playbook.
On définit ensuite les variables. On peut avoir des fichiers séparés avec les variables ou les déclarer directement. On peut aussi utiliser les dossiers group_vars
et host_vars
qui sont dans le même répertoire que le fichier de playbook. C'est le même principe que l'inventaire.
les pré-taches → s'exécutent avant les autres tâches.
Puis on a les rôles et enfin les tâches.
Avoir les pré-tâches est utile, par exemple si on veut installer python avant d'appliquer les tâches d'un rôle.
Puis les “handlers” sont déclenchés à la fin du playbook. Ca peut par exemple être de recharger un service comme nginx dont on aurait changé la configuration.
Ensuite, on peut avoir dans le même fichier, un second playbook (commençant par - name).
On créé un fichier playbook1.yml
dans un dossier ./playbooks
.
- name: Mon playbook hosts: all tasks: - ping:
Quand on ne sait pas comment fonctionne tel module, ou même quel module choisir, on peut se référer à la doc ansible qui est très bien faite. Par ex: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/ping_module.html
Chaque module renvoie des valeurs. Dans la doc, cela indique les valeurs par défaut.
On va reprendre notre lab vagrant qu'on avait fait, avec quelques modifications.
Tout d'abord, on définit la variable suivante pour dire à vagrant d'utiliser le provider libvirt par défaut. :
export VAGRANT_DEFAULT_PROVIDER=libvirt
On peut persister ceci en rajoutant la commande dans notre ~/.bashrc
.
À chaque fois qu'on ouvre un terminal, vagrant saura qu'on veut utiliser libvirt comme provider par défaut.
Ensuite, on modifie le Vagrantfile pour avoir ceci:
Vagrant.configure("2") do |config| config.ssh.insert_key = false # to use the global unsecure key instead of one insecure key per VM config.vm.define :ubuntu1 do |debian1| debian1.vm.box = "debian/bullseye64" debian1.vm.hostname = "debian1" debian1.vm.network :private_network, ip: "10.10.10.11" end config.vm.define :debian1 do |debian2| debian2.vm.box = "debian/bullseye64" debian2.vm.hostname = "debian2" debian2.vm.network :private_network, ip: "10.10.10.12" end config.vm.synced_folder "./", "/vagrant", disabled: true config.vm.provider "libvirt" do |libvirt| # Enable forwarding of forwarded_port with id 'ssh'. libvirt.forward_ssh_port = true # Customize the amount of memory on the VM: libvirt.memory = "1024" end end
On a rajouté une IP fixe à nos deux machines, ce sera plus simple pour la suite de l'atelier. On dit également à vagrant d'utiliser la même clé SSH pour toutes les VMs. Même si ce n'est pas sécurisé, on s'en fiche parce que c'est juste un labo
On aura deux interfaces réseau sur les machines.
La clé se trouve dans ~/.vagrant.d/insecure_private_key
, on peut l'ajouter à notre ssh-agent pour être tranquille.
Et enfin, on modifie l'inventaire inventories/hosts.ini
:
[debian] debian1 debian2
On supprime tout ce qui concerne ubuntu.
Dans les variables, on indique les IPs :
- dans le fichier inventories/hostvars/debian1.yml, on met ansible_host: 10.10.10.11
- dans le fichier inventories/hostvars/debian2.yml, on met ansible_host: 10.10.10.12
On peut tester la connexion ssh:
ansible -m ping all
Si on a des soucis avec le fingerprint de la clé ssh des VMs, on peut rajouter ceci dans ansible.cfg
:
[defaults] ... host_key_checking = false
C'est pas sécurisé, mais à nouveau c'est juste un labo…
Pour lancer notre playbook :
ansible-playbook playbooks/playbook1.yml
Différentes tâches s'affichent :
PLAY [Mon playbook] ************************************************************************** TASK [Gathering Facts] *********************************************************************** ok: [debian1] ok: [debian2] TASK [ping] ********************************************************************************** ok: [debian1] ok: [debian2] PLAY RECAP *********************************************************************************** debian1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 debian2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Dans la première tâche PLAY, Ansible indique le nom du playbook en cours.
Dans la seconde, il indique la liste des tâches, à commencer par la tâche Gathering Facts. Cette tâche n'était pas définie mais a été lancée. Si on ne dit rien à Ansible, il va chercher les facts des VM. Il récupère notamment l'OS de la VM car ça lui sera utile.
On peut désactiver ce comportement:
- name: Mon playbook gather_facts: false ...
Dans TASK, il effectue la tâche qu'on a définie. Ici il fait un ping, comme on le lui a demandé.
Dans PLAY RECAP, il fait le récapitulatif de ce qui a fait, modifié sur le serveur, et les éventuelles erreurs.
On va installer nginx, et puis on débuggera à partir de là. On rajoute cette tâche à la place de notre ping.
tasks: - name: Installation de nginx apt: name: nginx state: present
Attention à l'indentation ! Il faut faire une indentation de deux entre les “dictionnaires”. Le premier tiret est une liste de tâche qui se trouve dans la liste des playbooks. Pour une tâche, on a un premier dictionnaire qui indique le nom de la tâche et le module invoqué. Et on a un sous-dictionnaire qui représente les paramètres du module.
Ici, on installe le paquet nginx via le module apt et on demande à ce que le paquet soit présent (au lieu de absent
ou latest
)
Ici, le lancement du playbook échoue :
ansible-playbook playbooks/playbook1.yml PLAY [Mon playbook] ********************************************************************************************************************************************************************************* TASK [Installation de nginx] ************************************************************************************************************************************************************************ fatal: [debian2]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "msg": "No package matching 'nginx' is available"} fatal: [debian1]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "msg": "No package matching 'nginx' is available"} PLAY RECAP ****************************************************************************************************************************************************************************************** debian1 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0 debian2 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
La raison est liée au fait qu'on n'a pas fait d'apt update avant.
Il suffit de rajouter le paramètre suivant à la tâche:
... state: present update_cache: true
Mais cela échoue encore :
ansible-playbook playbooks/playbook1.yml PLAY [Mon playbook] ********************************************************************************************************************************************************************************* TASK [Installation de nginx] ************************************************************************************************************************************************************************ fatal: [debian2]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "msg": "Failed to lock apt for exclusive operation: Failed to lock directory /var/lib/apt/lists/: E:Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)"} fatal: [debian1]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "msg": "Failed to lock apt for exclusive operation: Failed to lock directory /var/lib/apt/lists/: E:Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)"} PLAY RECAP ****************************************************************************************************************************************************************************************** debian1 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0 debian2 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Pour débugguer, on peut utiliser comme vu la dernière fois l'argument -vvv :
The full traceback is: File "/tmp/ansible_apt_payload_mqokgpgd/ansible_apt_payload.zip/ansible/modules/apt.py", line 1336, in main File "/usr/lib/python3/dist-packages/apt/cache.py", line 551, in update with _WrappedLock(apt_pkg.config.find_dir("Dir::State::Lists")): File "/usr/lib/python3/dist-packages/apt/cache.py", line 74, in __enter__ raise LockFailedException(("Failed to lock directory %s: %s") % fatal: [debian1]: FAILED! => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "invocation": { "module_args": { "allow_change_held_packages": false, "allow_downgrade": false, "allow_unauthenticated": false, "autoclean": false, "autoremove": false, "cache_valid_time": 0, "clean": false, "deb": null, "default_release": null, "dpkg_options": "force-confdef,force-confold", "fail_on_autoremove": false, "force": false, "force_apt_get": false, "install_recommends": null, "lock_timeout": 60, "name": "nginx", "only_upgrade": false, "package": [ "nginx" ], "policy_rc_d": null, "purge": false, "state": "present", "update_cache": true, "update_cache_retries": 5, "update_cache_retry_max_delay": 12, "upgrade": null } }, "msg": "Failed to lock apt for exclusive operation: Failed to lock directory /var/lib/apt/lists/: E:Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)" }
Ici, c'est plus lisible car tout n'est pas regroupé sur une seule ligne. On retrouve notre message mais on a tout le détail de la manière dont le playbook a été appliqué.
Une autre façon de debugguer, c'est d'utiliser… la tâche debug !
- debug: msg: "hello"
On peut faire dire à la tache débug des messages par défaut.
Ici, on voit apparaître la tâche debug :
TASK [debug] **************************************************************************************************************************************************************************************** task path: /home/celo/Documents/Ateliers-Ansible/Ansible-Test/playbooks/playbook1.yml:6 ok: [debian1] => { "msg": "hello" } ok: [debian2] => { "msg": "hello" }
On peut aussi lui dire d'afficher les variables.
- name: "Installation de nginx" nginx: name: nginx state: present update_cache: true register: nginx_result failed_when: false - debug: var: nginx_result # équivalent à msg: "{{ nginx_result }}"
register
et failed_when
sont ici des paramètres de la tâche.
Les tâches ont toujours un résultat. Le débug montre bien cela, on affiche le résultat de la commande.
On peut mettre ce résultat dans une variable, ce qui est pratique quand on veut vérifier par exemple qu'un fichier existe. Un module d'Ansible fait cela, et on peut stocker ça pour retrouver si le fichier existait ou pas.
Dans failed_when: false, on force la tâche à ne pas échouer de manière à pouvoir récupérer quelque chose.
Et cette fois, on place la tâche debug après l'installation de nginx, car elle va afficher le résultat du module.
Ici, on constate que la tâche Installation de nginx n'a pas échoué (comme on lui a dit que ça n'échouait jamais), mais on retrouve les infos de débuggage dans un format un peu plus digeste que lorsque ça échoue :
TASK [Installation de nginx] ************************************************************************************************************************************************************************ ok: [debian2] ok: [debian1] TASK [debug] **************************************************************************************************************************************************************************************** ok: [debian1] => { "nginx_result": { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "failed": false, "failed_when_result": false, "msg": "Failed to lock apt for exclusive operation: Failed to lock directory /var/lib/apt/lists/: E:Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)" } } ok: [debian2] => { "nginx_result": { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "failed": false, "failed_when_result": false, "msg": "Failed to lock apt for exclusive operation: Failed to lock directory /var/lib/apt/lists/: E:Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)" } }
On peut dire à Ansible de voir si le playbook se lance mais sans faire de changements, cela se fait avec l'option --check
. On appelle ça un “dry run”.
On remet dans notre fichier (on enlève les debug):
tasks: - name: Installation de nginx apt: name: nginx state: present update_cache: true
Dans Ansible, par défaut, on n'est pas root. Il faut lui définir qu'on veut utiliser sudo. On peut le faire avec l'argument –become.
On peut aussi ajouter become: true dans le playbook au même niveau que les hosts.
hosts: all become: true ...
On voit que la tâche est passée en changée, donc ça a marché :
ansible-playbook playbooks/playbook1.yml --become PLAY [Mon playbook] ********************************************************************************************************************************************************************************* TASK [Installation de nginx] ************************************************************************************************************************************************************************ changed: [debian1] changed: [debian2] PLAY RECAP ****************************************************************************************************************************************************************************************** debian1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 debian2 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Si on relance la tâche, on voit que le playbook va plus vite, et ne change rien
Pour une tâche donnée, on peut rajouter un paramètre pour lui dire d'exécuter la tâche en tant qu'un utilisateur, par ex:
apt: name: nginx state: present update_cache: true become_user: vagrant
Avec ce paramètre, on constate que le playbook échoue à nouveau avec l'erreur E:Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
Concrètement, l'idée est qu'on ne doit pas avoir peur de lancer à nouveau le playbook. L'idée est que ça ne change rien dans le système si la valeur a déjà été changée.
Si nginx est déjà installé, il ne le réinstalle pas.
Si on a un restart, est-ce que ce sera idempotent ?
- name: Restart nginx systemd: name: nginx state: restarted
On retire aussi le become_user: vagrant
de tout à l'heure.
Ici, lorsqu'on applique le playbook, il redémarre nginx. Lorsqu'on relance nginx, il fait pareil… ce n'est pas idempotent ! Si on a des services web qui tournent sur le serveur, ils sont tous dans les choux.
On utilise les handlers.
Ceux-si sont utilisés par ex quand on modifie une config. Le handleur n'est déclanché que s'il est notifié que quelque chose a changé dans la config. On ajoute dans les paramètres de la tâche un notify.
Les handlers sont exécutés tout à la fin du playbook, lorsque toutes les tâches ont réussi. Attention, s'il y a une tâche qui échoue, par défaut les handlers ne vont pas être exécutés. Il y a des paramètres dans ansible pour modifier ce comportement.
On va créer un fichier de config pour nginx, que l'on place dans ./playbooks/files/nginx.conf
:
server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; server_name _; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } }
Par défaut, Ansible va chercher les fichiers de configuration dans playbooks/files/.
On pourrait utiliser un sous-dossier nginx dans files.
On va utiliser le module copy pour mettre le fichier de configuration sur les VMs:
tasks: ... - name: Configuration de nginx copy: src: nginx.conf dest: /etc/nginx/sites-available/default notify: Restart nginx handlers: - name: Restart nginx systemd: name: nginx state: restarted
On peut voir qu'on ne spécifie pas le dossier files
puisque ansible va chercher directement dans ce dossier. On notifie le handler quand la config a changé. Et on a défini un handler pour redémarrer nginx. Ansible va se baser sur le nom du handler pour savoir lequel déclencher.
En éxécutant le playbook avec l'argument –diff, on peut voir ce qu'il change dans le fichier de config.
On voit qu'après une première exécution du playbook, le fichier de config est modifié et le handler se déclenche. Si on relance une seconde fois, le fichier n'est plus modifié, et le handler ne se déclenche pas.
On a donc un playbook idempotent \o/
Par générer, on entend avoir des variables dans la config.
Si par exemple on veut définir le port d'écoute de nginx, on peut l'utiliser dans une variable, et le mettre dans l'inventer.
On appelle ça un template… et ça va se trouver dans un dossier playbook/templates.
On déplace notre fichier nginx.conf dans ce nouveau dossier. On renomme aussi le fichier en nginx.conf.j2
En haut du fichier, on rajoute des accolades avec ansiblemanaged. les doubles accolades montrent que c'est une variables. La variable ansiblemanaged est une variable d'ansible qui indique que ansible se charge de la gestion de ce fichier et que toute modificaiton sera écrasée au prochain lancement du playbook.
Le mot-clé comment
indique de commenter le résultat de ansible manage pour l'ajouter un commentaire. C'est ce qu'on appelle un filtre dans la syntaxe jinja2. Il permet de manipuler le contenu d'une variable. Ici, ce filtre (ou fonction) va juste modifier le contenu de la variable pour mettre des #
devant chaque ligne.
{{ ansible_managed | comment }} server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; server_name _; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } }
On modifie notre playbook:
tasks: ... - name: Configuration de nginx template: src: nginx.conf.j2 dest: /etc/nginx/sites-available/default.conf notify: Restart nginx
On remplace juste le module copy par le module template. Et bien entendu, on renomme la source en nginx.conf.j2
Si le handler échoue pour une raison ou une autre, il ne va pas ce déclencher à nouveau puisque la config n'est plus modifiée. Pour éviter ça, on va tromper ansible en rajoutant une nouvelle ligne par exemple dans le fichier de config, ce qui va forcer la tâche à être modifiée.
Sur la VM, on peut vérifier que le fichier porte bien l'indication qu'il est géré par ansible :
# # Ansible managed # server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; server_name _; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } }
À titre d'exercice, on pourrait s'amuser à définir une variable domain
et remplacer la ligne server_name _;
pour que l'utilisateur puisse définir le nom de domaine qu'il veut.
Pour le fichier de configuration, on peut choisir différent paramètres : l'utilisateur propriétaire, le groupe, les permissions…
- name: Configuration de nginx template: src: nginx.conf.j2 dest: /etc/nginx/sites-available/default owner: root group: root mode: "0644" # équivalent à "u=rw,g=r,o=r" notify: Restart nginx
Ici, on met root, c'est pour la démo. Mais c'est de toute façon une bonne pratique d'indiquer root et les permissions. Le linter d'ansible le conseille d'ailleurs.
Ceci foncitonne également pour le module copy.
--diff
indique aussi les changements appliqués sur les fichiers.
On peut aussi demander à Ansible de vérifier le fichier (uniquement sur les template cette fois-ci) avec une commande :
- name: Configuration de nginx template: src: nginx.conf.j2 dest: /etc/nginx/sites-available/default owner: root group: root mode: "0644" # équivalent à "u=rw,g=r,o=r" validate: nginx -t -c %s notify: Restart nginx
Le %s représente le fichier de destination. Ce paramètre est obligatoire, sinon ansible va râler.
Avec cette option, si on a fait une erreur dans le fichier de config, le playbook échoue et on évite de casser le serveur. Avec l'option -vvv, on peut voir le message :
"msg": "failed to validate", "stderr": "nginx: [emerg] \"server\" directive is not allowed here in /home/vagrant/.ansible/tmp/ansible-tmp-1664032024.215524-28788-236571956266121/source:5\nnginx: configuration file /home/vagrant/.ansible/tmp/ansible-tmp-1664032024.215524-28788-236571956266121/source test failed\n", "stderr_lines": [ "nginx: [emerg] \"server\" directive is not allowed here in /home/vagrant/.ansible/tmp/ansible-tmp-1664032024.215524-28788-236571956266121/source:5", "nginx: configuration file /home/vagrant/.ansible/tmp/ansible-tmp-1664032024.215524-28788-236571956266121/source test failed" ],
jinja2 est un moteur de template très utilisé dans python.
On a vu la première syntaxe avec les variables ({{ ma_variable }}
).
On peut aussi mettre des conditions :
{% if temperature >= 19 %} blablabla {{ ma_variable }} {% else %} bloubloubloub {% endif %}
On peut aussi faire des boucles:
{% for temperature in temperatures %} {% if loop.first %}début{% endif %} {{ loop.index }} {{ temperature }} {% if loop.last %}fini{% endif %} {% endfor %}
Les variables loop.* sont propres aux boucles. La variable loop
est un dictionnaire, et on accède à ses éléments via le .
. On peut aussi faire loop["index"]
, c'est équivalent.
Si on a une variable temperatures
qui contient [19, 20, 21]
, cela donnera:
début 0 19 1 20 2 21 fini
On peut directement remplacer temperatures
dans la boucle par une liste comme [19, 20, 21]
.
Il y a des filtres qui permettent de manipuler les variables, et on en a une liste ici qui couvre pas mal de cas d'usage : https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html
Et aussi la doc de jinja2 pour les filtres : https://jinja.palletsprojects.com/en/3.0.x/templates/#builtin-filters
Une tâche conditionnelle s'applique sous certaines conditions. Dans le cours d'uptime formation, c'est placé au même niveau que les handler. Donc pour avoir un playbook idempotent, on peut utiliser en fait les handler ou les tâches conditionnelles.
En général, on utilise le handler, mais dans certains cas, ça peut être utile d'utiliser une tâche conditionnelle. Ca s'utilise avec le paramètre when.
On peut par exemple l'utiliser pour choisir le gestionnaire de paquet en fonction de l'OS. Ici, on a utilisé apt pour debian, mais ça ne conviendrait pas pour du OpenSuse ou Redhat.
Il y a une liste de variables magiques créées par Ansible pour nous faciliter la vie : https://docs.ansible.com/ansible/latest/user_guide/playbooks_vars_facts.html#vars-and-facts
La variable qui nous intéresse est ansible_os_family
qui indique si on est plutôt dans la famille Redhat, Debian, OpenSuse, etc.
- name: Installation de nginx (Debian) apt: name: nginx state: present update_cache: true when: ansible_os_family == 'Debian' - name: Installation de nginx (Redhat) yum: name: nginx state: present when: ansible_os_family == 'RedHat'
Ici, il ne faut pas d'accolade parce que when présuppose qu'on utilise des variables. Ici si l'OS n'était pas un Debian, la tâche serait skipée.
Pour cela, il faut bien sûr que les Gather Facts soient activés.
On voit que la tâche installation de nginx (RedHat), est skippée :
TASK [Installation de nginx (RedHat)] *************************************************************************************************************************************************************** skipping: [debian1] skipping: [debian2]
Après, l'idée d'Ansible c'est d'être le plus générique possible. On peut se dire qu'on aimerait avoir un truc simple qui fonctionne directement pour les RedHat et les Debian.
On peut utiliser le module package
qui est générique, mais possède moins de fonctionnalités spécifiques à apt
ou yum
, mais qui fait le taff la plupart du temps:
- name: Installation de nginx package: name: nginx state: present update_cache: true
Et pareil pour systemd, on peut utiliser le module service
qui est plus générique:
- name: Restart nginx service: name: nginx state: restarted
Bon, on a une erreur avec le validate, et comme on arrive à la fin de l'atelier, on va juste commenter la ligne.
À titre d'exercice, on pourrait créer une tâche qui s'assure que nginx est dans l'état started
après l'installation. Comme ça, si jamais la config a fait crasher nginx, on le verra au lancement suivant, puisque la tâche apparaîtra comme modifiée.
On peut créer des boucles dans les playbook.
Si on a une boucle pour configurer nginx sur différents domaines, on utilise une variable domains qu'on utilise dans loop. Les variables, comme on l'a vu, peuvent être défini à différents endroits. Ici, c'est un exercice, en principe il faut mieux définir ça dans l'inventaire.
vars: domains: - brocoli.be - patate.be tasks: ... - name: Configuration de nginx template: src: nginx.conf.j2 dest: /etc/nginx/sites-available/{{ item }} owner: root group: root mode: "0644" # équivalent à "u=rw,g=r,o=r" notify: Restart nginx loop: "{{ domains }}"
Par défaut, le nom d'un élément est item
.
Dans la config, on va dire à nginx de restreindre sa config pour un domaine en particulier. Donc, on remplace la ligne server_name _;
par server_name {{ item }};
:
{{ ansible_managed | comment }} server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; server_name {{ item }}; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } }
Ici, on va voir que la configuration se fait pour les différents domaines :
TASK [Configuration de nginx] *********************************************************************************************************************************************************************** changed: [debian2] => (item=brocoli.be) changed: [debian1] => (item=brocoli.be) changed: [debian2] => (item=patate.be) changed: [debian1] => (item=patate.be)
Si on a plusieurs variables, item
n'est pas très clair, on peut le modifier pour avoir domain
par exemple.
On rajoute des paramètres pour la boucle. Ici, le nom de la variable de boucle, qu'on appellera donc domain
.
- name: Configuration de nginx template: src: nginx.conf.j2 dest: /etc/nginx/sites-available/{{ domain }} owner: root group: root mode: "0644" # équivalent à "u=rw,g=r,o=r" notify: Restart nginx loop: "{{ domains }}" loop_control: loop_var: domain
Tous les paramètres de boucle se trouvent dans la doc : https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html
On modifie du coup le fichier de config, pour remplacer item
par domain
.
https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html
https://medium.com/polarsquad/ansible-best-practices-part-1-b3391b3c6f68
pip + virtualenv
plugin molecule-vagrant
Commande ansible-doc pour avoir la doc. → équivalent au man page
Prochain atelier Ansible : 24/10 à 14h
Lieu : Chez Célo (Crainhem)
Moment informel durant lequel on exprime en peu de mots comment, à titre personnel, la réunion a été vécue que ce soit positif ou négatif. Si une ou plusieurs tension est née durant la réunion, il est peut-être nécessaire d'envisager l'une ou l'autre réunion pour y remédier.