From 21485e74a4c5451539556d7fcbbe868df4e2e81d Mon Sep 17 00:00:00 2001 From: Gregory Colpart Date: Fri, 3 Mar 2017 16:21:27 +0100 Subject: [PATCH] =?UTF-8?q?Am=C3=A9liorations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HowtoAnsible.md | 115 ++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 72 deletions(-) diff --git a/HowtoAnsible.md b/HowtoAnsible.md index d12840e6..648dcc73 100644 --- a/HowtoAnsible.md +++ b/HowtoAnsible.md @@ -254,11 +254,12 @@ Pour avoir plus d'infos sur un module : (…) ~~~ -*Note* : c'est pratique pour avoir la documentation exacte pour votre version d'Ansible. En effet, celle du site corespond à la dernière version et n'indique pas toujours toutes les différences. - +> *Note* : c'est pratique pour avoir la documentation exacte pour votre version d'Ansible. En effet, celle du site corespond à la dernière version et n'indique pas toujours toutes les différences. ### playbook + + Un playbook va ensuite dérouler des _actions_ qui seront organisées en _tasks_, [roles](#roles) et [handlers](#handlers). Exemple de playbook simple : @@ -311,7 +312,7 @@ Un playbook plus évolué : # vim:ft=ansible: ~~~ -On lance ainsi le playbook : +On lance des playbooks ainsi : ~~~ $ ansible-playbook PLAYBOOK.yml --limit HOSTNAME --forks 1 @@ -355,17 +356,17 @@ $ ansible-playbook -l "*[0:9]" playbook.yml $ ansible-playbook -l "*[10:]" playbook.yml ~~~ -Il est de toute façon préférable de ne pas mettre `all` dans le champs `hosts` dans le playbook pour éviter un - _possible_ - oubli de "limite" de machines. - +Il est de toute façon préférable de ne pas mettre `all` dans le champs `hosts` dans le playbook pour éviter un oubli. ### handlers -Les **handlers** ne sont exécutées que si une action a fait la demande, via la directive `notify` disponible pour tous les modules. +Les **handlers** sont des actions définies dans un playbook, qui ne sont exécutées que dans certains cas. +On utilise l'option `notify` au sein d'un module pour évoquer un handler. Celui-ci ne sera exécuté que si un module a effectivement provoqué un changement. +L'usage classique est de recharger un service après une modification de configuration : si la modification est réalisée => le service est rechargé, si la modification est déjà effectuée => aucune action. -L'enregistrement du handler se fait seulement lorsque l'action a provoqué un changement. -L'exécution effective du handler se fait **une seule fois** en fin de "play", quel que soit le nombre de fois où il a été demandé pendant l'exécution. +Par défaut, l'exécution effective des handlers se fait **une seule fois** à la fin du playbook, quel que soit le nombre de fois où il a été demandé pendant l'exécution. -Les handlers servent le plus souvent à redémarrer des services. Exemple : +Exemple : ~~~{.yaml} tasks: @@ -388,6 +389,8 @@ Dans des rôles longs, nous conseillons de purger les handlers de temps en temps ### roles + + Lorsqu'on a besoin d'utiliser des fichiers ou _templates_ à copier, des variables avec des valeurs par défaut, des handlers… on peut organiser tout cela dans un **role** en respectant la structure conventionnelle suivante : ~~~ @@ -410,6 +413,8 @@ foo └── main.yml ~~~ +À titre d'exemple, voici des rôles Ansible que nous utilisons : + ### inventory @@ -447,8 +452,8 @@ proxy=proxy.mercerie.example.com * `hostname.internal` : serveur présent dans aucun groupe * `[httpservers]` : le nom du groupe (pour les serveurs http). Les noms de hosts qui suivent appartiendront à ce groupe -* `machine[01:57].evolix.net` : on peut indiquer une [pseudo-]expression régulière - ici ajoutera les machines _machine01.evolix.net_, _machine02.evolix.net_, _machine03.evolix.net_… _machine57.evolix.net_ -* `http.evolix.net:2222` : ansible se connecte par ssh, et _http.evolix.net_ a un port SSH d'écoute différent qui est 2222 +* `machine[01:57].example.com` : on peut indiquer une [pseudo-]expression régulière - ici ajoutera les machines _machine01.example.com_, _machine02.example.com_, _machine03.example.com_… _machine57.example.com_ +* `HOSTNAME:2222` : ansible se connecte par ssh, et _HOSTNAME_ a un port SSH d'écoute différent qui est 2222 * `[dbservers]` : groupe pour les serveurs de base de données * `machine50.example.com` : cette machine est déjà présente dans le groupe _httpservers_, mais sera aussi accessible à partir du groupe _dbservers_ * `alias ansible_port=2222 ansible_host=192.168.1.50` : la machine _alias_ n'a pas un vrai FQDN mais pointera vers _192.168.1.50_ car on a indiqué des variables propres à Ansible. Il est existe aussi `ansible_connection` (local ou ssh) ou `ansible_user` (le nom de l'utilisateur de la machine distante avec lequel Ansible se connectera en ssh) @@ -462,14 +467,13 @@ On peut aussi découper le fichier "inventory" selon les groupes et les variable Les variables propres à Ansible : - ### variables Les variables sont un élément clé de la configuration des playbooks et roles. Exemple : ~~~{.yaml} vars: - ip: 31.170.9.129 + ip: 192.0.2.42 conf_file: /etc/foo.conf tasks: @@ -534,7 +538,7 @@ On peut aussi n'éxecuter que certains tags : $ ansible-playbook (…) --tags "configuration,packages" ~~~ -Note : on peut également _taguer_ des rôles `include`. +> *Note* : on peut également _taguer_ des rôles `include`. ### Register @@ -572,7 +576,7 @@ La configuration est lue dans l'ordre suivant : ### ansible.cfg -Options utiles (TODO : à revoir) : +Quelques options qui peuvent être utiles : * `display_args_to_stdout` : mettre à `True` si on veut voir tout le contenu du _tasks_ executé pour chaque étape écrit sur _stdout_ * `display_skipped_hosts` : mettre à `False` si on ne veut pas voir affiché sur _stdout_ l'information d'un _task_ qui n'est pas exécuté _(le nom de variable est confu - mais il s'agit bien de l'affichage du task)_ @@ -591,63 +595,30 @@ Options utiles (TODO : à revoir) : ### unbalanced jinja2 block or quotes ~~~ -fatal: [test.evolix.net]: FAILED! => {"failed": true, "reason": "error while splitting arguments, either an unbalanced jinja2 block or quotes"} +fatal: [HOSTNAME]: FAILED! => {"failed": true, "reason": "error while splitting arguments, either an unbalanced jinja2 block or quotes"} ~~~ -Vérifier bien la syntaxe du document qui est référé pour cette erreur. Cela peut être un guillemet mal fermé (ou mélange simples/doubles guillemets), ou encore histoire de crochet devenant une parenthèse… - -### UNREACHABLE! - -~~~ -fatal: [test.evolix.net]: UNREACHABLE! => {"changed": false, "msg": "SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue", "unreachable": true} -~~~ - -Malheureusement, cela arrive souvent sur certaines machines (une ?), mais pas de solution pour le moment -> boire du café - beaucoup de café. - -Du côté de la machine distante, dans le fichier `/var/log/auth.log`: - -~~~ -14:56:29 localhost sshd[19915]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=dual.evolix.net user=service -14:56:31 localhost sshd[19915]: Accepted password for service from 192.168.4.137 port 42502 ssh2 -14:56:31 localhost sshd[19915]: pam_unix(sshd:session): session opened for user service by (uid=0) -14:56:31 localhost systemd-logind[641]: New session 181 of user service. -14:56:32 localhost sshd[19915]: pam_unix(sshd:session): session closed for user service -14:56:32 localhost systemd-logind[641]: Removed session 181. -~~~ - -Et quand ça marche - la session ne se referme pas, et est réutilisé par les exécutions playbook suivantes: - -~~~ -14:58:57 localhost sshd[20339]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=dual.evolix.net user=service -14:59:00 localhost sshd[20339]: Accepted password for service from 192.168.4.137 port 42511 ssh2 -14:59:00 localhost sshd[20339]: pam_unix(sshd:session): session opened for user service by (uid=0) -14:59:00 localhost systemd-logind[641]: New session 182 of user service. -(…) -15:01:08 localhost sshd[23034]: Received disconnect from 192.168.4.137: 11: disconnected by user -15:01:08 localhost sshd[23024]: pam_unix(sshd:session): session closed for user service -15:01:08 localhost systemd-logind[641]: Removed session 182. -~~~ - -Mais si tentative de déploiement Ansible juste après la session supprimée (par ex la 182), c'est à ce moment là qu'on se retrouve avec des *UNREACHABLE* -> savoir pourquoi sshd supprime la session ssh… +Bien vérifier la syntaxe : cela peut être un guillemet mal fermé (ou mélange simples/doubles guillemets), ou encore histoire de crochet devenant une parenthèse… ### Missing required arguments ~~~ -fatal: [test.evolix.net]: FAILED! => {"changed": false, "failed": true, "msg": "missing required arguments: section"} +fatal: [HOSTNAME]: FAILED! => {"changed": false, "failed": true, "msg": "missing required arguments: section"} ~~~ -Le message est assez clair, donc bien relire la doc du module sur Ansible, et toujours ajouter les arguments obligatoires pour ce module. +Le message est assez clair, donc bien relire la doc du module sur Ansible pour ajouter les arguments obligatoires pour ce module. ### Requires stdlib json or simplejson module ~~~ -fatal: [lenny.evolix.net]: FAILED! => {"changed": false, "failed": true, "msg": "Error: ansible requires the stdlib json or simplejson module, neither was found!"} +fatal: [HOSTNAME]: FAILED! => {"changed": false, "failed": true, "msg": "Error: ansible requires the stdlib json or simplejson module, neither was found!"} ~~~ ~~~ # apt install python-simplejson ~~~ + ## Astuces ### Vérifier un playbook @@ -658,15 +629,15 @@ fatal: [lenny.evolix.net]: FAILED! => {"changed": false, "failed": true, "msg": $ ansible-playbook --syntax-check my-experimental-playbook.yml ~~~ - +Voir -* vérifier les actions qui vont être faite s(mode `dry-run`) sans rien exécuter : +* vérifier les actions qui vont être faites (mode `dry-run`) sans rien exécuter : ~~~ $ ansible-playbook --check my-experimental-playbook.yml ~~~ -*Note* : certaines actions ne sont pas exécutées en mode "check", cela peut donc perturber celles qui sont bassées dessus. +> *Note* : certaines actions ne sont pas exécutées en mode "check", cela peut donc perturber celles qui sont bassées dessus. * avoir le diff des fichiers modifiés (ne marche pas avec les modules `replace`/`lineinfile` à priori) : @@ -714,7 +685,7 @@ Pour éviter que les différentes tâches s'appliquent une par une sur tout les strategy: free ~~~ -*Note*: ne plus se fier au texte `host changed` après texte de la tâche, car il pourrait s'agir d'une autre tâche affichée plus en haut dans le texte de l'historique. +> *Note*: ne plus se fier au texte `host changed` après texte de la tâche, car il pourrait s'agir d'une autre tâche affichée plus en haut dans le texte de l'historique. ### Fréquence des hosts @@ -725,6 +696,8 @@ Lors de l'exécution d'un play, on peut indiquer une fréquence sur le nombre d' ### Cowsay + + Si la commande `cowsay` est disponible sur votre machine, vous verrez un message à la fin : ~~~ @@ -750,22 +723,22 @@ Pour le désactiver : `export ANSIBLE_NOCOWS=1` Disponible aussi dans la conf du fichier `/etc/ansible/ansible.cfg` - - ### Conditions dans fichier jinja2 + + ~~~ {% if python_is_installed is defined %} Ansible devrait marcher -pardi! {% endif %} ~~~ - - Voir la doc pour plus de détails : ### Lire une entrée au clavier + + S'il manque une valeur pour la suite du script, soit on le gère en mettant une erreur, ou une valeur par défaut, mais sinon on peut aussi demander une saisie clavier : ~~~{.yaml} @@ -789,16 +762,14 @@ Si on veut utiliser cette variable dans une tâche, il faut simplement utiliser prenom_de_autre: prenom ~~~ - - ### Exécuter un playbook en mode interactif + + ~~~ $ ansible-playbook playbook.yml --step ~~~ - - ### Ne pas lancer une commande shell si le fichier existe En indiquant l'argument `creates` indiquant le chemin de fichier lors de l'utilisation du module shell, cette tâche ne s'exécutera que si le fichier indiqué par `creates` n'existe pas. @@ -808,7 +779,9 @@ Ces arguments sont disponibles pour certains modules (comme `shell`). C'est beaucoup plus simple et rapide que de tester le fichier par le module `stat` juste avant. -### Lancer tâche sur machine précise (voire locale) +### Lancer tâche sur machine précise (voire localhost) + + ~~~ - name: /etc/hosts @@ -822,10 +795,10 @@ C'est beaucoup plus simple et rapide que de tester le fichier par le module `sta Pour une exécution locale, on peut aussi utiliser l'attribut `local_action`. - - ### Ne lancer tâche qu'une seule fois + + ~~~ - name: Début installation, envoie email run_once: true @@ -834,8 +807,6 @@ Pour une exécution locale, on peut aussi utiliser l'attribut `local_action`. Si cet attribut est utilisé avec `delegate_to`, alors cette machine sera la seule à exécuter cette tâche. Sinon, c'est la première dans la liste de l'inventaire. - - ### Appliquer une tâche à une liste (tableau) -> boucle #### with_items @@ -966,7 +937,7 @@ Ou donner une condition ~~~ $ ansible -m setup -service.evolix.net | SUCCESS => { +HOSTNAME | SUCCESS => { "ansible_facts": { (…) "ansible_architecture": "x86_64",