Resources attached to the Road To DevOps tutorial https://blog.noobtoroot.xyz/road-to-devops/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

15 KiB

Logo Ansible

Playbooks Ansible

Jouer et rejouer facilement un jeu de commandes prédéfini sur un ensemble de machines.

Schéma archi globale

Format du Playbook

  • Il se présente sous la forme d'un simple fichier texte au format yaml.

  • Il peut donc être facilement versionné dans un outil de gestion de version.

yaml

  • Format ouvert de représentation de données.

  • Acronyme récursif de YAML Ain't Markup Language.

  • Permet de représenter des données complexes tout en conservant une excellente lisibilité.

  • Utilisation en forte progression ces dernières années.
    Ansible, GitLab, Docker Compose, Kubernetes manifests, etc...

  • Site officiel : https://yaml.org/

YAML basics

https://fr.wikipedia.org/wiki/YAML

  • attention ! l'indentation se fait avec un ou plusieurs espaces, jamais avec des tabulations !

  • Les commentaires sont signalés par le signe dièse # et se prolongent sur toute la ligne.

  • Les éléments de listes sont dénotés par le tiret -, suivi d'une espace, à raison d'un élément par ligne.

  • Les tableaux sont de la forme clé: valeur, à raison d'un couple par ligne.

YAML basics

https://fr.wikipedia.org/wiki/YAML

  • Les chaînes de caractères peuvent être entourées de guillemets doubles ", ou simples ', sachant qu'un guillemet s'échappe avec un antislash \, alors qu'une apostrophe s'échappe avec une autre apostrophe.

  • Les chaînes de caractères peuvent de plus être représentées par un bloc indenté avec des modificateurs facultatifs pour conserver | ou éliminer > les retours à la ligne.

  • Plusieurs documents rassemblés dans un seul fichier sont séparés par trois traits d'union ---.

YAML basics

https://fr.wikipedia.org/wiki/YAML

---
receipt:     Oz-Ware Purchase Invoice
date:        2012-08-06
customer:
    given:   Dorothy
    family:  Gale

items:
    - part_no:   A4786
      descrip:   Water Bucket (Filled)
      price:     1.47
      quantity:  4

    - part_no:   E1628
      descrip:   High Heeled "Ruby" Slippers
      size:      8
      price:     100.27
      quantity:  1

bill-to:  &id001
    street: |
            123 Tornado Alley
            Suite 16
    city:   East Centerville
    state:  KS

ship-to:  *id001

specialDelivery:  >
    Follow the Yellow Brick
    Road to the Emerald City.
    Pay no attention to the
    man behind the curtain.
...

yaml - Définition d’une collection (-)

# Une liste de fruits
fruits:
  - pomme
  - orange
  - framboise
  - mangue

Forme abrégée :

# Une liste de fruits
fruits: ['pomme', 'orange', 'framboise', 'mangue']

Définition d’un dictionnaire (key: value)

# Un utilisateur
martin:
  name: Martin Dupond
  job: developer
  skill: python

Forme abrégée :

# Un utilisateur
martin: { name: Martin Dupond, job: developer, skill: python }

Tasks

  • Les commandes d'un Playbook sont découpées en instructions unitaires appelées tâches (tasks).

  • Chaque tâche exécute un module Ansible avec des paramètres spécifiques.

  • Format d'une tâche :

- name: Description de la tâche
  <nom-du-module>:
    <paramètre-1>: <valeur-1>
    <paramètre-2>: <valeur-2>
    <paramètre-3>: <valeur-3>

Liste de tâches

  • Un playbook peut décrire une liste de plusieurs tâches.

  • Les tâches seront exécutées dans l'ordre d'apparition et de façon séquentielle sur chacune des machines cibles.

tasks:   <----------------------------- liste de tâche

  - name: Ma tâche 1   <--------------- tâche 1
    <nom-du-module>:
      <paramètre-1>: <valeur-1>
      <paramètre-2>: <valeur-2>
      <paramètre-3>: <valeur-3>

  - name: Ma tâche 2   <--------------- tâche 2
    <nom-du-module>:
      <paramètre-1>: <valeur-1>
      <paramètre-2>: <valeur-2>

Exemple réel

- hosts: web   # exécution d'un 'Play' sur le groupe 'web'
  tasks:
   - name: Installation of Apache Package   # tâche 1
     yum:
       name: httpd
       state: present
       update_cache: yes

   - name: Ensure Apache is running (and enabled at boot)   # tâche 2
     service: name=httpd state=started enabled=yes
  • Ici on mixe les deux types de syntaxes (normale et abrégée).
  • Les bonnes pratiques préconisent l'utilisation de la syntaxe normale.

Exemple réel

avec syntaxe normale

- hosts: web
  tasks:
   - name: Installation of Apache Package
     yum:
       name: httpd
       state: present
       update_cache: yes

   - name: Ensure Apache is running (and enabled at boot)
     service:
       name: httpd
       state: started
       enabled: yes

Notion de Play

---
- hosts: webservers   # Play 1 sur le groupe webservers
  tasks:
  - name: My task
    ...

- hosts: databases    # Play 2 sur le groupe databases
  tasks:
  - name: My task...
    ...
  • Chaque Play contient sa propre liste de tâches et cible un ensemble spécifique de machines.

Lancer un playbook

$ ansible-playbook <fichier-playbook> -i <fichier-inventaire>

$ ansible-playbook playbook.yaml -i ./hosts

PLAY [web] *******************************************************************

TASK [setup] *****************************************************************
ok: [web1.formation.sii.fr]
ok: [web2.formation.sii.fr]

TASK [Installation du package Apache] ****************************************
changed: [web2.formation.sii.fr]
changed: [web1.formation.sii.fr]

TASK [Ensure Apache is running (and enable it at boot)] **********************
changed: [web1.formation.sii.fr]
changed: [web2.formation.sii.fr]

PLAY RECAP *******************************************************************
web1.formation.sii.fr      : ok=3    changed=2    unreachable=0    failed=0
web2.formation.sii.fr      : ok=3    changed=2    unreachable=0    failed=0
* Notre Playbook comportait 2 tâches seulement, nous en voyons 3 !
  • Ansible a automatiquement ajouté à l'exécution une tâche nommée setup dont l'objectif est de récupérer les facts des machines cibles.

Récapitulatif du Playbook

PLAY RECAP *******************************************************************
web1.formation.sii.fr      : ok=3    changed=2    unreachable=0    failed=0
web2.formation.sii.fr      : ok=3    changed=2    unreachable=0    failed=0
  • Sur les 2 machines cibles :

    • ok : 3 tâches ont été exécutées avec succès.
    • changed : 2 tâches ont modifié l'état du système.
    • unreachable : Toutes les machines étaient joignables.
    • failed : Aucune tâche n'a échoué.

Relancer un playbook

$ ansible-playbook playbook.yaml -i ./hosts --become

PLAY [web] *******************************************************************

TASK [setup] *****************************************************************
ok: [web1.formation.sii.fr]
ok: [web2.formation.sii.fr]

TASK [Installation du package Apache] ****************************************
ok: [web1.formation.sii.fr]
ok: [web2.formation.sii.fr]

TASK [Ensure Apache is running (and enable it at boot)] **********************
ok: [web1.formation.sii.fr]
ok: [web2.formation.sii.fr]

PLAY RECAP *******************************************************************
web1.formation.sii.fr      : ok=3    changed=0    unreachable=0    failed=0
web2.formation.sii.fr      : ok=3    changed=0    unreachable=0    failed=0

Première exécution

PLAY RECAP *******************************************************************
web1.formation.sii.fr      : ok=3    changed=2    unreachable=0    failed=0
web2.formation.sii.fr      : ok=3    changed=2    unreachable=0    failed=0

Seconde exécution

PLAY RECAP *******************************************************************
web1.formation.sii.fr      : ok=3    changed=0    unreachable=0    failed=0
web2.formation.sii.fr      : ok=3    changed=0    unreachable=0    failed=0

Ordre d'exécution

  • Il est possible de contrôler l'ordre dans lequel les machines cibles sont adressées.

  • L'ordre par défaut est l'ordre d'apparition dans l'inventaire.

- hosts: all
  order: sorted   # l'ordre est défini ici
  gather_facts: False
  tasks:
    - debug:
        var: inventory_hostname

Ordre | Description

  •               | -
    

inventory | Ordre d'apparition dans l'inventaire. C'est le choix par défaut. reverse_inventory | Ordre inverse d'apparition dans l'inventaire. sorted | Ordre alphabétique des noms de machines. reverse_sorted | Ordre alphabétique inverse des noms de machines. shuffle | Ordre aléatoire.

Démarrer l'exécution à un endroit précis

$ ansible-playbook playbook.yaml --start-at-task="my task"

Cette commande démarre l'exécution du playbook à partir de la tâche nommée my task.

https://docs.ansible.com/ansible/latest/user_guide/playbooks_startnstep.html

Ignorer le code de retour d'une commande

  • Les modules command et shell sont sensibles au code de retour des commandes.

  • Pour ignorer les erreurs sur une commande qui renvoie un code > 0 on peut utiliser ignore_errors.

  • Ou, utiliser failed_when.

  • De même, changed_when peut être utilisé.

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True

Déclaration de variables

- hosts: web
  vars:
   - app_directory: /var/www/html
   - app_user: apache
   - app_group: apache

  tasks:
   - name: Modify permission on {{ app_directory }}
     file:
       dest: '{{ app_directory }}'
       mode: 0755
       owner: '{{ app_user }}'
       group: '{{ app_group }}'
       recurse: yes

Les variables sont déclarées dans vars
et résolues avec {{ }}.

$ ansible-playbook playbook.yaml -i ./hosts

PLAY [web] ****************************************************************

TASK [setup] **************************************************************
ok: [web1.formation.sii.fr]
ok: [web2.formation.sii.fr]

TASK [Modify permission of directory /var/www/html] ***********************
changed: [web1.formation.sii.fr]
changed: [web2.formation.sii.fr]

PLAY RECAP ****************************************************************
web1.formation.sii.fr      : ok=2    changed=1    unreachable=0    failed=0
web2.formation.sii.fr      : ok=2    changed=1    unreachable=0    failed=0

Les handlers et les notify

- hosts: web
  vars:
    - apache_listen_port: 8080

  tasks:
   - name: Modify Apache configuration
     lineinfile:
       dest: /etc/httpd/conf/httpd.conf
       regexp: '^Listen '
       line: 'Listen {{ apache_listen_port }}'
     notify: Reload Apache   # Signale que la configuration
                             # d'Apache doit être rechargée
  handlers:
   - name: Reload Apache     # Recharge la configuration
     service:
       name: httpd
       state: reloaded
$ ansible-playbook playbook.yaml -i ./hosts

PLAY [web] *******************************************************************

TASK [setup] *****************************************************************
ok: [web1.formation.sii.fr]
ok: [web2.formation.sii.fr]

TASK [Modify Apache configuration] *******************************************
changed: [web1.formation.sii.fr]
changed: [web2.formation.sii.fr]

RUNNING HANDLER [Reload Apache] *********************************************
changed: [web1.formation.sii.fr]
changed: [web2.formation.sii.fr]

PLAY RECAP *******************************************************************
web1.formation.sii.fr      : ok=3    changed=2    unreachable=0    failed=0
web2.formation.sii.fr      : ok=3    changed=2    unreachable=0    failed=0

Idempotence

  • L'idempotence signifie qu'une opération a le même effet qu'on l'applique une ou plusieurs fois.

  • Les commandes d'un Playbook doivent être écrites de manière à produire le même résultat quel que soit le nombre de fois où elles sont exécutées sur une même cible.

Travaux pratiques

Travaux pratiques

TP Ansible : playbooks

Variables sur la ligne de commande

Il est possible d'initialiser des variables directement sur la ligne de commande avec l'option --extra-vars (ou -e).

  • Ces variables peuvent être définies sous la forme :

    • chaîne de caractères

    $ ansible-playbook playbook.yaml --extra-vars "my_var_1=foo my_var_2=bar"

    • json

    $ ansible-playbook playbook.yaml --extra-vars '{"my_var_1":"foo","my_var_2":"bar"}'

    $ ansible-playbook playbook.yaml --extra-vars '{"my_var":"foo","my_list":["foo","bar"]}'

  • Utilisez le fomat json si vous voulez passer autre chose que des strings :

    • booleans
    • integers
    • floats
    • lists
    • ...

Découper un Playbook

  • Un Playbook peut se présenter sous la forme d'un fichier unique.

  • Toutefois il est possible de le découper en plusieurs fichiers séparés afin de mieux organiser et favoriser la ré-utilisation de certaines parties.

  • Il existe plusieurs manières de découper un Playbook :
    les includes, les imports, et les roles.

https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse.html

Includes et Imports

  • Disponibles à partir de Ansible v2.4.

  • Permettent le découpage des tâches d'un gros Playbook en fichiers plus petits.

  • Ces fichiers peuvent ensuite être appelés :

    • depuis un ou plusieurs Playbooks

    • plusieurs fois dans un même Playbook.

Import dynamique vs statique

  • Les commandes import permettent
    un chargement statique.
    (import_playbook, import_tasks, etc.)

  • Les commandes include permettent
    un chargement dynamique.
    (include_tasks, include_role, etc.)

Statique vs Dynamique

  • Statique
    Ansible traite les imports statique au moment de l'analyse du Playbook (avant l'exécution).

  • Dynamique
    Ansible traite les imports dynamiques au fur et à mesure durant l'exécution du Playbook.

  • Les imports statiques et dynamiques peuvent être mixés, toutefois cela n'est pas recommandé car cela rend le debug des Playbooks plus complexe.

Import de Playbooks

  • Il est possible d'importer un ou plusieurs Playbooks à l'intérieur d'un Playbook maître, avec import_playbook.

Roles

  • Plus puissants que les includes et les imports.

  • Permettent d'empaqueter un ensemble de tâches ainsi que les variables, handlers et autres autres éléments associés.

  • Les roles peuvent être facilement ré-utilisés et partagés.

Travaux pratiques

Travaux pratiques

TP Ansible : imports