Mettre en place un serveur manuellement peut rapidement s'avérer pénible, surtout si vous avez plusieurs machines à configurer de la même manière. Pas mal de personnes se sont penchées sur cette problématique et proposent des solutions pour automatiser le déploiement. Je vous propose de découvrir l'une d'entre elles aujourd'hui : Ansible.
Ansible permet de décrire la configuration a appliquer à nos différents serveurs au travers de recettes écrites en YAML. Ces recettes contiennent une série de taches qui seront lancées les unes après les autres. Les taches utilisent des modules internes à Ansible qui permettent de décrire les opérations à effectuer et les conditions de lancement.
Notre première tache
Pour cet exemple on va chercher à installer git sur nos serveurs. On commence d'abord par écrire un fichier hosts qui va contenir la liste de nos serveurs.
[web]
192.168.33.10
Ici on précise que l'on a un groupe "web" qui contient un seul serveur. On peut définir plusieurs groupe afin de séparer les serveurs suivant la configuration à y effectuer (si on a des serveurs pour la base de données et des serveurs pour le serveur web par exemple).
Ensuite nous allons créer un fichier YAML qui va permettre de décrire notre recette :
---
- name: Installation des serveurs web
hosts: web
remote_user: root
tasks:
- name: Installation de Git
apt: name=git state=latest
...
Le module APT permet d'utiliser la commande apt afin d'installer différents packages sur votre serveur. L'avantage est qu'Ansible n'effectuera pas cette tâche à chaque fois. La seconde fois que vous lancerez le déploiement, il détectera que Git est déjà installé et ne fera rien.
Enfin pour lancer le déploiement :
ansible-playbook -i hosts playbook.yml
Les rôles
Afin de mieux organiser nos taches, on peut les séparer dans des rôles afin de pouvoir les réutiliser plus simplement.
roles
|-- <nom du role>
|--- tasks
|--- main.yml
|--- installation.yml
|--- configuration.yml
|--- handlers
|--- main.yml
|--- defaults
|--- main.yml
- Le dossier tasks va contenir les taches, le fichier main.yml sera chargé par défaut et peut inclure d'autres fichiers de taches via un include.
- Le dossier handlers va contenir des taches à effectuer lors de la réussite d'autres taches (comme le redémarrage d'nginx par exemple).
- Le dossier defaults va contenir les variable par défaut pour ce role. Ces variables peuvent être modifiées dans le playbook qui chargera ce role.
Les handlers
Les handlers permettent de gérer des taches qui doivent être effectuées en cas de changement d'une tache précédente. Par exemple lors de l'installation d'nginx on souhaite supprimer la configuration par défaut. Suite à cette suppression on doit notifier nginx pour qu'il recharge notre configuration. On va ainsi commencer par créer un handler pour gérer le rechargement d'nginx :
# handlers/main.yml
---
- name: nginx reload
service: name=nginx state=reloaded
Ensuite dans notre série de tache nginx :
---
- name: Install
apt: name=nginx state=latest
- name: Start
service: name=nginx state=started enabled=true
- name: Supprimer default.conf
file: path=/etc/nginx/sites-enabled/default state=absent
notify: nginx reload
Les variables
Une configuration doit s'adapter suivant les besoins ! Pour cela on peut définir des variables que l'on pourra utiliser dans nos recette. Par exemple on va paramétrer la timezone à utiliser pour php. Dans notre fichier defaults/main.yml
ou dans la partie vars
de notres playbook :
php_timezone: Europe/Paris
On peut alors injecter cette variable dans notre tache
- lineinfile: dest=/etc/php/7.0/fpm/php.ini regexp='date.timezone[\s]?=' line='date.timezone = {{ php_timezone }}'
On peut aussi utiliser des listes
php_packages:
- php7.0
- php7.0-common
- php7.0-cli
- php7.0-intl
- php7.0-curl
- php7.0-cgi
- php7.0-fpm
- php7.0-mcrypt
- php7.0-mysql
- php7.0-gd
# Que l'on utilisera Ensuite
- name: Installation du package {{ item }}
apt: name={{ item }} state=latest
with_items: php_packages
Les templates
Ces variables peuvent aussi être utilisé dans des templates. Par exemple on souhaite créer une configuration nginx modulable :
server{
server_name www.{{ item.domain }};
return 301 $scheme://{{ item.domain }}$request_uri;
}
server{
server_name {{ item.domain }};
root /var/www/{{ item.domain }};
{% if item.php %}
index index.php index.html;
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
{% else %}
index index.html;
{% endif %}
}
Par défaut, Ansible utilise le moteur de template Jinja que l'on peut appeller depuis le module template.
- name: Création de la configuration nginx
template: src=templates/nginx.j2 dest=/etc/nginx/sites-available/{{ item.domain }} force=yes
notify: nginx reload
Ansible Galaxy
Créer ses propres rôles peut sembler complexe lorsque l'on commence. Ansible dispose d'un hub appellé Galaxy qui permet d'échanger ces recettes avec la communauté. C'est un bon point de départ si vous voulez voir ce que font les autres et découvrir comment les autres utilisateurs utilisent Ansible.