Aller au contenu

Developper Roles et Collections Ansible AWS EC2

logo ansible

Jusqu’à maintenant, je n’utilisais que les drivers docker et vagrant pour provisionner des machines de tests avec molecule lors de mes développements de roles et collections Ansible. Comme je n’ai plus assez de ressources à la maison pour les provisionner, je me suis dit pourquoi utiliser des instances AWS EC2. Après avoir tâtonnè longtemps, j’ai fini par réussir, j’ai décidé de vous en faire profiter.

Installation

Par défaut molécule n’installe que les drivers docker et delegated. Il faut donc installer le driver ec2, ainsi que la librairie boto3.

Terminal window
pip install molecule molecule-ec2 boto3

Création de la configuration AWS

Maintenant que nous avons tout ce qu’il nous, passons à l’installation et la configuration la cli awx. Comme très souvent je vais utiliser asdf pour l’installer.

Terminal window
asdf plugin add aws-cli
asdf install aws-cli latest
asdf global aws-cli latest

Passons à la configuration du compte en créant au prélable un compte sur IAM :

Terminal window
aws configure
AWS Access Key ID [None]: xxxxxxxxxx
AWS Secret Access Key [None]: xxxxx/xx/xxxxxxxxxxxxxxxxxxxx
Default region name [None]: eu-west-3
Default output format [None]: json

Initatialisation du role Ansible avec le role EC2

Pour ceux qui ne connaissent pas molecule je vous renvoie à mon premier tutoriel. Créons le role :

Terminal window
molecule init role -d ec2 steph.pyenv

Configuration du scenario molecule

Bon il reste un peu de travail avant d’instancier notre première instance EC2. Commencons par éditer le scenario avec le fichier présent dans le dossier molecule/<nom_scenario>/molecule.yml.

---
dependency:
name: galaxy
driver:
name: ec2
platforms:
- name: instance
image_owner: "099720109477"
image_name: "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-20221201"
instance_type: t3a.micro
vpc_subnet_id: subnet-0b13a91a5bd16a5bf
key_inject_method: ec2
ssh_user: ubuntu
tags:
Name: molecule_instance
provisioner:
name: ansible
verifier:
name: ansible

Quelques explications sur les variables :

  • image_owner : le nom du owner de l’AMI. Ici canonical
  • image_name : le nom de l’AMI
  • instance_type : le type d’instance. Ici une t3a.micro une des moins chères, quelques centimes/heures.
  • vpc_subnet_id : le sous-réseau à utiliser. Dans mon exemple j’utilise le réseau publique accessible directement.
  • key_inject_method : La méthode pour injecter la clé. J’utilise de l’injecter au moment de la création de l’instance.
  • ssh_user: l’utilisateur défini dans l’image qui est fonction du type d’AMI. Pour une ubuntu : ubuntu, pour une Amazon Linux, ec2_user

Toutes les variables sont documentés dans le fichier molecule/<nom_scenario>/create.yml

Création et destruction de l’instance.

Bon tout est prêt lancons le converge pour créer l’instance :

Terminal window
molecule converge
INFO default scenario test matrix: dependency, create, prepare, converge
INFO Performing prerun with role_name_check=0...
INFO Set ANSIBLE_LIBRARY=/home/vagrant/.cache/ansible-compat/4489a2/modules:/home/vagrant/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO Set ANSIBLE_COLLECTIONS_PATH=/home/vagrant/.cache/ansible-compat/4489a2/collections:/home/vagrant/.ansible/collections:/usr/share/ansible/collections
INFO Set ANSIBLE_ROLES_PATH=/home/vagrant/.cache/ansible-compat/4489a2/roles:/home/vagrant/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
INFO Using /home/vagrant/.cache/ansible-compat/4489a2/roles/steph.pyenv symlink to current repository in order to enable Ansible to find the role using its expected full name.
INFO Running default > dependency
WARNING Skipping, missing the requirements file.
WARNING Skipping, missing the requirements file.
INFO Running default > create
PLAY [Create] ******************************************************************
TASK [Validate platform configurations] ****************************************
[WARNING]: Unable to find '/home/vagrant/.cache/molecule/pyenv/default/run-
config.yml' in expected paths (use -vvvvv to see paths)
ok: [localhost] => (item=instance)
TASK [Write run config to file] ************************************************
[WARNING]: Unable to find '/home/vagrant/.cache/molecule/pyenv/default/run-
config.yml' in expected paths (use -vvvvv to see paths)
changed: [localhost]
TASK [Generate local key pairs] ************************************************
changed: [localhost] => (item=instance)
TASK [Look up EC2 AMI(s) by owner and name (if image not set)] *****************
ok: [localhost] => (item=instance)
TASK [Look up subnets to determine VPCs (if needed)] ***************************
ok: [localhost] => (item=instance)
TASK [Validate discovered information] *****************************************
ok: [localhost] => (item=instance)
TASK [Create ephemeral EC2 keys (if needed)] ***********************************
changed: [localhost] => (item=instance)
TASK [Create ephemeral security groups (if needed)] ****************************
changed: [localhost] => (item=instance)
TASK [Create ephemeral EC2 instance(s)] ****************************************
changed: [localhost] => (item=instance)
TASK [Wait for instance creation to complete] **********************************
FAILED - RETRYING: [localhost]: Wait for instance creation to complete (300 retries left).
FAILED - RETRYING: [localhost]: Wait for instance creation to complete (299 retries left).
FAILED - RETRYING: [localhost]: Wait for instance creation to complete (298 retries left).
FAILED - RETRYING: [localhost]: Wait for instance creation to complete (297 retries left).
changed: [localhost] => (item=instance)
TASK [Collect instance configs] ************************************************
ok: [localhost] => (item=instance)
TASK [Write Molecule instance configs] *****************************************
changed: [localhost]
TASK [Start SSH pollers] *******************************************************
changed: [localhost] => (item=instance)
TASK [Wait for SSH] ************************************************************
[WARNING]: The 'finished' test expects an async task, but a non-async task was
tested
ok: [localhost] => (item=instance)
TASK [Wait for boot process to finish] *****************************************
Pausing for 120 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=15 changed=8 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
INFO Running default > prepare
PLAY [Prepare] *****************************************************************
TASK [Make sure python3 is installed] ******************************************
ok: [instance]
PLAY RECAP *********************************************************************
instance : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
INFO Running default > converge
PLAY [Converge] ****************************************************************
TASK [Gathering Facts] *********************************************************
ok: [instance]
TASK [Include steph.pyenv] *****************************************************
PLAY RECAP *********************************************************************
instance : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Pour se connecter dessus puis la détruire :

Terminal window
molecule login
INFO Running default > login
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-1026-aws x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sun Dec 4 15:20:15 UTC 2022
System load: 0.0927734375 Processes: 108
Usage of /: 20.0% of 7.57GB Users logged in: 0
Memory usage: 23% IPv4 address for ens5: 172.31.149.83
Swap usage: 0%
0 updates can be applied immediately.
Last login: Sun Dec 4 15:17:43 2022 from 91.166.20.90
-bash: warning: setlocale: LC_ALL: cannot change locale (fr_FR.UTF-8)
ubuntu@ip-172-31-149-83:~$ exit
molecule destroy

Quelques indications en cas difficultés

Destruction de la VM dans la console AWS

Il se peut que vous rencontriez quelques problèmes. Par exemple vous avez détruit l’instance à la main dans la console EC2 (pas bien), résultat la commande molecule destroy plante. Pour rétablir la situation :

Terminal window
rm -rf ~/.cache/molecule/<nom_du_role>/<nom_scenario/>

Ouf, c’est moins compliqué que lorsque vous perdez le state terraform!

Utilisation dans une CI.

Attention à l’utilisation du scenario Test.

Si vous utilisez la commande molecule test sur ne nombreux rôles, vous risquez de détruire toutes les VM présentes dans le même subnet_id ! Donc 2 solutions, Créez des subnet dédiés à chaque rôle ou retirer destroy du scenario test. Pour cela à la fin du fichier molecule.yml ajoutez ces lignes :

scenario:
test_sequence:
- dependency
- cleanup
- create
- prepare
- converge
- cleanup
- destroy

Je dois vérifier s’il est possible de filtrer les instances par ta, ce qui serait plus simple à mettre en oeuvre.

D’autres cas

Si je trouve d’autres situations, je complèterai le billet.

Plus loin

Il ne vous reste plus qu’à développer vos roles et collections Ansible ! N’oubliez pas la sécurité avant tout en durcissant vos roles Ansible.

A bienôt.