Skip to main content

Installation & utilisation d'Ansible

Installation de l'environnement virtuel python

Création de l'utilisateur d'ansible :

adduser user-ansible

Installation de l'environnement virtuel python : 

apt-get install python-virtualenv sshpass

sshpass sert au bon fonctionnement de la suite !

Changement d'utilisateur : 

su - user-ansible

Lancement de l'environnement virtuel : 

virtualenv ansible4.6.0

Activation de l'environnement virtuel : 

source ansible4.6.0/bin/activate

Installation d'ansible

Installation d'ansible : 

pip install ansible==4.6.0

Est-ce que ansible est bien installé ?

ansible --version

image-1633383044412.png

Préparation de la communication avec les nodes

Définition des nodes :

Création du fichier de définition des nodes :

nano inventaire.ini
http1
bdd1

Modification de notre fichier host : 

nano /etc/hosts

On ajoute : 

# le node http1
34.88.193.243 http1
# le node bdd1
35.228.198.62 bdd1

Test du bon fonctionnement SSH des nodes :

ssh root@http1
ssh root@bdd1
Réalisation de pings sur nos nœuds : 
ansible -i inventaire.ini -m ping http1 --user root --ask-pass
ansible -i inventaire.ini -m ping bdd1 --user root --ask-pass

image-1633442685680.png

image-1633442696209.png

Installation de python à distance sur nos nœuds : 
ansible -i inventaire.ini -m raw -a "yum install -y python3" http1 --user root --ask-pass
ansible -i inventaire.ini -m raw -a "yum install -y python3" bdd1 --user root --ask-pass

Résultat :

image-1633385833649.png

Génération d'une chaine SHA-512 :
ansible localhost -i inventaire.ini -m debug -a "msg={{ 'passforce' | password_hash('sha512', 'sceretsalt') }}"

Le mot de passe pour l'utilisateur user-ansible est donc "passforce", choisissez-en un différent !

Résultat  :
localhost | SUCCESS => {
    "msg": "$6$sceretsalt$tBcfGEgifQpQZsg5CIGZ79XC55h5vHy7UWrys7cAF37KNCQQbm7iCvy58MlLQLaS2fLF6ZjqDVHhVrkMdRi0f0"
}

Notre clef SHA-512 a bien été générée !

Création d'un utilisateur nommé "ansible" sur tous les nodes : 
ansible -i inventaire.ini -m user -a 'name=user-ansible password=$6$sceretsalt$tBcfGEgifQpQZsg5CIGZ79XC55h5vHy7UWrys7cAF37KNCQQbm7iCvy58MlLQLaS2fLF6ZjqDVHhVrkMdRi0f0' --user root --ask-pass http1
ansible -i inventaire.ini -m user -a 'name=user-ansible password=$6$sceretsalt$tBcfGEgifQpQZsg5CIGZ79XC55h5vHy7UWrys7cAF37KNCQQbm7iCvy58MlLQLaS2fLF6ZjqDVHhVrkMdRi0f0' --user root --ask-pass bdd1

Résultat : 

image-1633442774848.png

image-1633442802700.png

Mettez évidement votre chaine à vous !

 

Ajout des droits de sudoers à nos nouveaux utilisateurs : 

ansible -i inventaire.ini -m user -a 'name=user-ansible groups=wheel append=yes ' --user root --ask-pass http1
ansible -i inventaire.ini -m user -a 'name=user-ansible groups=wheel append=yes ' --user root --ask-pass bdd1

image-1633443099352.png

Nos deux utilisateurs sont maintenant sudoers ! 

 

Nous vérifions maintenant que l'utilisateur  user-ansible dispose bien des droits sudo :

ansible -i inventaire.ini -m user -a 'name=user-ansible groups=wheel append=yes ' --user user-ansible --ask-pass --become --ask-become-pass all

Nous répondons : 

SSH password: passforce
BECOME password[defaults to SSH password]: passforce

En sortie nous avons :

image-1633446465335.png

L'utilisateur a bien le droit de sudo ! 

Génération de clefs SSH :

ssh-keygen -t ecdsa

image-1633443306629.png

Ajoutez la clé publique de l’utilisateur user-ansible sur les nodes :
ansible -i inventaire.ini -m authorized_key -a 'user=user-ansible state=present key="{{ lookup("file", "/home/user-ansible/.ssh/id_ecdsa.pub") }}"' --user user-ansible --ask-pass all

Le mot de passe demandé est "passforce" !

Résultat : 

image-1633446214381.png

Vérification du bon fonctionnement des clefs SSH :

ansible -i inventaire.ini -m authorized_key -a 'user=user-ansible state=present key="{{ lookup("file", "/home/user-ansible/.ssh/id_ecdsa.pub") }}"' --user user-ansible --become --ask-become-pass all
BECOME password: passforce 

Nous constatons, que on nous as demandé uniquement le mot de passe de sudo (BECOME password). Cela confirme que la liaison fonctionne bel et bien sans mot de passe ! 

Organisation de déploiement :

A titre d'exemple, nous allons installer la solution "MediaWiki".

Pour ce faire, nous commençons par définir les différentes étapes -  que l'on nommera des rôle - d'installation : 

  • Installation d'apache
  • Installation de MariaDB
  • Configuration d'apache
  • Configuration de MariaDB
  • Variables Globales

 

Structure d'un rôle : 

  • role/
    • files/             ---> Contient tous les fichier à copier sur le node
    • tasks/           ---> Contient les taches à exécuter 
      • main.yml
    • handlers/     ---> Contient les taches de notification
      • main.yml
    • defaults/      ---> Contient des variables par défaut
      • main.yml
    • meta/           ---> Contient des dépendances et des informations
      • main.yml

 

On applique ça à nos rôles à nous : 

 

  • Apache
    • tasks/
      • taches à exécuter pour installer apache et php
    • handlers
      • tache pour redémarrer le service apache
  • MariaDB
    • tasks/
      • taches à exécuter pour installer MariaDB
  • Commun
    • defaults/
      • Définition des variables globales
  • ConfDB
    • meta/
      • Dépendance avec le rôle Commun
    • tasks/
      • Taches à exécuter pour installer la base de donnée
  • ConfApache
    • meta/
      • Dépendance avec le rôle Commun
    • tasks/
      • Taches à exécuter pour installer apache

 

Pour simplifier la suite, nous allons créer un groupe de nodes : 

nano inventaire.ini
[apache]
http1

[db]
bdd1

 

Création du répertoire roles :

mkdir roles
cd roles

 

Nous allons maintenant utiliser ansible-galaxy qui permet de télécharger, créer et gérer les rôles ansible :

ansible-galaxy init apache

Regardons ce qu'ansible-galaxy a créer :

image-1633550710976.png

Cependant, nous allons garder uniquement les répertoires handlers, meta et tasks. Puis nous allons créer le fichier de configuration de la tache php-7 dans le rôle apache  :
rm ./apache/{README.md,defaults/,files/,templates/,tests/,vars/} -r
touch apache/tasks/php7-install.yml

Création du rôle mariadb :

mkdir -p mariadb/tasks/
touch mariadb/tasks/main.yml

Création du rôle médiawiki :

mkdir mediawiki
Création du rôle Commun : 
mkdir -p mediawiki/commun/defaults/
touch mediawiki/commun/defaults/main.yml
Création du rôle Confdb :
mkdir -p mediawiki/confdb/meta mediawiki/confdb/tasks
touch mediawiki/confdb/tasks/main.yml 
touch mediawiki/confdb/meta/main.yml
Création du rôle Confapache :
mkdir -p roles/mediawiki/confapache/meta roles/mediawiki/confapache/tasks
touch roles/mediawiki/confapache/tasks/main.yml roles/mediawiki/confapache/meta/main.yml

Ce qui nous donne cette arborescence là : 

image-1633553546268.png

Modification du main.yml du rôle apache :

nano roles/apache/tasks/main.yml
---

#1. Cette t  che permet d ^`^yinstaller Apache (httpd)    l ^`^yaide du module yum
- name: "apache installation"
  ansible.builtin.yum:
    name: "httpd"
    state: "present"

#2. Cette t  che active le service Apache
- name: "apache service activation"
  service:
    name: "httpd"
    state: "started"
    enabled: yes

#3. Cette t  che fait appel    un autre fichier de configuration pour installer PHP. Elle est ex  cut  e uniquement si la variable php_install est    vraie (par d  faut, elle e$
- name: "install php7 packages"
  include: "php7-install.yml"
  when: php_install|default(False)|bool
  1. La première tâche, "apache installation" va installer le serveur Apache avec le module “yum”. Le name: "httpd" indique le paquet concerné et le state: "present" spécifie qu’il faut l’installer. 

  2. La deuxième tâche, “apache service activation” va activer le service Apache avec le module “service”. Le name: "httpd" indique le service concerné, le state: "started" indique que le service sera démarré et le enabled: yes indique que le service sera activé.

  3. La troisième tâche, “install php7 packages” inclut un fichier de configuration externe pour installer PHP. La tâche fait appel avec l’option “include” au fichier php7-install.yml qui est placé dans le répertoire tasks à coté de main.yml. La condition when avec le filtre (php_install|default(False)|bool) permettent de conditionner l’installation de PHP.

Source : https://openclassrooms.com/fr/courses/2035796-utilisez-ansible-pour-automatiser-vos-taches-de-configuration/6373887-controlez-lexecution-des-operations-et-enchainez-plusieurs-actions

Modification du fichier php7-install.yml du rôle apache :

---

#1. Cette tâche installe le dépôt  EPEL (Extra Packages for Enterprise Linux)
- name: "epel activation"
  yum:
name: "epel-release"
state: present

#2. Cette tâche installe le dépôt REMI pour bénéficier du paquet PHP7
- name: "remi repo activation"
  yum:
name: "https://rpms.remirepo.net/enterprise/remi-release-7.rpm"
state: present

#3. Cette tâche installe PHP7 et ses extensions
- name: "install php70 packages"
  yum:
name: "php,php-mysql,php-xml,php-mbstring,php-mcrypt,php-gd,php-intl"
state: latest
enablerepo: "remi-php70"
  changed_when: yes
  notify: [ "apache restart" ]
  1. La première tâche, "epel activation", va activer le dépôt epel avec le module “yum”. Le name: "epel-release" indique le dépôt concerné et le state: present spécifie qu’il faut l’installer.
    Sur Centos, tous les logiciels ne sont pas disponibles par défaut. C’est le cas pour PHP7 ; il faut donc ajouter le dépôt EPEL qui va contenir le paquet PHP7.

  2. La deuxième tâche, “remi repo activation”, va installer le paquet remi-release-7.rpm avec le module “yum”. Le nom indique le service concerné ; le state: present indique que le paquet sera installé.
    Sous Centos, les paquets logiciels sont sous la forme RPM. Pour installer PHP7, vous avez besoin du paquet remi-release-7.rpm qui est dans le dépôt REMI qui dépend du dépôt EPEL.

  3. La troisième tâche, “install php7 packages”, installe les paquets php7 avec le module “yum”. Et les options :

    • le name indique l’ensemble des paquets à installer ; 

    • state: latest indique qu’il faut installer les dernières versions disponibles des paquets ;

    • enablerepo: "remi-php70" indique d’utiliser le dépôt remi-php70 pour les installer ;

    • changed_when : force le changement d'état, c’est-à-dire qu'avec cette condition à yes, l'exécution de la tâche provoquera un changement ;  

    • notify: [ "apache restart" ] indique que si la tâche change d'état (et uniquement si la tâche a engendré un changement), notify fait appel au handler "apache restart" pour relancer le service Apache.

Source : https://openclassrooms.com/fr/courses/2035796-utilisez-ansible-pour-automatiser-vos-taches-de-configuration/6373887-controlez-lexecution-des-operations-et-enchainez-plusieurs-actions

 

Création du Handler : 

nano roles/apache/handlers/main.yml
---
- name: "apache restart"
  service:
name: "httpd"
state: "restarted"

Le module service est utilisé pour relancer le service httpd avec l’option state: "restarted".

 

Modification du main.yml du rôle mariadb :

nano roles/mariadb/tasks/main.yml
---

# Installation des paquets mariadb serveur et son extension Python
- name: "mariadb-server installation"
  yum:
name:  "mariadb-server,MySQL-python"
state: "installed"

# Active le service MariaDB 
- name: "start mariadb service"
  service:
name:  "mariadb"
state: "started"
enabled: yes

La première tâche "mariadb-server installation" va installer mariadb serveur et son extension Python avec le module “yum”. Le name:  "mariadb-server,MySQL-python" indique les paquets concernés et state: "installed" indique que les paquets doivent être installés.

--> state peut prendre indifféremment la valeur present ou installed. Ce sont deux alias.

La deuxième tâche “start mariadb service” va activer et démarrer le service MariaDB avec le module “service”. Le name:  "mariadb"  indique le service concerné, state: "started" indique de démarrer le service et enabled:yes, de l'activer.

Source : https://openclassrooms.com/fr/courses/2035796-utilisez-ansible-pour-automatiser-vos-taches-de-configuration/6373887-controlez-lexecution-des-operations-et-enchainez-plusieurs-actions

Modification du main.yml du rôle commun (dans mediawiki) :

nano roles/mediawiki/commun/defaults/main.yml
---

# nom de la base de données
mediawiki_db_name: "mediawiki"

# nom de l’utilisateur de la base de données et son mot de passe
mediawiki_db_user: "mediawiki"
mediawiki_db_password: !vault |
       $ANSIBLE_VAULT;1.1;AES256      36663934633330396131376162363633666635376633313430616164303662633233303232353839      3932666230633632626434363734623537623463363631320a636662363032376563303163643366      37626237383534653035663335623233646364326365326565366361343835663030316533376664      6633376539663563310a386439653931623333316532326262343562326638313266343236346536
       3032

# nom et mot de passe de l’administrateur Mediawiki
mediawiki_admin_user: "admin"
mediawiki_admin_password: !vault |
       $ANSIBLE_VAULT;1.1;AES256      36663934633330396131376162363633666635376633313430616164303662633233303232353839      3932666230633632626434363734623537623463363631320a636662363032376563303163643366      37626237383534653035663335623233646364326365326565366361343835663030316533376664      6633376539663563310a386439653931623333316532326262343562326638313266343236346536
       3032

# nom du Mediawiki et son titre
mediawiki_name: "mediawiki"
mediawiki_title: "ELS"

# l’emplacement du répertoire d'installation de Mediawiki
mediawiki_directory: "/var/www/html/{{mediawiki_name}}"

# répertoire de maintenance de Mediawiki
mediawiki_maintenance_directory: "{{mediawiki_directory}}/maintenance"

# Definie le premier node du groupe mariadb
mediawiki_db_host: "{{groups.db.0}}"

# l’url des sources Mediawiki
mediawiki_archive_url: "https://releases.wikimedia.org/mediawiki/1.31/mediawiki-1.31.1.tar.gz"

Modification du main.yml du rôle confdb (dans mediawiki) :

nano roles/mediawiki/confdb/meta/main.yml
dependencies:
  - role: "mediawiki/commun"

Modification du main.yml du rôle confdb (dans mediawiki) :

nano roles/mediawiki/confdb/tasks/main.yml
---

#1. Installation de la base de donnée Mediawiki
- name: "mediawiki database"
  mysql_db:
name: "{{mediawiki_db_name}}"
state: present

#2. Création d’un accès utilisateur et attribution des privilèges sur la base Mediawiki
- name: "mediawiki user+privileges"
  mysql_user:
name: "{{mediawiki_db_user}}"
password: "{{mediawiki_db_password}}"
priv: "{{mediawiki_db_name}}.*:ALL"
host: "{{item}}"
state: present
  with_items: "{{groups.apache}}"
nano roles/mediawiki/confapache/meta/main.yml
dependencies:
  - role: "mediawiki/commun"

 

nano roles/mediawiki/confapache/tasks/main.yml 
---

#1. Création du repertoire pour l’installation des fichiers Mediawiki
- name: "mediawiki directory"
  file:
path: "{{mediawiki_directory}}"
owner: "apache"
group: "apache"
state: directory

#2. Décompresse le fichier source archive Mediawiki et le formate sans extension
- name: "uncompress mediawiki archive"
  unarchive:
src: "{{mediawiki_archive_url}}"
dest: "{{mediawiki_directory}}"
owner: "apache"
group: "apache"
remote_src: yes
# supprime mediawiki-1.xx.x/ du chemin
extra_opts: --transform=s/mediawiki-[0-9\.]*\///

#3. Exécute la tâche avec l'utilisateur apache, se place dans le répertoire de maintenance et exécute la commande de configuration si le fichier localsetting.php n’existe pas
- name: "mediawiki configuration"
  become: yes
  become_user: "apache"
  args:
   creates: "{{mediawiki_directory}}/LocalSettings.php"
   chdir: "{{mediawiki_maintenance_directory}}"
  command:
php install.php --scriptpath /{{mediawiki_name}}
    --dbname mediawiki --lang fr
    --dbuser {{mediawiki_db_user}}
    --dbpass {{mediawiki_db_password}}
    --pass {{mediawiki_admin_password}}
    --dbserver {{mediawiki_db_host}}  
    {{mediawiki_title}} {{mediawiki_admin_user}}
  run_once: yes
  delegate_to: "{{item}}"
  with_items: "{{groups.apache}}"

#4. Exécute la tâche avec l'utilisateur apache, se place dans le répertoire de maintenance et exécute la commande de mise à jour de la baseune seule fois    
- name: "mediawiki db update"
  become: yes
  become_user: "apache"
  command:
php update.php --quick
  args:
chdir: "{{mediawiki_maintenance_directory}}"
  # La mise à jour à besoin d'être lancée une seule fois
  run_once: yes
  register: resultat
  changed_when: "' ...done.' in resultat.stdout"

Création des playbooks : 

nano install-apache.yml
---
- name: "Installation apache"
  hosts: http1
  roles:
    - role: "apache"
      php_install: yes
ansible-playbook -i inventaire.ini --user user-ansible --become --ask-become-pass install-apache.yml
Résultat : 

image-1633871020711.png