Aller au contenu
Infrastructure as Code medium

Inventaire dynamique AWS EC2 avec amazon.aws.aws_ec2

35 min de lecture

Logo Ansible

Pour piloter du parc AWS depuis Ansible, le plugin amazon.aws.aws_ec2 est le standard de fait. Il interroge l'API AWS et retourne toutes vos instances EC2 d'une région ou d'un compte, groupées automatiquement par tag, par VPC, par AZ. C'est le plugin officiel maintenu par Red Hat.

Cette page est didactique, sans lab pratique car AWS suppose un compte cloud et engendre de la facturation. Elle vous donne les patterns à appliquer le jour où vous gérez un parc AWS depuis Ansible.

  • Configurer le plugin amazon.aws.aws_ec2 (région, filtres, credentials).
  • Grouper automatiquement les instances par tag, par VPC, par état.
  • Combiner avec un inventaire statique pour les hôtes on-prem.
  • Comprendre les bonnes pratiques sécurité (IAM role > clés statiques).
  • Anticiper les pièges courants (rate limiting, multi-région).
  • Compte AWS avec instances EC2 lancées.
  • amazon.aws collection installée.
  • Credentials AWS configurés (variables d'env ou IAM role sur le control node).
  • Avoir lu Concepts des plugins d'inventaire.

Deux installations distinctes sont nécessaires, et confondre les deux est la cause d'échec la plus fréquente. La collection amazon.aws apporte le code du plugin côté Ansible ; les bibliothèques Python boto3 et botocore portent le dialogue avec l'API AWS. Elles doivent être installées dans l'interpréteur Python qu'utilise Ansible, pas dans un autre environnement virtuel, sinon le plugin remonte boto3 module not found alors que pip list montre bien le paquet.

Fenêtre de terminal
ansible-galaxy collection install amazon.aws
pip install boto3 botocore

Le plugin nécessite boto3 et botocore côté control node. Activer dans ansible.cfg :

[inventory]
enable_plugins = host_list, script, auto, yaml, ini, amazon.aws.aws_ec2

Le nom du fichier n'est pas libre. Le plugin ne se déclenche que sur un fichier dont le nom se termine par aws_ec2.yml ou aws_ec2.yaml : inventory/aws_ec2.yml convient, production.aws_ec2.yml aussi, mais inventory/ec2.yml sera ignoré sans message d'erreur. Créer inventory/aws_ec2.yml :

---
plugin: amazon.aws.aws_ec2
regions:
- eu-west-3

Tester :

Fenêtre de terminal
ansible-inventory -i inventory/aws_ec2.yml --graph

Toutes vos instances EC2 de la région eu-west-3 apparaissent. Par défaut, elles sont nommées par leur instance_id (ex: i-0abc123def456).

Par défaut, l'instance s'appelle i-0abc.... Pour utiliser le tag Name (ce que vous voyez dans la console AWS) :

plugin: amazon.aws.aws_ec2
regions:
- eu-west-3
hostnames:
- tag:Name
- dns-name
- private-ip-address

hostnames: est une liste : Ansible essaie le premier critère, puis le second si le premier est vide. Ici : tag Name en priorité, sinon DNS public, sinon IP privée.

Les tags AWS sont la clé d'un parc bien organisé. Le plugin les expose automatiquement :

plugin: amazon.aws.aws_ec2
regions:
- eu-west-3
keyed_groups:
# Un groupe par valeur du tag Environment (prod, staging, dev)
- prefix: env
key: tags.Environment
# Un groupe par valeur du tag Role (web, db, lb)
- prefix: role
key: tags.Role
# Groupes hiérarchiques par région et AZ
- prefix: region
key: placement.region
- prefix: az
key: placement.availability_zone

Résultat : ansible-inventory --graph montre :

@all:
|--@env_prod:
| |--web1.example.com
| |--db1.example.com
|--@env_staging:
| |--web-staging.example.com
|--@role_web:
| |--web1.example.com
| |--web-staging.example.com
|--@role_db:
| |--db1.example.com
|--@region_eu-west-3:
| |--... (toutes les instances)
|--@az_eu-west-3a:
| |--web1.example.com

Vous pouvez maintenant cibler env_prod:&role_web pour déployer uniquement sur les webservers de prod.

Si vous avez 500 instances dont seulement 50 vous concernent, filtrer côté API plutôt que côté playbook change le temps de réponse : AWS ne renvoie que les instances retenues, et le plugin n'a pas à construire des groupes que personne n'utilisera. Les clés utilisées ici sont celles de l'API EC2, pas des noms Ansible : instance-state-name, vpc-id, ou tag:<Nom> pour un tag précis.

plugin: amazon.aws.aws_ec2
regions:
- eu-west-3
filters:
# Uniquement les instances en cours d'exécution
instance-state-name: running
# Uniquement celles tagged Environment=prod
tag:Environment: prod
# Uniquement celles dans un VPC spécifique
vpc-id: vpc-0123abcdef

Avantage : moins de payload réseau, plus rapide, et vos collègues qui regardent l'inventaire ne voient pas les instances qui ne les concernent pas.

plugin: amazon.aws.aws_ec2
aws_access_key_id: AKIAIOSFODNN7EXAMPLE # ← clés en clair !
aws_secret_access_key: wJalrXUtnFEMI/K7MDENG/EXAMPLE

Jamais de clés en clair dans le fichier d'inventaire, qui finit dans Git, dans les logs CI, partagé en équipe.

Acceptable pour un poste de développement ou un job CI où la plateforme injecte les valeurs. Deux limites à connaître : les variables restent visibles dans l'environnement de tous les processus enfants lancés depuis ce shell, et un export tapé à la main atterrit dans l'historique du shell. Préfixez la ligne d'un espace ou passez par un fichier sourcé hors du dépôt.

Fenêtre de terminal
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=eu-west-3
ansible-inventory -i inventory/aws_ec2.yml --list
plugin: amazon.aws.aws_ec2
aws_profile: production
regions:
- eu-west-3

Le fichier d'inventaire ne contient alors qu'un nom de profil, ce qui le rend commitable sans risque : les secrets vivent dans ~/.aws/credentials, hors du dépôt, avec des permissions 0600. C'est aussi la solution la plus pratique quand vous jonglez entre plusieurs comptes AWS, puisque changer de compte revient à changer une seule ligne.

Avec ~/.aws/credentials :

[production]
aws_access_key_id = AKIA...
aws_secret_access_key = ...

Si Ansible tourne sur une instance EC2, attacher un IAM role à cette instance avec une policy EC2:Describe*. Pas de clés à gérer du tout, l'instance reçoit ses credentials via le metadata service AWS.

plugin: amazon.aws.aws_ec2
regions:
- eu-west-3
# Pas de credentials : l'IAM role est utilisé automatiquement

C'est le pattern le plus sûr en production.

Pour chaque instance, le plugin expose un dict de facts très riche, accessible dans vos playbooks :

- name: Afficher l'IP privée de chaque webserver
hosts: env_prod:&role_web
tasks:
- name: Afficher les attributs EC2 de l'hôte
ansible.builtin.debug:
msg: |
{{ inventory_hostname }} :
- private IP : {{ private_ip_address }}
- public IP : {{ public_ip_address | default('aucune') }}
- instance ID: {{ instance_id }}
- VPC : {{ vpc_id }}
- AZ : {{ placement.availability_zone }}
- tag Owner : {{ tags.Owner | default('non défini') }}

Les noms de ces variables viennent directement de la réponse de l'API DescribeInstances, convertie du CamelCase de l'API vers le snake_case d'Ansible : PrivateIpAddress devient private_ip_address, VpcId devient vpc_id. Aucun préfixe n'est ajouté par défaut, d'où le risque de collision avec vos propres variables de playbook ; l'option hostvars_prefix: 'aws_' du plugin permet de les isoler si besoin. Les tags font exception à la conversion : leurs clés gardent la casse d'origine, d'où tags.Environment et non tags.environment.

Sur un compte avec 200+ instances, chaque commande Ansible déclenche une API call DescribeInstances. Au-delà de quelques runs/min, AWS rate-limit. Activer le cache :

plugin: amazon.aws.aws_ec2
regions:
- eu-west-3
cache: true
cache_plugin: jsonfile
cache_timeout: 600 # 10 minutes
cache_connection: /tmp/ansible_aws_ec2_cache

Pour rafraîchir après création d'instances :

Fenêtre de terminal
ansible-inventory -i inventory/aws_ec2.yml --list --refresh-cache

Pour gérer un parc multi-région :

plugin: amazon.aws.aws_ec2
regions:
- eu-west-3
- us-east-1
- ap-southeast-1

Toutes les instances des 3 régions sont fusionnées en un seul inventaire. Le keyed_groups: region les groupe automatiquement par région.

Pattern courant : on-prem (statique) + AWS (dynamique) dans le même run :

inventory/
├── 01-static.yml ← serveurs on-prem
└── 02-aws_ec2.yml ← plugin AWS
Fenêtre de terminal
ansible-playbook -i inventory/ playbook.yml

Le playbook.yml peut cibler webservers (groupe défini dans le statique on-prem) et env_prod (groupe AWS) sans problème.

Les deux premières lignes concernent l'environnement Python et les credentials : elles se manifestent au tout premier appel, avant même que l'API AWS soit contactée. Les suivantes apparaissent plus tard, quand l'inventaire fonctionne mais ne remonte pas ce que vous attendez. Dans ce second cas, le réflexe utile est ansible-inventory --list -vvv, qui affiche l'appel API exact envoyé par le plugin, filtres compris.

SymptômeCauseFix
boto3 module not foundModule Python manquantpip install boto3 botocore
Unable to locate credentialsPas de credentials configurésVariables d'env ou aws_profile: ou IAM role
RequestLimitExceeded (429)Trop d'API calls (rate limit)Activer le cache (cache: true)
Instances absentesFiltre trop restrictif--list -vvv pour voir l'API call exacte
Hostname = i-0abc...Pas de hostnames: configuréhostnames: [tag:Name, ...]
Multi-région lentUne seule call par régionPréférer un cache long (>= 600s)

Ce tableau situe le plugin AWS face aux deux autres sources dynamiques couvertes dans cette section. La ligne à regarder en premier est « Retourne IP ? » : elle décide si vous pouvez lancer un playbook immédiatement après la découverte, ou s'il vous faudra une étape intermédiaire pour résoudre les adresses. La ligne « Groupage » vient ensuite, car c'est elle qui détermine la quantité de configuration manuelle à écrire pour obtenir des groupes exploitables.

CritèreAWS EC2libvirtProxmox
SetupCloud + IAMLocal libvirtToken API
CoûtCloud billZéroZéro
Retourne IP ?Oui (privée + publique)Non sans QEMU agentOui
GroupageTags AWSManuel via groups:Tags Proxmox
Multi-sourceOui (multi-région)Limité au host localLimité au cluster
  • amazon.aws.aws_ec2 = standard pour Ansible + AWS. Maintenu par Red Hat.
  • hostnames: = utiliser le tag Name au lieu de l'instance ID pour des hostnames lisibles.
  • keyed_groups: sur les tags AWS = pattern n°1 pour grouper automatiquement.
  • filters: réduire le payload côté API pour les gros parcs.
  • Credentials : IAM role > AWS profile > variables d'env > jamais en clair dans le YAML.
  • Cache mandatory au-delà de quelques runs/min (rate limit AWS).
  • Multi-région supportée nativement via regions: liste.
  • Plugin NetBox : agréger plusieurs clouds et le bare-metal dans une source unique, quand les tags AWS ne suffisent plus.
  • Écrire un script custom : le recours pour un fournisseur cloud sans plugin maintenu.
  • Trouver le bon module : la collection amazon.aws s'installe comme les autres, avec les mêmes garde-fous supply chain.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn