Cet article fait partie de notre guide: Le kit du nouvel administrateur réseau

Comment automatiser l’administration du réseau avec Ansible

Ansible est l’un des outils d’automatisation les plus populaires en administration réseau. Cet article donne les clés pour se lancer et détaille un premier projet.

Une fois que l’administrateur a pris connaissance des bonnes pratiques de l’automatisation du réseau et qu’il a compris son principe en écrivant des scripts Python, l’étape suivante consiste à se familiariser avec l’environnement de contrôle Ansible. Ansible est à la fois un langage d’automatisation et le nom du moteur qui l’exécute. Il est d’autant plus adapté à l’automatisation des réseaux qu’il est simple et s’interface naturellement avec les équipements en place.

Grâce à Ansible, il devient simple de réaliser une grande variété d’opérations fréquentes : exécuter des commandes et collecter les résultats dans des fichiers (ce qui est idéal pour le dépannage), mais aussi valider le fonctionnement du réseau en le comparant à un modèle, ou encore configurer des équipements selon des modèles, ce qui passe idéalement par des variables Jinja2.

Ansible est facile à apprendre, ce qui permet aux utilisateurs d’être rapidement productifs. La documentation de base est plutôt bien rédigée et quantité de tutoriaux vidéo sont disponibles en ligne pour démarrer. En ce qui concerne l’automatisation des réseaux, un bon point de départ est le portail (en anglais) Ansible for Network Automation. Il contient des liens vers plusieurs autres documents, dont un guide de démarrage, un guide des sujets avancés, ou encore la liste de tous les modules qui facilitent l’interaction avec différents types d’équipements.

Ansible fonctionne depuis un serveur de contrôle et pilote les équipements en ligne de commande via le protocole Secure Socket Shell (SSH), ou via leur API si elle existe. Cela évite d’avoir à installer un agent sur les équipements. L’ensemble repose sur des fichiers de configuration faciles à lire, avec des arguments en ligne de commande.

Dans le cadre de cet article, nous allons étudier un script d’exemple qui utilise le module cli_command pour envoyer des commandes CLI à un appareil type, ici un switch Cisco 3560CX. Les modules spécifiques à un fournisseur donné commencent toujours par le nom de son système d’exploitation, par exemple ios_* ou eos_*.

Ce script permettra de collecter les données de la table ARP (Address Resolution Protocol), exactement comme nous l’avions fait lors de l’article consacré à l’automatisation du réseau via des scripts Python, ce qui permet de comparer les méthodes et les résultats.

Le principe de fonctionnement

Le premier bon réflexe consiste à construire une hiérarchie de répertoires pour séparer les différents types de données de configuration que nous allons créer, afin d’éviter un enchevêtrement de fichiers qui pourrait nuire à la compréhension de ce que nous faisons. Dans notre exemple, nous utiliserons la structure de répertoires et de fichiers suivante :

├── ansible.cfg
├── group_vars
│   ├── IOS_switches.yml
├── host_vars
│   └── test_sw.yml
├── inventory.yml
└── sh_arp.yml

Le fichier ansible.cfg contient la configuration même d’Ansible. Les valeurs par défaut, issues de l’environnement Ansible, étant souvent le meilleur choix, il n’est pas systématiquement nécessaire de recréer ici ce fichier. Sachez qu’il est au format INI, lequel utilise la syntaxe nom = valeur. Par défaut, la collecte de données depuis les périphériques est désactivée (gathering = explicit) parce qu’elle n’est pas pensée pour des équipements réseau. Le nom du fichier d’inventaire est indiqué et les tentatives supplémentaires de communication sont désactivées :

     1  [defaults]
     2  gathering = explicit
     3  inventory = inventory.yml
     4  retry_files_enabled = False

Le répertoire group_vars contient tous les fichiers qui définissent des variables pour un groupe de plusieurs équipements. Nous allons par exemple mettre dans ce répertoire un fichier IOS_switches.yml au format YAML qui contiendra des variables valables pour tous les équipements réseau fonctionnant sous IOS, le système d’exploitation de Cisco.

Dans ce fichier, nous indiquons qu’il faut utiliser le module Ansible network_cli, que le système d’exploitation cible est ios et nous précisons les identifiants de connexion. Pour la sécurité de la connexion, il est recommandé d’utiliser soit des coffres-forts Ansible, soit des clés SSH ; dans les deux cas, les informations d’identification ne doivent pas être présentées en clair dans un fichier en texte clair. Mais dans le cadre de notre initiation, il est plus simple de le faire :

     1  ---
     2  # IOS_switches variables
     3  ansible_connection: network_cli
     4  ansible_network_os: ios
     5  ansible_become: yes
     6  ansible_become_method: enable
     7  ansible_become_password: "foobar"
     8 
     9  ansible_user: tester
    10  ansible_ssh_pass: foobar

Le répertoire host_vars contient les fichiers de définition de variables spécifiques à chaque équipement (chaque « hôte »). On trouvera typiquement dans un tel fichier le nom d’hôte de cet équipement et l’adresse IP à utiliser pour son administration. Les variables présentes dans ces fichiers remplacent les variables de groupe qui portent le même nom, ce qui permet de définir une variable générique et de la remplacer au cas par cas. Voici par exemple la structure test_sw.yml :

     1  ---
     2  # test_sw variables
     3  ipaddr: 192.168.1.108
     4  hostname: test_sw

Le fichier inventory.yml est l’inventaire des équipements, rangés dans des groupes, en utilisant le format YAML. Les équipements peuvent être contenus dans plusieurs groupes. Le matériel test_sw est ainsi membre des groupes IOS_switches et access.

 
     1  ---
     2  all:
     3    children:
     4      IOS_switches:
     5        hosts:
     6          test_sw
     7      IOS_routers:
     8        hosts:
     9          router1
    10      access:
    11        hosts:
    12          test_sw
    13      core:
    14        hosts:
    15          router1

Enfin, le fichier sh_arp.yml, toujours au format YAML, est ce qu’on appelle un playbook Ansible. C’est lui qui contrôle l’exécution de la tâche d’automatisation. Dans notre exemple, c’est lui qui indique comment récupérer la table ARP et comment afficher le résultat (la « sortie »). Un playbook peut contenir plusieurs « jeux » (« play » en anglais), et chaque jeu peut contenir plusieurs tâches.

Ci-dessous, nous appelons notre jeu « Gather ARP data ». Les hôtes concernés sont ceux qui sont listés dans le groupe IOS_switches. Ce jeu a deux tâches, chacune avec un nom. Ces noms sont simplement des chaînes de texte qui apparaîtront telles quelles dans la sortie. Dans la tâche 1, le module ios_command est utilisé pour exécuter la commande show arp. Le registre des directives est utilisé pour stocker la sortie de ios_command dans une variable Ansible nommée cli_result.

La tâche 2 affiche simplement le résultat qui a été stocké, en se référant à la liste stdout_lines qui se trouve dans cli_result.

 
     1  ---
     2  - name: Gather ARP data
     3    hosts: IOS_switches
     4    tasks:
     5      - name: "Task 1: Get output of show arp on IOS"
     6        ios_command:
     7          commands: "show arp"
     8        register: cli_result
     9 
    10      - name: "Task 2: Display stdout_lines[0]"
    11        debug:
    12          msg: "{{ cli_result.stdout_lines[0] }}"

Ci-dessous, nous lançons le script Ansible.

 
     1     $ ansible-playbook sh_arp.yml
     2    
     3     PLAY [Gather ARP data] ***************************************************
     4    
     5     TASK [Task 1: Get output of show arp on IOS] *****************************
     6     ok: [test_sw]
     7    
     8     TASK [Task 2: Display stdout_lines[0]] ***********************************
     9     ok: [test_sw] => {
    10         "msg": [
    11             "Protocol  Address     Age (min)  Hardware Addr   Type   Interface",
    12             "Internet  192.168.1.108      -   bcc4.933e.49c0  ARPA   Vlan1",
    13             "Internet  192.168.1.126      5   f894.c220.2177  ARPA   Vlan1",
    14             "Internet  192.168.1.133      1   88c2.55fb.9ce7  ARPA   Vlan1",
    15             "Internet  192.168.1.138      0   a860.b60a.7a3a  ARPA   Vlan1"
    16         ]
    17     }
    18    
    19     PLAY RECAP ***************************************************************
    20     test_sw                    : ok=2    changed=0    unreachable=0    failed=0  
    21   

Ansible sur plusieurs appareils

Automatiser le réseau avec Ansible ne consiste bien évidemment pas à exécuter une seule commande sur un seul appareil, mais des jeux de commandes sur plusieurs. Ainsi, utilisez l’exemple ci-dessus afin d’exécuter sur votre réseau plusieurs commandes show et stockez les résultats dans des fichiers. Cela vous permettra ensuite d’utiliser de simples expressions de recherche grep pour trouver des modèles spécifiques parmi des centaines de fichiers.

Par exemple, vous conserverez des copies du résultat de show version sur chaque équipement afin de documenter les appareils de votre réseau et leurs numéros de série. Vous pouvez aussi sauvegarder le résultat des commandes show arp et show mac address dynamic pour, ultérieurement, retrouver simplement où un périphérique est connecté dans votre réseau.

Avec ces jeux de commandes, Ansible permet aussi de sauvegarder dynamiquement les configurations de nombreux appareils. Ensuite, vous pourrez vous en servir pour les redéployer, pour les industrialiser sur plusieurs équipements afin de maintenir une qualité de service et un routage précis, ou pour les comparer avec celles en production, afin de vérifier que les configurations de votre réseau restent conformes à votre design, qu’elles ont été rechargées correctement.

Les playbooks font d’excellentes tâches préétablies, mais il existe aussi un mode ad hoc pour automatiser l’exécution d’une même commande sur de nombreux appareils. Des filtres, des analyseurs et des plugins sont par ailleurs disponibles pour affiner les traitements.

Pour aller plus loin, nous vous conseillons de suivre les cours (en anglais) Automating Networks with Ansible the Right Way de Nick Russo. 

Pour approfondir sur Administration de réseaux