Les environnements d’exécution Ansible

Magazine
Marque
Linux Pratique
Numéro
130
Mois de parution
mars 2022
Spécialité(s)


Résumé

Ansible est un fabuleux outil d’automatisation, mais la gestion de son environnement d’exécution (version utilisée de l’outil ou de Python, librairies, dépendances système) se révèle parfois un véritable casse-tête… qui est désormais résolu par l’introduction des « Ansible Environnements Execution ». Explication détaillée de cette fonctionnalité dans cet article !


Body

Les environnements d’exécution pour Ansible (execution environments) sont une manière d’isoler l’exécution de l’outil à l’aide de conteneurs. Ceux-ci permettent de fournir l’ensemble des dépendances que requiert le bon déroulement d’un playbook. Celles-ci peuvent être liées au système, comme une version précise de Python, ou composées d’un groupement de collections (extensions pour Ansible). Chaque environnement d’exécution permet de créer une image (de conteneur) dédiée à l’exécution d’un playbook (et rien d’autre).

Afin de bien comprendre la manière dont cette solution logicielle s’intègre au sein de l’écosystème Ansible, nous allons étudier, sommairement, l’ensemble des briques qui la forment, soit :

  • Ansible Runner - un outil en ligne de commandes qui permet d’exécuter les playbooks Ansible sans installer intégralement l’outil et ses dépendances.
  • Ansible Builder - un utilitaire qui permet de construire une image de conteneur (Docker ou Podman) pour exécuter un playbook à l’aide d’Ansible Runner.
  • Execution Environments - l’intégration des deux précédents outils au sein d’AWX (ou Ansible Automation Platform).

1. Ansible Runner

En essence, Ansible Runner est la modularisation de la partie d’Ansible responsable d’exécuter les tâches de ses playbooks. Dans les faits, il est simplement un sous-ensemble de la commande ansible-playbook. Comme Ansible Runner peut s’exécuter au sein d’un conteneur, il est aisé de l’embarquer et d’éviter ainsi de déporter la complexité d’installation de l’outil et de ses dépendances Python sur les systèmes cibles.

En outre, Ansible Runner regroupe les résultats et informations associées à ses exécutions. Sa particularité principale est de fournir une interface commune qui n’évolue que très peu dans le temps alors que le reste d’Ansible continue lui de changer et de s’enrichir.

Il existe trois manières d’interagir avec cet outil. La première est l’utilisation en ligne de commandes de celui-ci, la seconde est par l’intermédiaire d’un conteneur et la troisième sous forme d’une librairie Python, afin d’être exploitée au sein d’un programme ou script du même langage.

1.1 Utilisation en ligne de commandes

Dans le cadre de cet article, nous allons seulement étudier l’utilisation d’Ansible Runner en ligne de commandes, afin de nous permettre de bien comprendre son fonctionnement.

Son installation se fait relativement aisément sur une distribution Linux moderne. À titre d’exemple, voici comment installer celui-ci sur un système sous Fedora (ou utilisant des paquets RPM et l’outil de gestion de paquets logiciels dnf) :

$ dnf install python-ansible-runner

Si cet outil a été construit pour être exécuté à l’aide de commandes, il n’est pas réellement destiné à être utilisé manuellement. Avant tout, il a pour fonction d’être invoqué au sein d’un processus isolé. Néanmoins, à titre d’exemple de son fonctionnement, nous allons exécuter un simple playbook avec Ansible Runner.

Voici le contenu du playbook que nous allons exécuter :

---
- hosts: localhost
  gather_facts: false
  tasks:
 
    - debug:
        msg: "Hello"

Ci-dessous, le résultat de son exécution à l’aide d’Ansible Runner :

# ansible-runner run /work/ -p playbook.yml
 
PLAY [localhost] ***************************************************************
 
TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "Hello"
}
 
PLAY RECAP *********************************************************************
localhost  : ok=1  changed=0  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0

Si Ansible Runner est destiné à être utilisé par des processus plus que par des êtres humains, il propose néanmoins une fonctionnalité fort pratique qui mérite d’être mentionnée. En effet, de par sa nature, il est capable d’exécuter un rôle Ansible sans requérir la mise en place d’un playbook. Lors de son invocation, l’outil va générer pour son utilisateur celui-ci afin de pouvoir exécuter directement le rôle.

$ ansible-runner run demo --role testrole --hosts localhost

De manière similaire, on peut tirer profit d’Ansible Runner afin d’exécuter un module Ansible directement, sans utiliser un playbook :

$ ansible-runner run work -m debug --hosts localhost -a msg="'running module from runner'"
[WARNING]: No inventory was parsed, only implicit localhost is available
localhost | SUCCESS => {
    "msg": "running module from runner"
}

Ansible Runner étant entièrement paramétrable par le processus qui l’invoque, il dispose d’une quantité importante d’options. Cependant, pour faciliter sa mise en place et son utilisation au sein d’Ansible, tous ces arguments sont aussi définissables par l’intermédiaire d’une arborescence de fichiers.

.
├── env
│   ├── envvars
│   ├── extravars
│   ├── passwords
│   ├── cmdline
│   ├── settings
│   └── ssh_key
├── inventory
│   └── hosts
└── project
    ├── test.yml
    └── roles
        └── testrole
            ├── defaults
            ├── handlers
            ├── meta
            ├── README.md
            ├── tasks
            ├── tests
            └── vars

À noter qu’à la fin de son exécution, Ansible Runner produit également une arborescence de fichiers contenant les nombreuses données sur le déroulement de celle-ci. On peut y trouver le résultat de la commande et d’autres informations destinées à être consommées par le processus à la source de son invocation :

.
├── artifacts
│   └── 37f639a3-1f4f-4acb-abee-ea1898013a25
│       ├── fact_cache
│       │   └── localhost
│       ├── job_events
│       │   ├── 1-34437b34-addd-45ae-819a-4d8c9711e191.json
│       │   ├── 2-8c164553-8573-b1e0-76e1-000000000006.json
│       │   ├── 3-8c164553-8573-b1e0-76e1-00000000000d.json
│       │   ├── 4-f16be0cd-99e1-4568-a599-546ab80b2799.json
│       │   ├── 5-8c164553-8573-b1e0-76e1-000000000008.json
│       │   ├── 6-981fd563-ec25-45cb-84f6-e9dc4e6449cb.json
│       │   └── 7-01c7090a-e202-4fb4-9ac7-079965729c86.json
│       ├── rc
│       ├── status
│       └── stdout

Il nous faut aussi mentionner que l’outil a plusieurs modes d’exécution. L’option run exécute directement Ansible Runner, et attend la fin du processus avant de rendre la main. À l’inverse, l’option start démarre l’outil en tâche de fond, et crée un fichier PID associé à son exécution. Pour interrompre celle-ci, on peut alors utiliser l’option stop. Une option complémentaire is-alive permet de vérifier que le processus s’exécute toujours.

Avec cette revue de haut niveau du fonctionnement d’Ansible Runner, nous sommes maintenant prêts à aborder la suite, c’est-à-dire son usage au sein d’un conteneur.

2. Encapsuler l’exécution d’Ansible Runner à l’aide d’Ansible Builder

Maintenant que nous avons vu dans les grandes lignes l’utilisation d’Ansible Runner, nous allons étudier un autre outil nommé Ansible Builder. Celui-ci va nous permettre d’isoler l’exécution du précédent au sein d’un conteneur.

Notons tout de suite qu’il est bien sûr possible de concevoir un conteneur afin d’encapsuler l’exécution d’Ansible Runner à l’aide des outils habituels. Cependant, cet outil facilite considérablement la tâche en générant pour nous le fichier Containerfile.

Lors de son exécution, Ansible Builder observe le processus suivant :

  • analyse et validation du fichier de définition fourni ;
  • création d’un fichier Containerfile ;
  • construction de l’image à partir de celui-ci à l’aide de Podman.

Commençons par installer Ansible Builder qui, à l’inverse du précédent, ne dispose pas d’un paquet logiciel sous forme de RPM. Il nous faut donc recourir à l’utilisation de l’utilitaire python PIP.

$ pip install ansible-builder

Ansible Builder installé, il nous faut lui fournir un fichier de définition, qui lui spécifie comment construire l’image dont nous avons besoin. Ce fichier respecte les contraintes du format YAML et il se compose de plusieurs sections.

Si la fonction et le sens de la plupart de ces sections sont évidents, nous allons expliciter les plus importantes d’entre elles à l’aide de l’exemple suivant :

version: 1
 
build_arg_defaults:
  ANSIBLE_GALAXY_CLI_COLLECTION_OPTS: "-v"
 
ansible_config: 'ansible.cfg'
 
dependencies:
  galaxy: galaxy-deps.yml
  python: python-deps.txt
  system: system-deps.txt
 
additional_build_steps:
  prepend: |
    RUN cat /etc/redhat-release
  append:
    - RUN echo Image has been built!

La section intitulée build_arg_defaults: permet de spécifier les arguments éventuellement requis pour l’étape de construction. L’attribut ansible_config: se passe de commentaires, il permet simplement de fournir, si nécessaire, le chemin vers le fichier de configuration d’Ansible en lui-même.

La section la plus importante est bien sûr celle nommée dependencies:, car c’est celle-ci qui définit les chemins vers les descripteurs des dépendances requises. Un playbook Ansible est, en fin de compte, un logiciel relativement complexe dont le bon fonctionnement dépend de la mise en place de beaucoup d’autres éléments. Ces descripteurs permettent donc d’indiquer à Ansible Builder tous les éléments requis pour que son exécution se déroule sans incident.

Dans cette section, on peut indiquer les collections Ansible nécessaires pour l’exécution de celui-ci, soit ses dépendances de haut niveau. Mais, l’on peut aussi spécifier les bibliothèques Pythons exigées par le playbook ou même les paquetages logiciels supplémentaires requis, soit des dépendances de bas niveau.

Le format du descripteur spécifiant les collections Ansible requises suit la syntaxe usuelle et déjà utilisée au sein du projet Ansible :

$ cat galaxy-deps.yml
---
collections:
  - name: awx.awx

Le descripteur de dépendances Python est un simple fichier texte. Il liste celles-ci, une par ligne, et accepte une syntaxe intuitive pour indiquer les versions requises :

awxkit
packaging
requests>=2.4.2

De manière pratique, ce format suit la même syntaxe que celle utilisée par la sortie standard de la commande pip freeze. On peut donc ainsi facilement générer ce fichier à partir de l’exécution de celle-ci.

Il est également possible d’indiquer un répertoire relatif à celui où s’exécute Ansible Builder et par ce biais embarquer des librairies Python qui ne seraient pas disponibles en ligne.

Enfin, le descripteur de dépendance système suit le format de l’outil bindep. Il permet d’installer celles-ci, si cette étape n’est pas déjà garantie par les collections embarquées avec le playbook. Là aussi, on peut spécifier un chemin relatif afin d’assurer le déploiement d’un paquet qui ne sera pas disponible en ligne.

libxml2-devel [platform:rpm]
git [platform:rpm]

Tous ces éléments proprement définis dans notre fichier image-definition.yml, nous pouvons maintenant exécuter la commande Ansible Builder :

$ ansible-builder build -f image-definition.yml
Running command:
  podman build -f context/Containerfile -t ansible-execution-env:latest context
Complete! The build context can be found at:
/home/rpelisse/ansible-builder/context

Notez que, par commodité, la commande crée le fichier Containerfile et l’image associée. Il est possible de ne générer que le fichier de description afin de construire l’image à l’aide des outils usuels ou simplement sur un autre système :

$ ansible-builder create

Ci-dessous, le fichier Containerfile généré par Ansible Builder :

$ cat context/Containerfile
ARG EE_BASE_IMAGE=quay.io/ansible/ansible-runner:stable-2.10-devel
ARG EE_BUILDER_IMAGE=quay.io/ansible/ansible-builder:latest
 
FROM $EE_BASE_IMAGE as galaxy
ARG ANSIBLE_GALAXY_CLI_COLLECTION_OPTS=
USER root
 
ADD _build/ansible.cfg ~/.ansible.cfg
 
ADD _build /build
WORKDIR /build
 
RUN ansible-galaxy role install -r requirements.yml --roles-path /usr/share/ansible/roles
RUN ansible-galaxy collection install $ANSIBLE_GALAXY_CLI_COLLECTION_OPTS -r requirements.yml --collections-path /usr/share/ansible/collections
 
FROM $EE_BUILDER_IMAGE as builder
 
COPY --from=galaxy /usr/share/ansible /usr/share/ansible
 
ADD _build/requirements.txt requirements.txt
ADD _build/bindep.txt bindep.txt
RUN ansible-builder introspect --sanitize --user-pip=requirements.txt --user-bindep=bindep.txt --write-bindep=/tmp/src/bindep.txt --write-pip=/tmp/src/requirements.txt
RUN assemble
 
FROM $EE_BASE_IMAGE
USER root
RUN cat /etc/redhat-release
 
COPY --from=galaxy /usr/share/ansible /usr/share/ansible
 
COPY --from=builder /output/ /output/
RUN /output/install-from-bindep && rm -rf /output/wheelsRUN echo This is a post-install command!

L’image associée à ce fichier Containerfile a aussi été générée :

$ podman images
REPOSITORY                           TAG       IMAGE ID      CREATED        SIZE
localhost/ansible-execution-env      latest    59e76041594b  6 minutes ago  802 MB
...

On peut également directement exécuter celle-ci afin de vérifier la conformité du cadre d’exécution spécifié :

$ podman run -ti localhost/ansible-execution-env /bin/bash
bash-4.4# ansible --version
ansible 2.10.16.post0
  config file = None
  configured module search path = ['/home/runner/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.8/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.8.8 (default, Aug 25 2021, 16:13:02) [GCC 8.5.0 20210514 (Red Hat 8.5.0-3)]

Avec tous ces éléments en place, Ansible Runner pour l’exécution et le conteneur défini et construit par Ansible Builder, nous allons pouvoir maintenant étudier comment mettre en place cet environnement d’exécution, à l’aide de la plateforme AWX, qui est le centre névralgique de toute infrastructure Ansible.

3. Mise en place d’un environnement d’exécution

Les environnements d’exécution sont conçus pour fournir un cadre cohérent, reproductible, portable et aisément partageable. Ainsi, le playbook sera exécuté de manière identique par AWX que sur un autre système utilisant le même cadre d’exécution.

Ceci facilite grandement le développement d’automatisations et de contenus pour Ansible qui sont destinés à être exécutés par AWX ou son équivalent supporté par Red Hat, Ansible Automation Platform. Plus spécifiquement, le terme d’environnement d’exécution dans le cadre d’Ansible Runner désigne le conteneur qui exécute Ansible à l’aide de celui-ci.

Notons au préalable que, comme tous les éléments gérés par AWX, les environnements d’exécution peuvent être manipulés de manière globale ou être liés à une organisation. Mais, dans tous les cas, l’utilisateur doit avoir le niveau de privilèges requis sur le système afin de pouvoir les utiliser. Ainsi, les environnements d’exécution liés à une organisation nécessitent les droits d’administrateur pour exécuter le playbook au sein de celui-ci.

Maintenant que nous avons construit notre environnement d’exécution, il ne reste plus qu’à le déployer au sein de AWX. La première étape consiste simplement à accéder à la section dédiée aux environnements d’exécution au sein de l’outil de gestion de l’infrastructure Ansible.

Ceci est illustré par la Figure 1.

awx-ee-1-s

Figure 1

Une fois dans cette section de l’interface graphique, il suffit de cliquer sur le bouton Ajouter afin de spécifier un nouvel environnement d’exécution (Figure 2).

awx-ee-2-s

Figure 2

Ceci nous redirige naturellement vers un formulaire, qui va nous permettre d’indiquer les quelques éléments nécessaires au déploiement de cet environnement d’exécution (Figure 3).

awx-ee-3-s

Figure 3

On note qu’il existe trois manières de synchroniser un environnement d’exécution avec sa source. Au choix, on peut :

  • Toujours effectuer l’opération Pull afin de télécharger systématiquement l’image la plus récente pour le conteneur.
  • Ne jamais réaliser cette opération pour utiliser le dernier conteneur récupéré.
  • Ou encore, ne rien spécifier pour cette opération.

Toutes ces étapes accomplies, nous avons maintenant à notre disposition un nouvel environnement d’exécution. On peut désormais l’associer à n’importe quelle tâche déjà définie au sein de AWX, comme illustré sur la Figure 4.

awx-ee-4-s

Figure 4

Conclusion

À l’aide d’un simple conteneur encapsulant l’exécution d’une partie du moteur Ansible, les environnements d’exécution permettent de commodément isoler dans un processus dédié et surtout dans un environnement conforme au besoin de la tâche que l’on souhaite exécuter. C’est donc un outil aisé d’utilisation qui encapsule avec succès un nombre d’opérations relativement complexes afin de faciliter autant que possible sa mise en place et ceci tout en garantissant une exécution d’Ansible encore plus stable et robuste.



Article rédigé par

Par le(s) même(s) auteur(s)

Automatiser le déploiement d'un MOM avec Wildfly et Ansible

Magazine
Marque
Linux Pratique
Numéro
137
Mois de parution
mai 2023
Spécialité(s)
Résumé

Dans de nombreuses organisations et grandes entreprises, les solutions logicielles de gestion de messages (ou MOM pour « Messaging Oriented Middleware ») sont omniprésentes. Dans cet article, nous proposons donc d’évoquer le déploiement d’une telle solution, à l’aide du serveur Java open source, Wildfly, et de manière entièrement automatisée grâce à Ansible…

Getting Things Done... avec Bash !

Magazine
Marque
Linux Pratique
HS n°
Numéro
57
Mois de parution
avril 2023
Spécialité(s)
Résumé

Depuis la parution de l’ouvrage du même nom, il y a 22 ans, la méthodologie Getting Things Done a fait son bonhomme de chemin. L’utilisant depuis plus de dix ans, nous vous proposons d’en faire, dans cet article, non pas une présentation détaillée, mais un retour d’expérience sur comment nous l’utilisons au quotidien et, en particulier, comment notre interpréteur shell favori, Bash, est au cœur de son outillage !

Introduction à l’automatisation avec Ansible

Magazine
Marque
Linux Pratique
HS n°
Numéro
57
Mois de parution
avril 2023
Spécialité(s)
Résumé

La croissance constante de la taille des systèmes d'information, comme la démultiplication de leurs environnements d'exécution, a rendu essentielle l'automatisation de toutes tâches d'administration de ceux-ci. Cet article propose donc d'introduire son lecteur à l'une des solutions d'automatisation la plus appréciée : Ansible.

Les derniers articles Premiums

Les derniers articles Premium

Quarkus : applications Java pour conteneurs

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Initié par Red Hat, il y a quelques années le projet Quarkus a pris son envol et en est désormais à sa troisième version majeure. Il propose un cadre d’exécution pour une application de Java radicalement différente, où son exécution ultra optimisée en fait un parfait candidat pour le déploiement sur des conteneurs tels que ceux de Docker ou Podman. Quarkus va même encore plus loin, en permettant de transformer l’application Java en un exécutable natif ! Voici une rapide introduction, par la pratique, à cet incroyable framework, qui nous offrira l’opportunité d’illustrer également sa facilité de prise en main.

De la scytale au bit quantique : l’avenir de la cryptographie

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Imaginez un monde où nos données seraient aussi insaisissables que le célèbre chat de Schrödinger : à la fois sécurisées et non sécurisées jusqu'à ce qu'un cryptographe quantique décide d’y jeter un œil. Cet article nous emmène dans les méandres de la cryptographie quantique, où la physique quantique n'est pas seulement une affaire de laboratoires, mais la clé d'un futur numérique très sécurisé. Entre principes quantiques mystérieux, défis techniques, et applications pratiques, nous allons découvrir comment cette technologie s'apprête à encoder nos données dans une dimension où même les meilleurs cryptographes n’y pourraient rien faire.

Les nouvelles menaces liées à l’intelligence artificielle

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Sommes-nous proches de la singularité technologique ? Peu probable. Même si l’intelligence artificielle a fait un bond ces dernières années (elle est étudiée depuis des dizaines d’années), nous sommes loin d’en perdre le contrôle. Et pourtant, une partie de l’utilisation de l’intelligence artificielle échappe aux analystes. Eh oui ! Comme tout système, elle est utilisée par des acteurs malveillants essayant d’en tirer profit pécuniairement. Cet article met en exergue quelques-unes des applications de l’intelligence artificielle par des acteurs malveillants et décrit succinctement comment parer à leurs attaques.

Les listes de lecture

8 article(s) - ajoutée le 01/07/2020
Découvrez notre sélection d'articles pour faire vos premiers pas avec les conteneurs, apprendre à les configurer et les utiliser au quotidien.
11 article(s) - ajoutée le 02/07/2020
Si vous recherchez quels sont les outils du DevOps et comment les utiliser, cette liste est faite pour vous.
8 article(s) - ajoutée le 02/07/2020
Il est essentiel d'effectuer des sauvegardes régulières de son travail pour éviter de perdre toutes ses données bêtement. De nombreux outils sont disponibles pour nous assister dans cette tâche.
Voir les 58 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous