Playbooks LEMP Ansible

Playbooks LEMP Ansible

ansible_wordlogo_blackDans le précédent article je vous avais présenté Ansible, comment l’installer, exécuter des commandes sur un ensemble de serveurs, et nous avions fait nos premiers pas avec les playbooks. Nous allons maintenant passer à la vitesse supérieure.

Dans cet article, nous allons aller plus loin, et nous rapprocher d’un playbook que nous pourrions utiliser  en production (avec un peu de tuning) en installant une stack lemp et un serveur de monitoring.

Introduction

Pour notre environnement, nous allons donc jouer sur 3 serveurs. Un premier serveur monitoring-01 faisant office de serveur de supervision, avec l’installation de munin. Un second serveur db-01 sur lequel nous installerons MySQL, et un dernier serveur frontal  web-01 qui hébergera php-fpm et NGnix.

Inventaire

Comme dans le précédent article, nous allons commencer par l’édition de notre inventaire, mais cette fois nous le stockerons dans le même dossier que le playbook:

$ mkdir lemp
$ cd lemp
$ vi hosts
[monitoringservers]
monitoring-01 ansible_ssh_host=192.168.56.210 ansible_ssh_user=root

[webservers]
web-01 ansible_ssh_host=192.168.56.211 ansible_ssh_user=root

[dbservers]
db-01 ansible_ssh_host=192.168.56.212 ansible_ssh_user=root

Nous avons donc créer 3 groupes de serveurs, et définit en dessous de chaque groupe, les serveurs appartenant à chacun d’eux.

Nous allons maintenant nous assurer que Ansible est en mesure d’atteindre chacun de ces serveurs via un ping (après avoir évidemment déployé vos clés ssh):

$ ansible all -i hosts -m ping
monitoring-01 | success >> {
    "changed": false,
    "ping": "pong"
}

web-01 | success >> {
    "changed": false,
    "ping": "pong"
}

db-01 | success >> {
    "changed": false,
    "ping": "pong"
}

Rôles

Les rôles sont une notion très importante, ils permettent de définir quelles tâches sont à exécuter pour un ensemble de serveurs. Dans notre exemple nous allons utiliser 4 rôles différents. Le premier sera common qui aura en charge l’installation des paquets commun à tous les serveurs, ensuite nous allons retrouver un rôle par groupe de serveurs (db, web et monitoring).

Les rôles seront isolés dans leur propre dossier, et contiendront un dossier tasks qui stockera les tâches à exécuter pour chaque rôle:

$ mkdir -p roles/{common,monitoring,web,db}/tasks
$ tree roles/
roles/
├── common
│   └── tasks
├── db
│   └── tasks
├── monitoring
│   └── tasks
└── web
    └── tasks

 common

Commençons par le rôle common. Nous allons installer les paquets communs à tous les serveurs via ce rôle, mais aussi installer munin-node et le configurer pour le rendre accessible depuis le serveur monitoring-01.

$ vi roles/common/tasks/main.yml
---

- name: Mise à jour des paquets
  apt: update_cache=yes cache_valid_time=7200

- name: Installation des paquets communs
  apt: name={{ item }} state=present
  with_items:
   - htop
   - vim
   - tree

- name: Installation de munin-node
  apt: name={{ item }} state=present
  with_items:
   - munin-node
   - munin-plugins-extra

- name: Configuration de munin-node
  copy: src=munin-node.conf dest=/etc/munin/munin-node.conf
  notify: restart munin-node

Quelques nouvelles choses sont apparues, la première est l’utilisation de variables ({{ item }}), ou item sera substitué par chacune des valeurs contenues dans with_items.

Ensuite l’utilisation du module copy, qui va aller chercher notre fichier prêt à être déployé dans le dossier files. Nous devons donc, créer le dossier files et copier la configuration munin:

$ mkdir roles/common/files/
$ vi roles/common/files/munin-node.conf
log_level 4
log_file /var/log/munin/munin-node.log
pid_file /var/run/munin/munin-node.pid

background 1
setsid 1

user root
group root

allow ^192\.168\.56\.210$

host *
port 4949

La dernière chose, est la section notify, après la copie de la configuration de munin-node. Il s’agit en fait d’un événement qui sera lancé après avoir copié le fichier. Nous allons donc devoir mettre en place le listener correspondant, qui aura en charge de redémarrer le service munin-node:

$ mkdir roles/common/handlers/
$ vi roles/common/handlers/main.yml
---

- name: restart munin-node
  service: name=munin-node state=restarted

Voilà notre premier rôle est prêt à l’emploi. Pour pouvoir l’exploiter nous allons devoir indiquer à Ansible, à quels serveurs l’appliquer:

$ vi main.yml
---

- hosts: all
  roles:
  - common

Nous pouvons dès à présent tester notre playbook, et valider que le rôle common soit correctement appliqué à nos serveurs:

$ ansible-playbook -i hosts main.yml

monitoring

Nous allons maintenant procéder à la préparation du serveur de monitoring. Nous devons donc installer munin et déclarer tous les hosts à monitorer.

$ vim roles/monitoring/tasks/main.yml
---

- name: Installation de munin
  apt: name={{ item }} state=present
  with_items:
   - munin

- name: Configuration de munin
  template: src=munin.conf.j2 dest=/etc/munin/munin.conf
  notify: restart munin

La nouveauté dans ce rôle, est l’utilisation du module template. Ce module fonctionne à priori comme le module copy, sa particularité est qu’il nous offre la possibilité de générer le fichier à la volée en utilisant des variables mise à disposition par Ansible. Le moteur de template utilisé est Jinja2.

Pour voir l’ensemble des variables disponibles pour un serveur il suffit d’exécuter la commande suivante:

$ ansible monitoringservers -i hosts -m setup

Revenons à notre template munin.conf:

$ vim roles/monitoring/templates/munin.conf.j2
{% for host in groups['all'] %}

[{{ host }}.devart]
  address {{ hostvars[host]['ansible_eth1']['ipv4']['address'] }}
  use_node_name yes

{% endfor %}

Dans le template ci-dessus, nous bouclons donc sur les serveurs pour ajouter une section par serveur à monitorer.

Pour finir ce rôle, nous devons aussi créer le listener associé à l’event restart munin:

$ vim roles/monitoring/handlers/main.yml
---

- name: restart munin
  service: name=munin state=restarted

web

Le rôle web aura en charge l’installation de php-fpm et NGinx. Nous allons cette fois séparer l’installation de chaque service dans un fichier dédié pour plus de lisibilité.

Nous allons donc devoir créer 2 fichiers, un premier contiendra les tâches d’installation de php-fpm, et le second de NGinx. Ces fichiers vont être inclus dans le fichier principal via l’instruction include:

$ vim roles/web/tasks/main.yml

---

- include: install_php.yml
- include: install_nginx.yml

Passons maintenant à l’installation de php-fpm. Nous allons utilisés les paquets dotdeb afin d’obtenir une version récente de php (5.5). La première chose à faire sera de déclarer les dépôts dotdeb, nous allons pour cela utiliser les modules apt_repository et apt_key:

$ vim roles/web/tasks/dotdeb.yml

---

- name: Ajout de la clé dotdeb
  apt_key: id=89DF5277 url=http://www.dotdeb.org/dotdeb.gpg state=present

- name: Ajout du dépôt principal dotdeb
  apt_repository: repo='deb http://mirror.nl.leaseweb.net/dotdeb/ wheezy all' state=present

- name: Ajout du dépôt source dotdeb
  apt_repository: repo='deb-src http://mirror.nl.leaseweb.net/dotdeb/ wheezy all' state=present

- name: Ajout du dépôt de php55
  apt_repository: repo='deb http://packages.dotdeb.org wheezy-php55 all' state=present

- name: Ajout du dépôt de php55
  apt_repository: repo='deb-src http://packages.dotdeb.org wheezy-php55 all' state=present

L’objectif suivant est d’inclure le fichier dotdeb.yml dans le fichier d’installation php, et d’installer les paquets nécessaires:

$ vim roles/web/tasks/install_php.yml
---

- include: dotdeb.yml

- name: Installation de Php
  apt: name={{ item }} state=present
  with_items:
   - php5-fpm
   - php5-cli
   - php5-mysqlnd
   - php5-redis

Dernière chose à faire pour le rôle web, l’installation de NGinx:

$ vim roles/web/tasks/install_nginx.yml

---

- name: Installation de NGinx
  apt: name={{ item }} state=present
  with_items:
   - nginx

- name: Configuration de NGinx
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
  notify: restart nginx

- name: Ajout de la configuration de localhost
  template: src=default.j2 dest=/etc/nginx/sites-available/default
  notify: restart nginx

J’estime ne plus avoir besoin d’expliquer le script ci-dessus, mais vous remarquerez l’utilisation d’un template pour la configuration NGinx. En fait nous allons faire en sorte de configurer automatiquement la directive worker_process qui doit avoir pour valeur le nombre de processeurs disponibles sur le serveur:

$ vim roles/web/templates/nginx.conf.j2
user www-data;
worker_processes {{ ansible_processor_count }};
pid /var/run/nginx.pid;

events {
        worker_connections 768;
}

http {

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        gzip on;
        gzip_disable "msie6";

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

Nous avons donc utiliser la variable ansible_processor_count pour configurer la directive worker_process.

Nous en avons donc fini avec ce rôle !

db

Dernier rôle à préparer, celui des bases de données. Comme vous l’avez constaté, l’écriture des playbook demande quand même un certain temps, et peut être que ce temps vous ne l’avez pas !!

C’est pourquoi je vais vous présenter une autre façon d’installer des services, en utilisant un dépôt de playbooks. Galaxy,  est un site permettant de mettre à disposition des playbooks prêt à l’emploi, il en existe pour tous les goûts !

Pour l’installation de MySQL nous allons utiliser le playbook bennojoy.mysql, c’est le seul playbook MySQL ayant été noté par Ansible, et je pense même vu son id (1), qu’il s’agit du premier playbook mis en ligne sur Galaxy :).

Nous allons commencer par déclarer la dépendance de ce playbook dans un fichier et l’installer en utilisant la commande ansible-galaxy:

$ vim requirements.txt
bennojoy.mysql
$ ansible-galaxy install -r requirements.txt
 downloading role 'mysql', owned by bennojoy
 no version specified, installing master
 - downloading role from https://github.com/bennojoy/mysql/archive/master.tar.gz
 - extracting bennojoy.mysql to /etc/ansible/roles/bennojoy.mysql

Et pour l’utiliser:

- hosts: dbservers
  roles:
  - {role: mysql, root_db_pass: 123456;), mysql_db: none, mysql_users: none }

Et c’est tout ? Oui !!

Notre playbook est maintenant terminé, bien entendu je vous déconseille de l’utiliser tel quel pour votre production, aucune attention n’a été apportée aux configurations des services.

Vous voulez le tester ?

Monter une VM (Debian) et lancer ses commandes:

$ apt-get update
$ apt-get install python-pip python-dev sshpass git
$ pip install ansible
$ git clone https://github.com/GuillaumeDievart/ansible-lemp
$ cd ansible-lemp
$ ansible-galaxy install -r requirements.txt
$ ansible-playbook -i hosts main.yml

Voilà, vous venez d’installer une stack LEMP monitoré sous munin 😉

Vous ne me croyez pas ? :

$ php -v
PHP 5.5.18-1~dotdeb.1 (cli) (built: Oct 22 2014 17:53:37)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies
$ mysql --version
mysql  Ver 14.14 Distrib 5.6.21, for debian-linux-gnu (x86_64) using  EditLine wrapper
$ nginx -v
nginx version: nginx/1.6.2

Conclusion

Dans cet article, j’ai voulu aller plus loin dans l’utilisation des playbooks. Nous avons abordé la notion de rôles, la manière de découper vos tâches en plusieurs fichiers, la génération de fichiers de configuration adapté au serveur cible et l’utilisation du dépôt Galaxy.

J’espère que ces connaissances vont vous permettre dès à présent de commencer à automatiser la configuration de vos serveurs. Mais sachez qu’il existe encore pas mal de notion à connaître d’ansible pour palier à tous les problèmes (condtions sur os (deb/rpm), boucles, tags …)

No Comments

Sorry, the comment form is closed at this time.