Developper Roles et Collections Ansible AWS EC2
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
.
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.
asdf plugin add aws-cliasdf install aws-cli latestasdf set --home aws-cli latest
Passons à la configuration du compte en créant au prélable un compte sur IAM ↗ :
aws configureAWS Access Key ID [None]: xxxxxxxxxxAWS Secret Access Key [None]: xxxxx/xx/xxxxxxxxxxxxxxxxxxxxDefault region name [None]: eu-west-3Default 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 :
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: galaxydriver: name: ec2platforms: - 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: ansibleverifier: 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 :
molecule converge
INFO default scenario test matrix: dependency, create, prepare, convergeINFO 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/modulesINFO Set ANSIBLE_COLLECTIONS_PATH=/home/vagrant/.cache/ansible-compat/4489a2/collections:/home/vagrant/.ansible/collections:/usr/share/ansible/collectionsINFO Set ANSIBLE_ROLES_PATH=/home/vagrant/.cache/ansible-compat/4489a2/roles:/home/vagrant/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/rolesINFO 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 > dependencyWARNING 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 wastestedok: [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 :
molecule loginINFO Running default > loginWelcome 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 :
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.