Ansible

De Justine's wiki
Aller à la navigation Aller à la recherche

Présentation

Ansible est une plateforme logicielle libre pour la configuration et la gestion des ordinateurs. Elle combine le déploiement de logiciels multi-nœuds, l'exécution des tâches ad-hoc, et la gestion de configuration. Elle gère les différents nœuds à travers SSH et ne nécessite l'installation d'aucun logiciel supplémentaire sur ceux-ci. Les modules communiquent via la sortie standard en notation JSON et peuvent être écrits dans n'importe quel langage de programmation. Le système utilise YAML pour exprimer des descriptions réutilisables de systèmes, appelés playbook. Elle permet :

  • D'automatiser : déployer des applications, gérer des systèmes
  • De gagner du temps : grâce aux playbooks, on peut résoudre les problèmes une fois et partager facilement la solution
  • De collaborer : en créant une "culture de l'automatisation"
  • D'intégrer plus facilement en automatisant les technologies que l'on utilise déjà.

Mise en place

Source :

https://www.tartarefr.eu/ansible-par-la-pratique-premiere-partie-les-bases/

J'utilise deux machines :

  • Mon PC sous Ubuntu 18.10, sur lequel j'installe Ansible et sshpass
  • Une VM Debian basique, qui sera ma cible (192.168.1.49)

Avant toute chose, il faut que notre VM soit dans les known_hosts de la machine Ansible. Il suffit de s'y connecter une fois en ssh pour ajouter la clef !

Je commence par installer Ansible sur mon PC. Ensuite, je peux commencer à lancer une commande via Ansible :

justine@Justine-pc:/etc/ansible$ ansible 192.168.1.49 -m ping

Mais ça ne fonctionne pas : Ansible ne connait pas la cible, et on a pas d'utilisateur sur celle-ci !

Dans mon dossier home, je créée deux répertoires : prod et preprod, et dans chacun d'entre eux je met un fichier hosts.ini vierge. Ce fichier contiendra notre inventaire de machines.

Ensuite, dans preprod/hosts.ini, je mets :

[server]
192.168.1.49

[ansible]
localhost

Je peux ensuite rééessayer en précisant le répertoire de notre environnement et un utilisateur et ça fonctionne :

justine@Justine-pc:~/Ansible$ ansible -i ~/Ansible/preprod/hosts.ini 192.168.1.49 --user user --ask-pass -m ping
SSH password:
192.168.1.49 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Je peux tenter une commande :

justine@Justine-pc:~/Ansible$ ansible -i ~/Ansible/preprod/hosts.ini 192.168.1.49 --user user --ask-pass -a whoami
SSH password:
192.168.1.49 | CHANGED | rc=0 >>
user

Par défaut, Ansible utilise le même utilisateur que l'utilisateur local sur l'hôte distant. C'est pour cela qu'il faut bien gérer les utilisateurs. De plus, il faut penser que la connexion root en ssh est désactivée par défaut sur Debian !

Lancer une série de commandes

Le fichier permettant de lister les commande à lancer s’appelle un playbook. Il peut être monolithique ou divisé en plusieurs parties. Ansible recommande la séparation par rôle, ce qui permet de réutiliser les commandes d’un playbook et de les partager facilement avec la communauté.

Les rôles

Il faut bien réfléchir à la séparation des rôles qu'aura notre serveur, afin de garder une bonne modularité. Si on prend l'exemple d'un serveur web personnel qui contiendrait un blog Wordpress, un outil d'analyse de trafic web Piwik et du monitoring, on a déjà 3 rôles. Mais chacun de ces rôles en nécéssite d'autres (bdd, serveur web...), et que la machine doit rester à jour, on arrive a un grand nombre de rôles :

  •     system: concernera la post-installation du système
    •         Mettre le système à jour
    •         Définition des pools ntp (fr)
    •         Définition du nom d’hôte
    •         Définition basique du firewall: SSH (22)
    •         Redirection des mails locaux vers une adresse externe
    •         etc…
  •     pki: Concernera l’obtention et la mise à jour des certificats SSL
    •         Copie de nos clés privées
    •         Copies de nos fichiers et scripts gérant la pki (systemd)
  •     webserver: Concernera l’installation et la configuration d’apache
    •         Installation et configuration d’apache
    •         Mise à jour des extensions (ex modsecurity), hors RPM (les paquets RPMs seront mis à jour avec le rôle system)
    •         Ajout des ports HTTP (80) et HTTPS (443) au firewall
  •     database: Concernera l’installation et la configuration de mariadb
    •         Installation et configuration de mariadb
  •     blog: Concernera l’installation et la configuration de wordpress
    •         Installation et configuration du blog
    •         définition de l’alias ou du vhost pour le webserver
    •         import de la sauvegarde si elle existe
    •         Mise à jour des extensions, hors RPM (les paquets RPMs seront mis à jour avec le rôle system)
  •     webstat: Concernera l’installation et la configuration de piwik
    •         Installation et configuration de piwik
    •         définition de l’alias ou du vhost pour le webserver
    •         import de la sauvegarde si elle existe
  •     monitoring: Concernera l’installation et la configuration du monitoring
    •         Installation et configuration des outils
  •     ids: Concernera l’installation et la configuration des outils de détection et de vérification d’intrusion
    •         Installation et configuration des outils

Du coup, le changement d'un rôle impactera pas ou peu les autres, et on pourra facilement changer certaines choses. Changer de blog n'impactera pas le reste par exemple, mais changer de serveur web impactera les autres rôles.

Les Playbooks

Il s'agit de fichiers au format YAML, qui contient une succession de tâche à accomplir. Par défaut, une erreur sur l'une d'entre elles entraîne l'arrêt du processus. Il existe beaucoup de modules différents et la doc les présente tous :

https://docs.ansible.com/ansible/latest/modules/modules_by_category.html

À propos du YAML :

https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html

À propos des playbooks :

https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html#playbook-language-example

 

J'ai créé un playbook tout simple qui se contente d'installer apache2 :

#site.yml
---
- hosts: server #Je choisis mon hôte
  tasks:
    - name: update installation de serveur web #Je nomme ma tâche
      apt:  #Différentes commandes apt
        name: apache2
        force_apt_get: yes #Sinon, il utilise aptitude
        update_cache: yes
      become: true #Sert à utiliser sudo

Que je peux ensuite lancer :

justine@Justine-pc:~/Ansible/preprod$ ansible-playbook -i ~/Ansible/preprod/hosts.ini --user user --ask-pass --ask-become-pass site.yml
SSH password:
SUDO password[defaults to SSH password]:

PLAY [server] ******************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************
ok: [192.168.1.49]

TASK [update installation de serveur web] **************************************************************************************************

changed: [192.168.1.49]

PLAY RECAP *********************************************************************************************************************************
192.168.1.49               : ok=2    changed=1    unreachable=0    failed=0

Ici :

  • ansible-playbook -i ~/Ansible/preprod/hosts.ini : J'utilise un playbook en précisant l'environnement
  • --user user --ask-pass : utilisateur et demande de mot de passe pour ssh
  • --ask-become-pass : mot de passe pour sudo
  • site.yml : mon playbook

Si je relance le playbook, les tâches déjà effectuées seront ingorées. Cela évite les effets de bord : Les playbooks sont idempotents, c'est-à-dire qu'on peut bien les réutiliser si on veut ! Ici, je pourrais rajouter des fonctions à mon playbook et le relancer si j'en ai envie.

Chiffrer les variables des playbooks

Les playbooks peuvent s'avérer dangereux au niveau sécurité : si je dois donner un mot de passe à un utilisateur via un playbook, je ne vais pas par la suite le commit tel quel sur un dépôt public par la suite ! Pour ça, Ansible-vault propose deux façon de chiffrer les fichiers de variables :

  • Chiffrer tout le fichier de variables et utiliser les commandes ad-hoc pour éditer le fichier
  • Chiffrer seulement la valeur de la variable dans un fichier texte en clair

Chiffrer tout le fichier

On créée notre fichier chiffré et on inscrit notre variable une fois le fichier ouvert par l'éditeur par défaut (variable EDITOR) avec la commande :

justine@Justine-pc:~/Ansible/preprod$ ansible-vault create undossier/unfichierdevariables

#Je peux ensuite l'éditer :

justine@Justine-pc:~/Ansible/preprod$ ansible-vault edit undossier/unfichierdevariables

On peut aussi créer un fichier en clair et le chiffrer après :

echo 'mysql_root_password = "monsupermotdepasse"' > host_vars/server
ansible-vault encrypt host_vars/server

Chiffrer la valeur de la variable

On chiffre la valeur :

ansible-vault encrypt_string --vault-id @prompt 'monsupermotdepasse' --name 'mysql_root_password' >> host_vars/server
New vault password (default):
Confirm vew vault password (default):
Encryption successful

Mais je n'ai pas trop compris ce point-là...

Un playbook plus abouti

Le playbook suivant donne une idée un peu complète des possibilités offertes par l'outil, et devrait parler de lui-même.

Fichier de variables

``` --- name: johndoe

  1. pubkey est un lien vers un git de type https://mongit.fr/user.keys
  2. Il faut bien sûr avoir au préalable injecté une clef dans le git en question

pubkey: https://book.innertech.ovh/johndoe.keys file: /home/justine/Nextcloud/Ansible/resultat.txt inventoryfile: /home/justine/Nextcloud/Ansible/inventaire.txt ```