Try   HackMD

Fiche Aide Ansible

Ansible Playbook

Configuration des hotes

Ajout des clés SSH sur les clients

Génération d'une clé SSH :

ssh-keygen -t rsa -b 4096 -f .ssh/ansible_master

Voir le tutoriel

Ajout de la clé sur un client :

ssh-copy-id -i .ssh/ansible_master root@192.168.1.1
ssh-copy-id -i .ssh/ansible_master hyperion@192.168.1.2

Commande de tests

ssh root@192.168.1.1
^D
ssh hyperion@192.168.1.2
^D

Si l'injection a fonctionné, on n'a pas besoin de taper de mot de passe pour se connecter

Malgré que le compte soit dans le groupe sudo, il nécessite toujours de taper un mot de passe pour
Les commandes nécessitant une élévation de privilège. Pour la retirer, il faut : sudo visudo

- %sudo   ALL=(ALL:ALL) ALL
+ %sudo   ALL=(ALL:ALL) NOPASSWD: ALL

Inventaire des clients

Fichier par défaut du système : /etc/ansible/hosts

[mes_servers]   # Pas d'espace entre le texte et les crochets

192.168.1.1 ansible_user=root  # Pour préciser à Ansible l'utilisateur à utiliser
192.168.1.2

Fichier d'inventaire par projet : [ A compléter ]

Liste des commandes ansible basiques

Réalisation d'un ping

Réaliser un ping sur tous les clients

ansible all -m ping
Option Arguments Description
-m ping Charge le module en argument
None all Selectionne toutes les IP du fichier d'inventaire

Récupération de la configuration

ansible 192.168.1.1 -m setup -a "filter=*python*"
Option Arguments Description
None 192.168.1.1 IP du client à utiliser
-m setup Charge le module shell
-a "filter=*python*" Filtre les résultats en fonction de leur clé

Elevation de privilège

ansible 192.168.1.1 -m shell -a "fdisk -l" -b -K
Option Arguments Description
None 192.168.1.1 IP du client à utiliser
-m shell Charge le module shell
-b None Elevation de privilège sudo
-K None Demande le mot de passe sudo dans stdin

Note : Eviter les modules shell et raw dans les playbooks car ils ne sont pas idempotents

Envoyer un fichier

# Création d'un fichier pour le test
echo "Hello World!" > test.txt

ansible all -m copy -a "src=test.txt dest=/home/hyperion/ansible owner=hyperion mode=0644"  
Option Arguments Description
None all Utilise toutes les IP présentes dans l'inventaire
-m copy Charge le module copy pour la copie de fichier
-a "src=test.txt " Précise les paramètres de commande pour le module

Recevoir un fichier

ansible all -m fetch -a "src=/etc/passwd dest=/tmp flat=yes"

ls /tmp  # Une copie du fichier passwd doit se trouver dans le /tmp du master 
Option Arguments Description
None all Utilise toutes les IP présentes dans l'inventaire
-m fetch Charge le module fetch pour télécharger des fichiers
-a "src=test.txt " Précise les paramètres de commande pour le module

Installation packages

Ouvrir le port HTTP pour nginx : article

  • ajouter nginx dans le fichier /etc/services aux lignes commencant par http:
- http    80/tcp    www www-http  # WorldWideWeb HTTP
- http    80/udp    www www-http  # HyperText Transfert Protocol
+ http    80/tcp    www www-http nginx # WorldWideWeb HTTP
+ http    80/udp    www www-http nginx # HyperText Transfert Protocol

=> Problème rencontré pour le Lab4 de la formation Ansible

Installation de nginx dans deux clients (Debian et Centos 7)
Dans un fichier playbook nginx.yml

---

- name: Nginx server installed
  hosts: demoservers
  become: yes
  tasks:
  - name: Add epel-release repo
    yum:
      name: epel-release
      state: present
    when: ansible_facts['os_family'] == "RedHat"

  - name: latest Nginx version installed Centos
    yum:
      name: nginx
      state: present
    when: ansible_facts['os_family'] == "RedHat"

  - name: latest Nginx version installed Debian
    apt:
      name: nginx
      state: latest
    when: ansible_facts['os_family'] == "Debian"

  - name: Nginx enable and running Centos
    service:
      name: nginx
      enabled: true
      state: started
    when: ansible_facts['os_family'] == "RedHat"

  - name: Add nginx index template
    copy:
      src: index.html
      dest: /var/www/html/
    when: ansible_facts['os_family'] == "Debian"

  - name: Nginx enable and running Debian
    systemd:
      name: nginx
      enabled: true
      state: started
    when: ansible_facts['os_family'] == "Debian"

OS_Family vs Distribution : Lien Article

Gestion des variables

Les variables peuvent être définies de deux manières:

  • Directement dans le fichier
vars:
  user: admin
  group: wheel
  • Dans un fichier séparé
# Fichier dédié
---
user: admin
group: wheel
# Dans le fichier principal
vars_files:
- vars/users.yml 

Arborescence du projet :

|- webserver.yml
|- group_vars
  |- demoservers  # Un groupe d'hotes défini dans l'inventaire
|- host_vars
  |- 192.168.1.1  # Un hote existant dans l'inventaire
|- html
  |- dev_index.html
  |- prod_index.html

webserver.yml

---
- name: Copy index.html
  hosts: demoservers
  become: yes
  tasks:
  - name: copy right index.html
    copy:
      src: "html/{{ stage }}_index.html"
      dest: /var/www/html/index.html

group_vars/demoservers

---
stage: dev

host_vars/192.168.1.1

---
stage: prod

Valeur de retour

Documentation

Dans le playbook :

---
- name: Installs a package and prints the result
  hosts: dbservers
  become: True
  tasks:
  - name: Install the package
    yum:
      name: git
      state: present
      update_cache: yes
    register: install_result  # Récupération du stdout
    
- debug: var=install_result.result

install_result est un dictionnaire et peut être déréférencé.

Valeur dans le playbook

---
- name: Create users
  hosts: all
  become: yes
  vars:
    user: admin
    group: wheel
    homedir: /dev/null
    shell: /bin/false
  tasks:
  - user:
      name: "{{ user }}" # Avec ou sans espace entre la variable et les accolades
      group: "{{ group }}"
      home: "{{ homedir }}"
      shell: "{{ shell }}"

Utilisation des facts

---
- name: Output facts within a playbook
  hosts: webservers
  tasks:
  - name: Prints Ansible facts
    debug:
      msg: The default IPv4 address of {{ ansible_fqdn }} is {{ ansible_enp0s3.ipv4.address }}
ok: [192.168.1.1] => {
"msg": "The default IPv4 address of debian is 192.168.1.1"
}
ok: [192.168.1.2] => {
"msg": "The default IPv4 address of localhost.localdomain is 192.168.1.Z"
}

Les boucles

---
- name: Loop demo
  hosts: 192.168.1.92
  vars:
    check_services:
    - nginx
    - sshd
  tasks:
  - name: Check if service is started
    service:
      name: "{{ item }}"
      state: started
    loop: "{{ check_services }}" # Iteration sur chaque élement

Conditions multiples

---
- name: MySQL server installation
  hosts: all
  become: yes
  tasks:
  - name: Install latest MySQL server when host RAM greater than 1 GB with YUM
    yum:
      name: mysql-server
      state: latest
    when: ansible_facts['os_family'] == "RedHat" and ansible_memtotal_mb > 1024
  - name: Install latest MySQL server when host RAM greater than 1 GB with APT
    apt:
      name: mysql-server
      state: latest
    when: ansible_facts['os_family'] == "Debian" and ansible_memtotal_mb > 1024

Handlers/Trigger

---
- name: Manage Nginx
  hosts: 192.168.1.57
  become: yes
  tasks:
  - name: Copy Nginx configuration file
    copy:
      src: conf/default.conf
      dest: /etc/nginx/sites-enabled/
    notify:
    - restart_nginx # Si l'état est "changed", le handler sera appelé
  handlers:
  - name: restart_nginx
    service:
      name: nginx
      state: restarted

Les templates

test_server.yml

---
- hosts: demoservers
  gather_facts: yes
  become: yes
  tasks:
    - name: Install index.html
      template:
        src: html/index.html.j2
        dest: /var/www/html/index.html
        mode: 0644

html/index.html.j2

<html>
    <h1>Hostname: {{ ansible_fqdn | default('undefined') }}</h1>
    <center>
        <ul>
            <li>System : {{ ansible_os_family | default ('linux') }}</li>
            <li>Type : {{ stage | upper }}</li>
            <li>Stage : {{ stage | replace("prod", "Production") |
                replace("dev", "Development" }}</li>
        </ul>
    </center>
</html>

Documentation Jinja2

Ansible Galaxy

Création d'un role

ansible-galaxy init nginx

Cette commande génère une arborescence de dossier de fichier à la manière de
django startapp nginx avec les structures essentielles à la déclaration d'un rôle

├── nginx
│   ├── README.md
│   ├── defaults
│   │   └── main.yml
│   ├── files
│   ├── handlers
│   │   └── main.yml
│   ├── meta
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   ├── templates
│   ├── tests
│   │   ├── inventory
│   │   └── test.yml
│   └── vars
|       └── main.yml