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.
Au niveau des prérequis, on va commencer par faire le nécessaire sur une machine cible qui sera gérée par Ansible.
Ansible fonctionnant sans agent, il faut que son compte ait les droits dessus.
On va y créer un compte dédié.
Donc sur une machine cible, avec les commandes suivantes, on passe root et on crée le compte que va utiliser Ansible.
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
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 la commande ci-dessous.
ssh-keygen -t ecdsa -b 256
Lien vers le fichier : cliquez ici
Notez que l'article https://nbeguier.medium.com/a-real-world-comparison-of-the-ssh-key-algorithms-b26b0b31bfd9
préconise Ed25519 au lieu de ECDSA
ssh-keygen -t ed25519 -b 256 -f <fichier de clé ECDSA>
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
Lien vers le fichier : cliquez ici
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
Lien vers le fichier : cliquez ici
Toujours dans /etc/ssh/sshd_config, éventuellement decommenter cette ligne mais par défaut c'est à Yes
PubkeyAuthentication yes
Lien vers le fichier : cliquez ici
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
Comme indiqué sur la doc officielle, ansible peut s'installer avec python.
Contrôler la présence de python3 en demandant d'afficher la version :
python3 -V
Lien vers le fichier : cliquez ici
Si nécessaire, vous pouvez installer python3 avec l'une de ces commandes :
sudo apt install python3
sudo yum install python3
Lien vers le fichier : cliquez ici
Tout cela pour dire qu'on peut alors installer ansible avec
python3 -m pip install --user ansible
Lien vers le fichier : cliquez ici
Problème du fichier ansible.cfg absent
Avec une installation avec python3 je me suis retrouvé sans fichier ansible.cfg
D'après ce post je ne suis pas le seul à avoir eu le problème.
On peut vérifier l'existence du fichier de configuration avec la commande ansible --version
Si config file est à 'None' c'est qu'il n'existe pas. Exemple :
[ansible@MYSERVER ~]$ ansible --version
ansible [core 2.14.4]
config file = None
configured module search path = ['/home/ansibleio/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/ansibleio/.local/lib/python3.9/site-packages/ansible
ansible collection location = /home/ansibleio/.ansible/collections:/usr/share/ansible/collections
executable location = /home/ansibleio/.local/bin/ansible
python version = 3.9.14 (main, Nov 7 2022, 00:00:00) [GCC 11.3.1 20220421 (Red Hat 11.3.1-2)] (/usr/bin/python3)
jinja version = 3.1.2
libyaml = True
A ce sujet la doc indique qu'on peut générer le fichier dans son homefolder avec la commande
cd
ansible-config init --disabled -t all > ansible.cfg
sudo mkdir /etc/ansible
sudo chown root:votrecompteansible ansible.cfg
sudo chown root:votrecompteansible /etc/ansible
sudo mv ansible.cfg /etc/ansible/
sudo chmod 660 /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
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
Comme montré sur https://ansible-tips-and-tricks.readthedocs.io/en/latest/modifying-files/modifying-files/#using-regex
On peut modifier le paramètre d'une ligne
---
- 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