Aller au contenu
Infrastructure as Code medium

Inventaire dynamique AWS EC2 avec amazon.aws.aws_ec2

10 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.
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

Créer inventory/aws_ec2.yml (le suffixe _ec2.yml est attendu par Ansible) :

---
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 évite les coûts :

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.

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

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 — utilise l'IAM role 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:
- 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') }}

Toutes les variables AWS sont préfixées sans aws_ — accès direct.

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.

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)
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.

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn