---
title: Fiche Aide Ansible
author: Rémi Maubanc
tags: CGI
---
Fiche Aide Ansible
===
## Ansible Playbook
### Configuration des hotes
#### Ajout des clés SSH sur les clients
Génération d'une clé SSH :
```bash
ssh-keygen -t rsa -b 4096 -f .ssh/ansible_master
```
Voir le [tutoriel](https://wiki-prog.infoprepa.epita.fr/index.php/Practical_GIT.html)
Ajout de la clé sur un client :
```bash
ssh-copy-id -i .ssh/ansible_master root@192.168.1.1
ssh-copy-id -i .ssh/ansible_master hyperion@192.168.1.2
```
Commande de tests
```
ssh root@192.168.1.1
^D
ssh hyperion@192.168.1.2
^D
```
Si l'injection a fonctionné, on n'a pas besoin de taper de mot de passe pour se connecter
Malgré que le compte soit dans le groupe sudo, il nécessite toujours de taper un mot de passe pour
Les commandes nécessitant une élévation de privilège. Pour la retirer, il faut : `sudo visudo`
```git
- %sudo ALL=(ALL:ALL) ALL
+ %sudo ALL=(ALL:ALL) NOPASSWD: ALL
```
#### Inventaire des clients
Fichier par défaut du système : */etc/ansible/hosts*
```yaml
[mes_servers] # Pas d'espace entre le texte et les crochets
192.168.1.1 ansible_user=root # Pour préciser à Ansible l'utilisateur à utiliser
192.168.1.2
```
Fichier d'inventaire par projet : [ A compléter ]
### Liste des commandes ansible basiques
#### Réalisation d'un ping
Réaliser un ping sur tous les clients
```bash
ansible all -m ping
```
| Option | Arguments | Description |
|--------|-----------|---------------------------------------------------|
| -m | ping | Charge le module en argument |
| None | all | Selectionne toutes les IP du fichier d'inventaire |
#### Récupération de la configuration
```bash
ansible 192.168.1.1 -m setup -a "filter=*python*"
```
| Option | Arguments | Description |
|--------|---------------------|----------------------------------------------|
| None | 192.168.1.1 | IP du client à utiliser |
| -m | setup | Charge le module `shell` |
| -a | "filter=\*python\*" | Filtre les résultats en fonction de leur clé |
#### Elevation de privilège
```bash
ansible 192.168.1.1 -m shell -a "fdisk -l" -b -K
```
| Option | Arguments | Description |
|--------|-------------|-----------------------------------------|
| None | 192.168.1.1 | IP du client à utiliser |
| -m | shell | Charge le module `shell` |
| -b | None | Elevation de privilège sudo |
| -K | None | Demande le mot de passe sudo dans stdin |
**Note :** Eviter les modules *shell* et *raw* dans les playbooks car ils ne sont pas idempotents
#### Envoyer un fichier
```bash
# Création d'un fichier pour le test
echo "Hello World!" > test.txt
ansible all -m copy -a "src=test.txt dest=/home/hyperion/ansible owner=hyperion mode=0644"
```
| Option | Arguments | Description |
|--------|--------------------|----------------------------------------------------------|
| None | all | Utilise toutes les IP présentes dans l'inventaire |
| -m | copy | Charge le module `copy` pour la copie de fichier |
| -a | "src=test.txt ..." | Précise les paramètres de commande pour le module |
#### Recevoir un fichier
```bash
ansible all -m fetch -a "src=/etc/passwd dest=/tmp flat=yes"
ls /tmp # Une copie du fichier passwd doit se trouver dans le /tmp du master
```
| Option | Arguments | Description |
|--------|--------------------|----------------------------------------------------------|
| None | all | Utilise toutes les IP présentes dans l'inventaire |
| -m | fetch | Charge le module `fetch` pour télécharger des fichiers |
| -a | "src=test.txt ..." | Précise les paramètres de commande pour le module |
### Installation packages
Ouvrir le port HTTP pour nginx : [article](https://www.thegeekdiary.com/how-to-open-a-ports-in-centos-rhel-7/)
+ ajouter nginx dans le fichier */etc/services* aux lignes commencant par http:
```bash
- http 80/tcp www www-http # WorldWideWeb HTTP
- http 80/udp www www-http # HyperText Transfert Protocol
+ http 80/tcp www www-http nginx # WorldWideWeb HTTP
+ http 80/udp www www-http nginx # HyperText Transfert Protocol
```
:::danger
=> Problème rencontré pour le Lab4 de la formation Ansible
:::
Installation de nginx dans deux clients (Debian et Centos 7)
Dans un fichier playbook *nginx.yml*
```yaml
---
- name: Nginx server installed
hosts: demoservers
become: yes
tasks:
- name: Add epel-release repo
yum:
name: epel-release
state: present
when: ansible_facts['os_family'] == "RedHat"
- name: latest Nginx version installed Centos
yum:
name: nginx
state: present
when: ansible_facts['os_family'] == "RedHat"
- name: latest Nginx version installed Debian
apt:
name: nginx
state: latest
when: ansible_facts['os_family'] == "Debian"
- name: Nginx enable and running Centos
service:
name: nginx
enabled: true
state: started
when: ansible_facts['os_family'] == "RedHat"
- name: Add nginx index template
copy:
src: index.html
dest: /var/www/html/
when: ansible_facts['os_family'] == "Debian"
- name: Nginx enable and running Debian
systemd:
name: nginx
enabled: true
state: started
when: ansible_facts['os_family'] == "Debian"
```
OS_Family vs Distribution : [Lien Article](https://techviewleo.com/list-of-ansible-os-family-distributions-facts/)
### Gestion des variables
Les variables peuvent être définies de deux manières:
- Directement dans le fichier
```yaml
vars:
user: admin
group: wheel
```
- Dans un fichier séparé
```yaml
# Fichier dédié
---
user: admin
group: wheel
```
```yaml
# Dans le fichier principal
vars_files:
- vars/users.yml
```
Arborescence du projet :
```
|- webserver.yml
|- group_vars
|- demoservers # Un groupe d'hotes défini dans l'inventaire
|- host_vars
|- 192.168.1.1 # Un hote existant dans l'inventaire
|- html
|- dev_index.html
|- prod_index.html
```
*webserver.yml*
```yaml
---
- name: Copy index.html
hosts: demoservers
become: yes
tasks:
- name: copy right index.html
copy:
src: "html/{{ stage }}_index.html"
dest: /var/www/html/index.html
```
*group_vars/demoservers*
```yaml
---
stage: dev
```
*host_vars/192.168.1.1*
```yaml
---
stage: prod
```
### Valeur de retour
[Documentation](https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html)
Dans le playbook :
```yaml
---
- name: Installs a package and prints the result
hosts: dbservers
become: True
tasks:
- name: Install the package
yum:
name: git
state: present
update_cache: yes
register: install_result # Récupération du stdout
- debug: var=install_result.result
```
:::info
`install_result` est un dictionnaire et peut être déréférencé.
:::
### Valeur dans le playbook
```yaml
---
- name: Create users
hosts: all
become: yes
vars:
user: admin
group: wheel
homedir: /dev/null
shell: /bin/false
tasks:
- user:
name: "{{ user }}" # Avec ou sans espace entre la variable et les accolades
group: "{{ group }}"
home: "{{ homedir }}"
shell: "{{ shell }}"
```
### Utilisation des facts
```yaml
---
- name: Output facts within a playbook
hosts: webservers
tasks:
- name: Prints Ansible facts
debug:
msg: The default IPv4 address of {{ ansible_fqdn }} is {{ ansible_enp0s3.ipv4.address }}
```
```bash
ok: [192.168.1.1] => {
"msg": "The default IPv4 address of debian is 192.168.1.1"
}
ok: [192.168.1.2] => {
"msg": "The default IPv4 address of localhost.localdomain is 192.168.1.Z"
}
```
### Les boucles
```yaml
---
- name: Loop demo
hosts: 192.168.1.92
vars:
check_services:
- nginx
- sshd
tasks:
- name: Check if service is started
service:
name: "{{ item }}"
state: started
loop: "{{ check_services }}" # Iteration sur chaque élement
```
### Conditions multiples
```yaml
---
- name: MySQL server installation
hosts: all
become: yes
tasks:
- name: Install latest MySQL server when host RAM greater than 1 GB with YUM
yum:
name: mysql-server
state: latest
when: ansible_facts['os_family'] == "RedHat" and ansible_memtotal_mb > 1024
- name: Install latest MySQL server when host RAM greater than 1 GB with APT
apt:
name: mysql-server
state: latest
when: ansible_facts['os_family'] == "Debian" and ansible_memtotal_mb > 1024
```
### Handlers/Trigger
```yaml
---
- name: Manage Nginx
hosts: 192.168.1.57
become: yes
tasks:
- name: Copy Nginx configuration file
copy:
src: conf/default.conf
dest: /etc/nginx/sites-enabled/
notify:
- restart_nginx # Si l'état est "changed", le handler sera appelé
handlers:
- name: restart_nginx
service:
name: nginx
state: restarted
```
### Les templates
*test_server.yml*
```yaml
---
- hosts: demoservers
gather_facts: yes
become: yes
tasks:
- name: Install index.html
template:
src: html/index.html.j2
dest: /var/www/html/index.html
mode: 0644
```
*html/index.html.j2*
```html
<html>
<h1>Hostname: {{ ansible_fqdn | default('undefined') }}</h1>
<center>
<ul>
<li>System : {{ ansible_os_family | default ('linux') }}</li>
<li>Type : {{ stage | upper }}</li>
<li>Stage : {{ stage | replace("prod", "Production") |
replace("dev", "Development" }}</li>
</ul>
</center>
</html>
```
[Documentation Jinja2](https://jinja.palletsprojects.com/en/2.10.x/templates/)
## Ansible Galaxy
### Création d'un role
```bash
ansible-galaxy init nginx
```
Cette commande génère une arborescence de dossier de fichier à la manière de
`django startapp nginx` avec les structures essentielles à la déclaration d'un rôle
```bash
├── nginx
│ ├── README.md
│ ├── defaults
│ │ └── main.yml
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ ├── tests
│ │ ├── inventory
│ │ └── test.yml
│ └── vars
| └── main.yml
```