Petite réorganisation

This commit is contained in:
Gregory Colpart 2017-03-03 09:00:50 +01:00
parent 6dc7b9c5c7
commit fd0f275775

View file

@ -24,17 +24,19 @@ Nous utilisons actuellement Ansible 2.0.2 (disponible via <http://pub.evolix.net
~~~
# apt install --allow-unauthenticated ansible=2.0.2.0-1~bpo8+1
~~~
## Utilisation
~~~
$ ansible --version
ansible 2.0.2.0
config file = /etc/ansible/ansible.cfg
configured module search path = Default w/o overrides
~~~
## Utilisation de base
Configuration minimale :
~~~
$ cat ~/.ansible.cfg
[defaults]
inventory = $HOME/.ansible/hosts
@ -43,17 +45,21 @@ inventory = $HOME/.ansible/hosts
#ssh_args = -o ControlMaster=no -o ControlPersist=no
ssh_args = -o ControlMaster=auto -o ControlPersist=300s
pipelining = True
~~~
$ echo HOSTNAME >> ~/.ansible/hosts
$ ssh-copy-id HOSTNAME
Exemples d'utilisation basique :
$ ansible HOSTNAME -i $HOME/.ansible/hosts -m ping
HOSTNAME | SUCCESS => {
"changed": false,
~~~
$ ansible localhost --module ping
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
$ ansible HOSTNAME -a "date"
$ echo HOSTNAME >> ~/.ansible/hosts && ssh-copy-id HOSTNAME && ansible HOSTNAME -i $HOME/.ansible/hosts --module ping --one-line
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)
@ -70,106 +76,24 @@ Options utiles pour [ansible-playbook](https://manpages.debian.org/cgi-bin/man.c
* `-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
L'utilisation d'Ansible se fait principalement avec un **playbook**. C'est l'élément clé, qui peut suffire à réaliser des tâches utiles. Il s'agit d'un fichier qui décrit la succession d'une ou plusieurs séries d'actions (des *plays*). Chaque **play** indique quelques réglages généraux comme le groupe de serveurs concernés, la manière de devenir administrateur, quels fichiers de variables charger et surtout des actions.
L'élément de base d'Ansible est le [module](#modules) : on peut exécuter une tâche (installation de paquets, copie de fichiers, etc.) en exécutant simplement `ansible --module`.
Pour regrouper plusieurs tâches, on utilise un [playbook](#playbook) : un fichier en syntaxe YAML qui va lister une succession de modules avec des arguments.
Au sein d'un playbook, on dispose d'options pratiques comme les [handlers](#handlers) : ils permettent le déclenchement d'une commande sous certaines conditions (redémarrage d'un service par exemple).
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.
Un playbook va ensuite dérouler des _actions_ qui seront organisées en _roles_, _tasks_ et _handlers_.
Une **action** est l'invocation d'une fonctionnalité particulière fournie par un module. Exemple, pour s'assurer de l'absence d'un fichier :
~~~
- file: path=/etc/cron.daily/apticron state=absent
~~~
Les actions peuvent être listées dans la partie **tasks** du playbook et peuvent être aussi déportées dans un fichier et inclus dans le playbook.
Les **handlers** sont des actions qui ne sont exécutées que si une autre action en a fait la demande, via l'attribut `notify`.
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 :
~~~
foo
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
└── main.yml
~~~
La partie **inventory** correspond à la description de l'inventaire des serveurs à configurer et inclus un mécanisme de configuration individuelle et par groupe. Nous y revenons plus loin.
## Howto Playbook
Exemple de playbook très simple :
~~~{.yaml}
---
- hosts: all
tasks:
- shell: echo hello World
# vim:ft=ansible:
~~~
Un playbook plus complexe (avec un seul "play") :
~~~{.yaml}
---
- hosts: all
gather_facts: yes
become: yes
vars_files:
- 'vars/main.yml'
vars:
external_roles: ~/GIT/ansible-roles
external_tasks: ~/GIT/ansible-public/tasks
pre_tasks:
- name: Minifirewall is stopped (temporary)
service:
name: minifirewall
state: stopped
roles:
- "{{ external_roles }}/minifirewall"
post_tasks:
- include: "{{ external_tasks }}/commit_etc_git.yml"
vars:
commit_message: "Ansible run firewall.yml"
handlers:
- name: restart minifirewall
service:
name: minifirewall
state: restarted
# vim:ft=ansible:
~~~
### Modules pour tasks
### Modules
<http://docs.ansible.com/ansible/list_of_all_modules.html>
Pour avoir la liste des modules utilisables dans *tasks* : `ansible-doc -l`
Le module est le garant de l'idempotence : Ansible gérera le succès de l'exécution et indiquera si une vérification ou action concrète a été effectuée. (TODO: à enrichir).
Voici quelques exemples :
Pour avoir la liste des modules utilisables : `ansible-doc -l`
Voici quelques exemples de modules que nous utilisons :
* Module [command](http://docs.ansible.com/ansible/command_module.html) :
@ -334,7 +258,166 @@ Le fonctionnement exacte de `replace` et de `lineinfile` est potentiellement dé
* 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`).
### vars
### playbook
Un playbook va ensuite dérouler des _actions_ qui seront organisées en _roles_, _tasks_ et _handlers_.
Exemple de playbook très simple :
~~~{.yaml}
---
- hosts: all
tasks:
- shell: echo hello World
# vim:ft=ansible:
~~~
Un playbook plus complexe :
~~~{.yaml}
---
- hosts: all
gather_facts: yes
become: yes
vars_files:
- 'vars/main.yml'
vars:
external_roles: ~/GIT/ansible-roles
external_tasks: ~/GIT/ansible-public/tasks
pre_tasks:
- name: Minifirewall is stopped (temporary)
service:
name: minifirewall
state: stopped
roles:
- "{{ external_roles }}/minifirewall"
post_tasks:
- include: "{{ external_tasks }}/commit_etc_git.yml"
vars:
commit_message: "Ansible run firewall.yml"
handlers:
- name: restart minifirewall
service:
name: minifirewall
state: restarted
# vim:ft=ansible:
~~~
### 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.
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.
Les handlers servent le plus souvent à redémarrer des services. Exemple :
~~~{.yaml}
tasks:
- name: copy Apache configuration
copy: (…)
notify: Restart Apache
handlers:
- name: Restart Apache
service:
name: apache2
state: restarted
~~~
Dans des rôles longs, nous conseillons de purger les handlers de temps en temps (en fin de groupe d'action). En effet, si un playbook est interrompu les handlers ne sont pas forcément exécutés alors que l'action qui les a déclenchés a bien eu lieu. On insère alors l'action suivante :
~~~{.yaml}
- meta: flush_handlers
~~~
### 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 :
~~~
foo
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
└── main.yml
~~~
### inventory
<http://docs.ansible.com/ansible/intro_inventory.html>
La partie **inventory** correspond à la description de l'inventaire des serveurs à configurer et inclus un mécanisme de configuration individuelle et par groupe.
Permet d'indiquer la liste des machines concernées par Ansible (peut être limité lors de l'exécution de la commande par l'option `-l`) et de pouvoir les regrouper dans des groupes.
Exemple:
~~~
hostname.internal
[httpservers]
machine[01:57].example.com
http.example.com:2222
[dbservers]
machine12.example.com
machine50.example.com
m[a:o]chine52.example.com
alias ansible_port=2222 ansible_host=192.168.1.50
[client]
host1 http_port=80 maxRequestsPerChild=808 # des variables qui seront automatiquement auto-completées liées à cet host
[commercant]
mercerie
chapeautier
[commercant:vars]
ntp_server=ntp.mercerie.example.com
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
* `[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)
* `host1 http_port=80 maxRequestsPerChild=808` : des variables qui seront automatiquement disponibles pour les actions sur _host1_
* `[commercant:vars]` : des variables qui seront liées au groupe _commercant_.
On peut aussi créer des groupes de groupes en utilisant `:children`
On peut aussi découper le fichier "inventory" selon les groupes et les variables : <http://docs.ansible.com/ansible/intro_inventory.html#splitting-out-host-and-group-specific-data>
Les variables propres à Ansible : <http://docs.ansible.com/ansible/intro_inventory.html#list-of-behavioral-inventory-parameters>
### variables
Les variables sont un élément clé de la configuration des playbooks et roles. Exemple :
@ -380,34 +463,6 @@ Pour gérer de nombreuses variables dans un projet, on peut stocker toutes celle
Les groupes sont définis dans le fichier d'[inventaire](http://docs.ansible.com/ansible/intro_inventory.html).
### Handlers
La directive `notify`, disponible pour tous les modules, permet de déclencher un `handler`.
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.
Les handlers servent le plus souvent à redémarrer des services. Exemple :
~~~{.yaml}
tasks:
- name: copy Apache configuration
copy: (…)
notify: Restart Apache
handlers:
- name: Restart Apache
service:
name: apache2
state: restarted
~~~
Dans des rôles longs, il est conseillé de purger les handlers de temps en temps (en fin de groupe d'action). En effet, si un playbook est interrompu les handlers ne sont pas forcément exécutés alors que l'action qui les a déclenchés a bien eu lieu. On insère alors l'action suivante :
~~~{.yaml}
- meta: flush_handlers
~~~
### Tags
<https://docs.ansible.com/ansible/playbooks_tags.html>
@ -457,6 +512,7 @@ Il est possible de consulter le contenu détaillé de la variable avec `debug` :
Pour certains modules, `register` est presque un passage obligatoire pour une utilisation cohérente des éléments (stat…).
## Configuration
<https://docs.ansible.com/ansible/intro_configuration.html>
@ -468,56 +524,6 @@ La configuration est lue dans l'ordre suivant :
* `~/.ansible.cfg`
* `/etc/ansible/ansible.cfg`
### Fichier "inventory"
<http://docs.ansible.com/ansible/intro_inventory.html>
Permet d'indiquer la liste des machines concernées par Ansible (peut être limité lors de l'exécution de la commande par l'option `-l`) et de pouvoir les regrouper dans des groupes.
Exemple:
~~~
hostname.internal
[httpservers]
machine[01:57].example.com
http.example.com:2222
[dbservers]
machine12.example.com
machine50.example.com
m[a:o]chine52.example.com
alias ansible_port=2222 ansible_host=192.168.1.50
[client]
host1 http_port=80 maxRequestsPerChild=808 # des variables qui seront automatiquement auto-completées liées à cet host
[commercant]
mercerie
chapeautier
[commercant:vars]
ntp_server=ntp.mercerie.example.com
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
* `[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)
* `host1 http_port=80 maxRequestsPerChild=808` : des variables qui seront automatiquement disponibles pour les actions sur _host1_
* `[commercant:vars]` : des variables qui seront liées au groupe _commercant_.
On peut aussi créer des groupes de groupes en utilisant `:children`
On peut aussi découper le fichier "inventory" selon les groupes et les variables : <http://docs.ansible.com/ansible/intro_inventory.html#splitting-out-host-and-group-specific-data>
Les variables propres à Ansible : <http://docs.ansible.com/ansible/intro_inventory.html#list-of-behavioral-inventory-parameters>
### ansible.cfg
Options utiles (TODO : à revoir) :