diff --git a/HowtoAnsible.md b/HowtoAnsible.md index 972a5862..9e0d37a4 100644 --- a/HowtoAnsible.md +++ b/HowtoAnsible.md @@ -1,6 +1,6 @@ --- title: Howto Ansible : automatisation d'infrastructure -categories: automation +categories automation --- * Documentation : @@ -18,7 +18,7 @@ Ansible peut exécuter des actions sur des serveurs distants sous : * *Debian 6* et supérieur : `# apt-get install python-apt dbus sudo` * *Debian 4 / 5* : utiliser le module [raw](https://docs.ansible.com/ansible/raw_module.html) d'Ansible * *OpenBSD* : voir **[pré-requis](https://wiki.evolix.org/HowtoAnsible#openbsd)** -* *FreeBSD* +* *FreeBSD* : `pkg install python` Nous utilisons actuellement Ansible 2.0.2 (disponible via sous Debian 8 : @@ -62,20 +62,8 @@ HOSTNAME | SUCCESS => {"changed": false, "ping": "pong"} $ ansible HOSTNAME --module command --args "date" HOSTNAME | SUCCESS | rc=0 >> jeudi 26 mai 2016, 23:16:01 (UTC+0200) - -$ ansible-playbook PLAYBOOK.yml --limit HOSTNAME --forks 1 - -$ ansible-playbook PLAYBOOK_WITH-SUDO.yml --limit HOSTNAME --ask-become-pass ~~~ -Options utiles pour [ansible-playbook](https://manpages.debian.org/cgi-bin/man.cgi?query=ansible-playbook&apropos=0&sektion=0&manpath=Debian+unstable+sid&format=html&locale=en) : - -* `-vvvv` : très verbeux (utile notamment pour debug SSH quand on a une erreur _unreachable_) -* `-k` / `--ask-pass` : demande le mot de passe pour la connexion SSH -* `-K` / `--ask-become-pass` : demande le mot de passe pour l'escalade (via sudo, su, doas…) -* `-l` / `--limit HOSTNAME` : limite la connexion à un ou plusieurs serveurs (attention, par défaut c'est *all*, cf `/etc/ansible/hosts`) -* `-f` / `--forks N` : nombre de process lancés en parallèle (par défaut 5)… peut être utile de mettre à 1 pour ne pas paralléliser - ## Les éléments d'Ansible @@ -85,7 +73,7 @@ Au sein d'un playbook, on dispose d'options pratiques comme les [handlers](#hand Si l'on veut organiser de façon poussée les différentes tâches, on utilisera des [roles](#roles) : il s'agit simplement d'inclure dans un playbook des fichiers YAML respectant une structure conventionnelle. Enfin, pour s'exécuter sur un ensemble de machines, Ansible a besoin d'un [inventory](#inventory) : c'est la liste des serveurs potentiellement concernés. -### Modules +### modules @@ -126,6 +114,15 @@ Voici quelques exemples de modules que nous utilisons : mode: "644" ~~~ +* Module [replace](http://docs.ansible.com/ansible/replace_module.html) : + +~~~{.yaml} +- replace: + dest: /etc/ssh/sshd_config + regexp: '^(Match User ((?!{{ name }}).)*)$' + replace: '\1,{{ name }}' +~~~ + * Module [lineinfile](http://docs.ansible.com/ansible/lineinfile_module.html) : ~~~{.yaml} @@ -136,6 +133,14 @@ Voici quelques exemples de modules que nous utilisons : regexp: "^IS_APTICRON=" ~~~ +> *Note:* replace vs lineinfile ? Le fonctionnement exacte de `replace` et de `lineinfile` est potentiellement déroutant. Voici quelques constatations : +> * avec le module `lineinfile`, si l'argument `regexp` n'est pas matché… il insère quand même la ligne ! `regexp` n'est pas une condition pour l'insertion mais une condition pour remplacer au lieu d'insérer ! +> * avec le module `lineinfile`, sauf cas tordus, l'argument `regexp` doit matcher l'argument `line` (sinon il va insérer la valeur de `line` à chaue exécution !) +> * le module `lineinfile` va d'abord évaluer si `regexp` matche et remplacer la dernière occurrence, puis si `regexp` ne matche pas il ajoute alors `line` (sans d'autre condition… même si elle existe déjà) +> * le module `replace` va remplacer uniquement si `regex` est matché, comme la commande `sed` +> * avec le module `lineinfile`, si l'on veut utiliser une référence (`\1`) dans `line`, ça donne une erreur, il faut utiliser `replace` +> * avec le module `lineinfile`, l'argument `backrefs: yes` sert à utiliser une référence au sein de l'argument `regexp` (et non pas au sein de l'argument `line`). + * Module [blockinfile](http://docs.ansible.com/ansible/blockinfile_module.html) : ~~~{.yaml} @@ -146,15 +151,6 @@ Voici quelques exemples de modules que nous utilisons : ## Set rights on files and directories written by Apache ~~~ -* Module [replace](http://docs.ansible.com/ansible/replace_module.html) : - -~~~{.yaml} -- replace: - dest: /etc/ssh/sshd_config - regexp: '^(Match User ((?!{{ name }}).)*)$' - replace: '\1,{{ name }}' -~~~ - * Module [ini_file](http://docs.ansible.com/ansible/ini_file_module.html) : ~~~{.yaml} @@ -247,16 +243,19 @@ Voici quelques exemples de modules que nous utilisons : state: restarted ~~~ -#### replace vs lineinfile +Pour avoir plus d'infos sur un module : -Le fonctionnement exacte de `replace` et de `lineinfile` est potentiellement déroutant. Voici quelques constatations : +~~~ +# ansible-doc shell +> SHELL + + The [shell] module takes the command name followed by a li + space-delimited arguments. It is almost exactly like the + (…) +~~~ + +*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. -* avec le module `lineinfile`, si l'argument `regexp` n'est pas matché… il insère quand même la ligne ! `regexp` n'est pas une condition pour l'insertion mais une condition pour remplacer au lieu d'insérer ! -* avec le module `lineinfile`, sauf cas tordus, l'argument `regexp` doit matcher l'argument `line` (sinon il va insérer la valeur de `line` à chaue exécution !) -* le module `lineinfile` va d'abord évaluer si `regexp` matche et remplacer la dernière occurrence, puis si `regexp` ne matche pas il ajoute alors `line` (sans d'autre condition… même si elle existe déjà) -* le module `replace` va remplacer uniquement si `regex` est matché, comme la commande `sed` -* avec le module `lineinfile`, si l'on veut utiliser une référence (`\1`) dans `line`, ça donne une erreur, il faut utiliser `replace` -* avec le module `lineinfile`, l'argument `backrefs: yes` sert à utiliser une référence au sein de l'argument `regexp` (et non pas au sein de l'argument `line`). ### playbook @@ -312,6 +311,51 @@ Un playbook plus complexe : # vim:ft=ansible: ~~~ +On lance ainsi le playbook : + +~~~ +$ ansible-playbook PLAYBOOK.yml --limit HOSTNAME --forks 1 + +$ ansible-playbook PLAYBOOK_WITH-SUDO.yml --limit HOSTNAME --ask-become-pass +~~~ + +Options utiles pour [ansible-playbook](https://manpages.debian.org/cgi-bin/man.cgi?query=ansible-playbook&apropos=0&sektion=0&manpath=Debian+unstable+sid&format=html&locale=en) : + +* `-vvvv` : très verbeux (utile notamment pour debug SSH quand on a une erreur _unreachable_) +* `-k` / `--ask-pass` : demande le mot de passe pour la connexion SSH +* `-K` / `--ask-become-pass` : demande le mot de passe pour l'escalade (via sudo, su, doas…) +* `-l` / `--limit HOSTNAME` : limite la connexion à un ou plusieurs serveurs (attention, par défaut c'est *all*, cf `/etc/ansible/hosts`) +* `-f` / `--forks N` : nombre de process lancés en parallèle (par défaut 5)… peut être utile de mettre à 1 pour ne pas paralléliser + +#### Limiter l'exécution à certaines machines + +* Limiter aux groupes _www_ et _sql_ (qui peuvent être indifféremment des groupes ou des serveurs) : + +~~~ +$ ansible-playbook -l "www:sql" playbook.yml +~~~ + +* limiter aux serveurs _foo-www01_, _foo-lb01_, _foo-filer_… : + +~~~ +$ ansible-playbook -l "foo-*" playbook.yml +~~~ + +* limiter aux 10 premiers serveurs de l'inventaire (utile pour faire par paquets) : + +~~~ +$ ansible-playbook -l "*[0:9]" playbook.yml +~~~ + +* puis à ceux restant : + +~~~ +$ 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. + + ### 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. @@ -467,7 +511,7 @@ Les groupes sont définis dans le fichier d'[inventaire](http://docs.ansible.com -Hormis le fait de ranger/trier chaque tâche dans une catégorie, ils permettent de limiter/exclure des tâches. +Les tags permettent de ranger/trier chaque tâche ou rôle dans une catégorie. ~~~{.yaml} - name: Coucou @@ -476,19 +520,19 @@ Hormis le fait de ranger/trier chaque tâche dans une catégorie, ils permettent tags: message ~~~ -Pour ne pas afficher les messages : +On peut également utiliser les tags pour limiter/exclure des tâches : ~~~ $ ansible-playbook (…) --skip-tags "message" ~~~ -On peut appliquer des tags à des rôles, ou voir directement n'éxecuter que certains tags : +On peut aussi n'éxecuter que certains tags : ~~~ $ ansible-playbook (…) --tags "configuration,packages" ~~~ -Note : on peut également _taguer_ des `include`. +Note : on peut également _taguer_ des rôles `include`. ### Register @@ -628,27 +672,6 @@ $ ansible-playbook --check my-experimental-playbook.yml $ ansible-playbook --check --diff my-experimental-playbook.yml ~~~ -### Plus d'infos sur module - -Lister les modules: - -~~~ -# ansible-doc -l -~~~ - -Avoir des infos sur un module: - -~~~ -# ansible-doc shell -> SHELL - - The [shell] module takes the command name followed by a li - space-delimited arguments. It is almost exactly like the - (…) -~~~ - -*Note* : c'est pratique pur 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. - ### Stopper l'éxecution du code Pour par exemple, stopper le code à un moment pour lire les valeurs d'une variables @@ -683,8 +706,6 @@ ou * Installer package python - - (bzip2, php, … selon services à installer) ~~~ @@ -697,33 +718,6 @@ ou > GRANT ALL ON db.* TO 'user'@'localhost'; ~~~ -### Limiter l'exécution à certaines machines - -* Limiter aux groupes _www_ et _sql_ (qui peuvent être indifféremment des groupes ou des serveurs) : - -~~~ -$ ansible-playbook -l "www:sql" playbook.yml -~~~ - -* limiter aux serveurs _foo-www01_, _foo-lb01_, _foo-filer_… : - -~~~ -$ ansible-playbook -l "foo-*" playbook.yml -~~~ - -* limiter aux 10 premiers serveurs de l'inventaire (utile pour faire par paquets) : - -~~~ -$ ansible-playbook -l "*[0:9]" playbook.yml -~~~ - -* puis à ceux restant : - -~~~ -$ 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. ### Lancement tâches hosts asynchrone @@ -800,7 +794,7 @@ tasks: var: prenom ~~~ -Malheureusement pour le moment, doit se situer avant `tasks`. +Malheureusement pour le moment, cela doit se situer avant `tasks`. Si on veut utiliser cette variable dans une tâche, il faut simplement utiliser le nom de la variable, et si on veut l'utiliser (explicitement) pour un play ne se trouvant pas dans le même fichier (donc ici la variable dans autre.yml s'appelera _prenom_de_autre_ et non prenom) :