TUTOS.EU

Première exemple d'utilisation de Ansible de A à Z


Cet article est là pour vous permettre d'avoir un premier exemple fonctionnel d'Ansible.

Il a été écrit après avoir visionné plusieurs des 127 vidéos de la playlist dédiée de xavki (trop long de tout regarder pour un premier essai),

Découverte de Ansible (très bien, un exemple de fou, des idées sur ce qu'on peut en faire, mais il manque du détail si on veut appliquer from scratch),

you need to learn ansible right now de NetworkChuck (bien mais il se connecte avec un login/mot de passe d'un compte root de base)

et une partie du getting_started de ansible.com


Le serveur Ansible s'installe obligatoirement sur une machine Linux.
Ansible fonctionnant sans agent, il va lui falloir les droits sur les machines cibles.
Pour cela on va ici créer un compte dédié sur la machine cible.

Avec les commande suivante, on passe root, on crée le compte

sudo -i
useradd -m myaccount4ansible
passwd myaccount4ansible
Lien vers le fichier : cliquez ici

Toujours sur la machine cible, on va donner les droits sudo à ce compte, sans qu'il ait à saisir un mot de passe pour cela.

Pour ce faire on va créer un fichier nommé admin sous /etc/sudoers.d avec nano

nano /etc/sudoers.d/admins
Lien vers le fichier : cliquez ici

Mettez y ceci

myaccount4ansible     ALL=(ALL)   NOPASSWD:ALL
Lien vers le fichier : cliquez ici

Il est préférable d'éviter d'utiliser un login/mot de passe.
Le mieux est de se connecter avec une clé SSH.
Toujours sur la machine cible, éditer la configuration du service SSH avec

nano /etc/ssh/sshd_config
Lien vers le fichier : cliquez ici

Au niveau du paramètre AllowGroups, ajouter celui qui correspond au compte utilisé par Ansible.
Cela permettra à votre compte de se connecter en ssh

Exemple :

AllowGroups myaccount4ansible
Lien vers le fichier : cliquez ici

A la fin du fichier, ajouter également une directive particulière pour que votre compte puisse s'authentifier avec une clé (ainsi qu'un mot de passe)

Match Group myaccount4ansible
PasswordAuthentication yes
PubKeyAuthentication yes
Lien vers le fichier : cliquez ici

On peut ajouter des contraintes sur l'ip source par exemple.
On trouve des informations en cherchant match dans https://man7.org/linux/man-pages/man5/sshd_config.5.html

Match Group myaccount4ansible Address 172.16.1.*
PasswordAuthentication yes
PubKeyAuthentication yes
Lien vers le fichier : cliquez ici

Redémarrer le service ssh pour prise en compte

systemctl restart sshd
Lien vers le fichier : cliquez ici

Maintenant, sur le serveur Ansible, passer sur le compte qui sera utilisé pour lancer les commandes

su -l ansible
Lien vers le fichier : cliquez ici

Si vous n'avez pas déjà une clé ssh, générez la avec

ssh-keygen -t ecdsa -b 521
Lien vers le fichier : cliquez ici

Il vous sera demandé un nom de fichier.
Ici le compte se nomme test donc j'ai nommé la clé testkey.
Elle sera placée à la racine du home du compte.

Vous trouverez deux fichiers, avec un en .pub pour la clé publique, et l'autre sans extension pour la clé privée.

On va maintenant charger votre clé privée dans un agent.
Vérifiez qu'il n'y en a pas un de lancé avec

ssh-add -l
Lien vers le fichier : cliquez ici

Si il n'est pas lancé vous devez avoir le message
Could not open a connection to your authentication agent

Lancez l'agent et ajoutez y votre clé privée.
Ici elle s'appelle testkey

eval `ssh-agent`
ssh-add testkey
Lien vers le fichier : cliquez ici

Déclarez votre clé publique sur le serveur à piloter avec Ansible avec la commande ssh-copy-id.
Pour que la commande fonctionne, vous devez avoir chargé votre clé privée au préalable avec la commande ssh-add sous peine d'avoir l'erreur
/usr/bin/ssh-copy-id: ERROR: failed to open ID file '/home/test/testkey': No such file

192.168.0.170 est l'ip de la machine où déclarer la clé et myaccount4ansible est le compte sur lequel la copier

ssh-copy-id -i testkey.pub myaccount4ansible@192.168.0.170
Lien vers le fichier : cliquez ici

Testez la connexion sur la machine cible.

ssh 'myaccount4ansible@192.168.0.170'
Lien vers le fichier : cliquez ici

En aparté voici des choses que l'on m'a indiqué pour ne pas à avoir à lancer un agent avec ces commandes :
eval `ssh-agent`
ssh-add testkey

 

avoir sa clé publique dans
cd
cat .ssh/authorized_keys

 

Dans /etc/ssh/sshd_config faire ces réglages (PAM veut dire Pluggable Authentication Modules, des librairies pour authentifier un utilisateurs sur des application ou services) :

UsePAM yes

 

Toujours dans /etc/ssh/sshd_config, éventuellement decommenter cette ligne mais par défaut c'est à Yes

PubkeyAuthentication yes

 

decommenter
AuthorizedKeysFile      .ssh/authorized_keys
 

Régler ce paramètre ainsi :

PermitRootLogin prohibit-password
 

commenter

#GSSAPIKeyExchange no
#GSSAPIEnablek5users no

dans

# GSSAPI options
#GSSAPIAuthentication yes
#GSSAPICleanupCredentials no
#GSSAPIStrictAcceptorCheck yes
GSSAPIKeyExchange no
GSSAPIEnablek5users no

 


Sur le serveur, installez simplement ansible avec

sudo apt install ansible
Lien vers le fichier : cliquez ici

Vérifiez la version avec

ansible --version
Lien vers le fichier : cliquez ici

Editez ansible.cfg

nano /etc/ansible/ansible.cfg
Lien vers le fichier : cliquez ici

Décommentez cette ligne pour ne pas à avoir à valider les fingerprint

host_key_checking = False

D'autres options pour ansible.cfg sont expliquées sur https://youtu.be/8Hb-i9lXdXA?t=368
On y parle par exemple de l'outil ansible-config, mais il n'est pas nécessaire ici.

A propos de ansible-config, j'ai tout de même noté que ansible-config list donne tous les paramètres que l'on peut configurer.

xavki en parle ici. Il donne ces choses à modifier.

 

On peut par exemple avoir la durée de chaque task avec
[defaults]
callback_whitelist = profile_tasks

 

Pour gagner en temps d exécution, mettre :
[ssh_connection]
pipelining = True

 

Partager plusieurs sessions pour une même connection et mettre un peu de persistence
[ssh_connection]
ssh_args = -o ControlMaster=auto -o Controlpersist=60s

 

ajouter éventuellement ceci :
-o PreferredAuthentications=publickey

 

Pour gérer 30 serveurs à la fois
[defaults]
forks = 30

 

 


Editez le fichier hosts

nano /etc/ansible/hosts
Lien vers le fichier : cliquez ici

On fait un groupe de machines nommé [linux]
On y place l'ip de notre machine cible
On indique également le login à utiliser pour se connecter

Faites un premier est simple avec un ping de la machine cible

ansible linux -m ping
Lien vers le fichier : cliquez ici

Vous devez avoir un retour en vert

Si vous avez un permission denied c'est peut être tout simplement que vous n'avez pas lancez votre agent ssh ni ajouté votre clé privée dedans (commandes eval `ssh-agent` et ssh-add)

Vous pouvez aussi lancer une commande, comme cat.
Ici on utilise cat pour avoir le type d'OS

ansible linux -a "cat /etc/os-release"
Lien vers le fichier : cliquez ici

Au lieu de lancer une commande, on peut demander à jouer un playbook, un recueil, une liste de choses à faire. Ils sont au format yml

On va en créé un avec

nano /etc/ansible/oneplaybook.yml
Lien vers le fichier : cliquez ici

Placez ceci dans le code.
Cela va installer nano sur la machine cible si le programme n'est pas présent.

---
 - name: lejob
   hosts: linux
   tasks:
    - name: check nano
      become: yes
      become_method: sudo
      apt:
       name: nano
       state: latest
Lien vers le fichier : cliquez ici

Pour jouer son contenu, taper

ansible-playbook /etc/ansible/oneplaybook.yml
Lien vers le fichier : cliquez ici

Le résultat est ici en vert, du coup c'est bon signe.
On a ok=2 pour dire qu'on a bien réussi à passer sudo et à faire l'installation de nano
changed=0 indique qu'il n'y a pas eu de modification, cad que nano était déjà installé.

Voici le détail du contenu du playbook

Attention l'indentation est très importante dans un fichier yml
L'indentation ce sont les retraits, les espaces et tabulations situés à gauche des lignes

Dans cet exemple j'ai écrit
---
- name: lejob


au lieu de
---
 - name: lejob

Le pire, c'est que le bug que cela provoque n'est pas indiqué à la bonne ligne.
Le programme indique ici à tort que l'erreur est au niveau de "hosts: linux"

Comme montré sur https://www.toptechskills.com/ansible-tutorials-courses/ansible-yum-module-tutorial-examples/#when-to-use-the-yum-module-vs-package-module

On peut filtrer sur la distribution, et utiliser apt sur une debian ou yum sur centos
Exemple :

---
 - name: install nano on centos
   hosts: linux
   tasks:
    - name: check nano
      become: yes
      become_method: sudo
      yum:
       name: nano
       state: latest
       update_cache: true
      when: ansible_os_family == 'RedHat'

 - name: install nano on Debian
   hosts: linux
   tasks:
    - name: check nano
      become: yes
      become_method: sudo
      apt:
       name: nano
       state: latest
       update_cache: true
      when: ansible_os_family == 'Debian'
Lien vers le fichier : cliquez ici

On peut créer un utilisateur avec

---
 - name: Create account
   hosts: linux
   become: yes
   become_method: sudo
   tasks:
    - name: Creation d'un user
      ansible.builtin.user:
       name: unuseransible
       shell: /bin/bash
       createhome: yes
       append: yes
       state: present
    - name: set du primary group
      ansible.builtin.user:
       name: unuseransible
       groups: unuseransible
       group: unuseransible
Lien vers le fichier : cliquez ici
---
 - name: Replace line in file examples
   hosts: linux
   tasks:
   - name: "Replace line in file apache conf"
     become: yes
     become_method: sudo
     replace:
       path: /home/myuser/test
       regexp: '(^ServerName\s)(.*)$'
       replace: '\1www.newdomain.com'
       backup: yes
Lien vers le fichier : cliquez ici

On peut déclencher une action si une ligne a été changée

---
   - name: "reglage du compte admin dans /opt/tomcat/conf/tomcat-users.xml"
     replace:
       path: /opt/tomcat/conf/tomcat-users.xml
       regexp: '(^(\s+)?<user username="admin")(.*)$'
       replace: '  <user username="admin" password="lepassword" roles="manager-gui,admin-gui"/>'
       backup: no
     register: result
   - name: "Restart service tomcat"
     ansible.builtin.service:
       name: tomcat
       state: restarted
     when: result.changed
Lien vers le fichier : cliquez ici

On peut aussi vérifier qu'une ligne existe avec le module lineinfile dont la page est
https://docs.ansible.com/ansible/2.4/lineinfile_module.html

et ce site donne des exemples d'utilisation :
https://www.middlewareinventory.com/blog/ansible-lineinfile-examples/

---
 - name: Lineinfile example
   hosts: linux
   become: yes
   become_method: sudo
   tasks:
   - name: "lineinfile module example"
     lineinfile:
       path: /home/myuser/test
       line: "parametre 1"
       state: present
       backup: no
Lien vers le fichier : cliquez ici

Du coup, on peut mixer les 2 et modifier un paramètre existant et le créer le cas échéant

---
 - name: Replace line in file examples
   hosts: linux
   become: yes
   become_method: sudo
   tasks:
   - name: "si le parametre existe on change son reglage"
     replace:
       path: /home/myuser/test
       regexp: '(^(\s+)?(#+)?LogLevel\s)(.*)$'
       replace: 'LogLevel debug'
       backup: no
   - name: "creation de la ligne si inexistante"
     lineinfile:
       path: /home/myuser/test
       line: "LogLevel debug"
       state: present
       backup: no
Lien vers le fichier : cliquez ici