Atelier 1 : Provisionner la VM et configurer avec Ansible
Dans cet atelier, vous créez la VM invitée sur l’hôte KVM, vous la rendez joignable depuis Internet, et vous utilisez Ansible pour amener l’OS à un socle sécurisé et prêt pour Docker.
Partie 2 sur 4 — Aperçu · Atelier 2 : Déployer et livrer · Exploitation et dépannage
- Provisionner une VM invitée KVM avec une IP privée statique et un socle protégé par snapshot
- Rediriger les ports entrants 80/443 de l’hôte KVM vers la VM et vérifier la joignabilité externe
- Choisir entre un reverse proxy nginx manuel et un reverse proxy géré par Ansible
- Configurer l’inventaire Ansible et exécuter les playbooks de socle et de Docker sur la VM
- Prendre et restaurer des snapshots de VM comme points de retour
Sur l’hôte KVM :
- KVM + libvirt installés (
virsh,virt-install) avec le pont NAT par défaut (virbr0,192.168.122.0/24) - Une IP publique statique avec capacité de redirection de ports, plus
iptablesetnetfilter-persistent - L’ISO Ubuntu 22.04 LTS Server disponible sur l’hôte
- Accès SSH + sudo à l’hôte, et accès à la console série pour l’installation de l’OS
Sur votre machine de contrôle :
- Ansible 2.9+ installé, avec les dossiers
inventory/etplaybooks/de ce dépôt récupérés - Le matériel de clé SSH pour l’utilisateur admin de la VM (créé pendant l’installateur de la Phase 1)
Renseignez-les une fois et chaque commande de cette page se met à jour. Les valeurs restent uniquement dans votre navigateur.
Remarque sur les valeurs de ce guide. Les valeurs à personnaliser pour cet atelier —
VM_IP, SSH_KEY_PATH, SSL_DOMAIN, SSL_EMAIL — apparaissent comme des jetons de type
__NOM__ et sont remplies automatiquement dès que vous les saisissez dans le panneau Vos
valeurs de labo ci-dessus. Les autres valeurs (p. ex. <VM_NAME>, <INTERFACE_NAME>) ne sont
pas suivies par ce panneau — remplacez-les vous-même par les vraies valeurs de votre
environnement. Conservez les vraies valeurs dans votre coffre de secrets / gestionnaire de mots
de passe, pas dans ces pages.
Phase 1 — Provisionner la VM sur l’hôte KVM
Toutes les commandes de cette phase s’exécutent sur l’hôte KVM, sauf mention contraire.
La VM invitée se trouve sur le sous-réseau NAT privé de libvirt et n’est pas joignable depuis Internet tant que vous n’avez pas ajouté la redirection de ports (Étape 1.4). L’état final de cette phase est une VM en fonctionnement, protégée par snapshot, avec une IP privée stable, joignable depuis Internet sur les ports 80/443.
Étape 1.1 — Définir les spécifications de la VM
Choisissez des valeurs de ressources adaptées à la charge. Points de départ :
| Paramètre | Exemple |
|---|---|
| Nom de la VM | <VM_NAME> |
| vCPU | 2–8 |
| RAM | 4–64 Go |
| Disque | 50–500 Go (qcow2) |
| OS | Ubuntu 22.04 LTS Server |
| Réseau | NAT libvirt default |
| IP statique | __VM_IP__ (une adresse libre dans 192.168.122.0/24) |
| Utilisateur admin | n’importe quel nom d’utilisateur non root |
Exécutez
osinfo-query os | grep ubuntupour trouver la chaîne--os-variantexacte de votre ISO.
Étape 1.2 — Créer la VM
sudo virt-install \
--name <VM_NAME> \
--ram <RAM_IN_MB> \
--vcpus <NUM_VCPUS> \
--disk path=/var/lib/libvirt/images/<VM_NAME>.qcow2,size=<DISK_GB>,format=qcow2 \
--os-variant ubuntu22.04 \
--network network=default \
--graphics none \
--console pty,target_type=serial \
--location /path/to/ubuntu-22.04-live-server-amd64.iso,kernel=casper/vmlinuz,initrd=casper/initrd \
--extra-args 'console=ttyS0,115200n8 serial'Attachez-vous à la console série pour lancer l’installateur :
sudo virsh console <VM_NAME>Les choix d’installation qui comptent :
- Utilisez le disque entier, sauf besoin de partitionnement personnalisé.
- Créez un utilisateur admin non root dédié avec un mot de passe fort (n’utilisez pas root).
- Activez le serveur OpenSSH quand cela vous est proposé.
- Détachez-vous de la console avec
Ctrl+]une fois l’installation terminée.
Étape 1.3 — Configurer une IP statique
Les adresses DHCP peuvent changer au redémarrage et casser vos règles de redirection de ports, alors fixez une IP statique.
Trouvez le nom de l’interface (généralement enp1s0 sur KVM) :
ip link showÉditez /etc/netplan/00-installer-config.yaml dans la VM et remplacez son contenu :
network:
ethernets:
<INTERFACE_NAME>:
dhcp4: no
addresses:
- __VM_IP__/24
gateway4: <GATEWAY_IP>
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
version: 2Appliquez et vérifiez :
sudo netplan apply
ip addr show <INTERFACE_NAME> # static IP present?
ping -c 3 8.8.8.8 # internet works?Étape 1.4 — Rediriger les ports de l’hôte vers la VM
(Ces commandes s’exécutent sur l’hôte KVM, pas sur la VM.) Redirigez le trafic public entrant vers l’IP privée de la VM.
# DNAT: rewrite destination of inbound :80 / :443 to the VM
sudo iptables -t nat -I PREROUTING 1 -i <PUBLIC_IFACE> -p tcp --dport 80 -j DNAT --to-destination __VM_IP__:80
sudo iptables -t nat -I PREROUTING 1 -i <PUBLIC_IFACE> -p tcp --dport 443 -j DNAT --to-destination __VM_IP__:443
# FORWARD: allow the routed traffic (insert at position 1, BEFORE libvirt's REJECT rules)
sudo iptables -I FORWARD 1 -p tcp -d __VM_IP__ --dport 80 -j ACCEPT
sudo iptables -I FORWARD 1 -p tcp -d __VM_IP__ --dport 443 -j ACCEPT
# Persist across reboots (iptables rules are volatile by default)
sudo apt install netfilter-persistent -y
sudo netfilter-persistent saveToujours -I FORWARD 1 (insertion), jamais -A (ajout en fin). Un ajout en fin place votre
règle après la règle REJECT par défaut de libvirt, qui rejette silencieusement le trafic
redirigé.
Vérifiez :
sudo iptables -t nat -L PREROUTING --line-numbers
sudo iptables -L FORWARD --line-numbersÉtape 1.5 — (Optionnel) Reverse proxy au niveau de l’hôte
La documentation de provisionnement de la VM inclut une mise en place manuelle d’un reverse
proxy nginx sur la VM (ports 80/443 → 127.0.0.1:<APP_PORT>, initialement avec un certificat
auto-signé « snakeoil »). Vous avez deux options et devez en choisir une — ne faites pas les
deux :
- Option A (recommandée pour cette plateforme) : sautez le nginx manuel ici et laissez les playbooks Ansible 02 + 04 (Phase 2) installer et configurer nginx + un vrai certificat Let’s Encrypt. Cela garde la couche web de la VM reproductible.
- Option B : si vous voulez que la VM soit joignable avant d’exécuter Ansible, faites la mise en place manuelle de nginx maintenant, puis laissez le playbook nginx d’Ansible prendre le relais ensuite.
Dans les deux cas, le travail du reverse proxy est le même : terminer 80/443 sur la VM et
transférer vers les ports des conteneurs applicatifs (Prefect 14200, Superset 18088, Dagster
13000 — voir la Phase 4).
Étape 1.6 — Prendre un snapshot de référence
Capturez un état propre et réputé sain vers lequel revenir.
sudo virsh snapshot-create-as \
--domain <VM_NAME> \
--name "baseline-post-provision" \
--description "Clean provision: static IP set, ports 80/443 forwarded" \
--atomicRevenez-y plus tard si nécessaire :
sudo virsh shutdown <VM_NAME>
sudo virsh snapshot-revert --domain <VM_NAME> --snapshotname baseline-post-provision
sudo virsh start <VM_NAME>Il existe une version entièrement automatisée de toute la Phase 1 (
provision-vm.sh) — éditez son bloc de configuration et exécutezsudo bash provision-vm.sh.
Checklist de sortie de la phase 1
| # | Vérification | Commande |
|---|---|---|
| 1 | VM en fonctionnement | sudo virsh list --all |
| 2 | IP statique présente et conservée au redémarrage | ip addr show <IFACE> puis sudo virsh reboot <VM_NAME> |
| 3 | Règles DNAT présentes | sudo iptables -t nat -L PREROUTING --line-numbers |
| 4 | Règles FORWARD ACCEPT en tête | sudo iptables -L FORWARD --line-numbers |
| 5 | Joignabilité externe (depuis une machine extérieure) | nc -zv <PUBLIC_IP> 80 / 443 |
| 6 | Snapshot de référence existant | sudo virsh snapshot-list --domain <VM_NAME> |
Piège : tester
nc -zv <PUBLIC_IP>depuis l’intérieur de la VM bloque — le NAT libvirt ne prend pas en charge le routage en épingle à cheveux (une VM joignant sa propre IP publique). Testez toujours depuis une machine externe.
$ sudo virsh snapshot-list --domain <VM_NAME>
Name Creation Time
-------------------------------------------------------
baseline-post-provision 2026-07-01 10:12:03 -0400
$ nc -zv <PUBLIC_IP> 80
Connection to <PUBLIC_IP> 80 port [tcp/http] succeeded!Vous ne voyez pas cela ?
virsh snapshot-listest vide — l’Étape 1.6 n’a pas été exécutée, ou--atomica échoué silencieusement. Relancez la commandesnapshot-create-aset vérifiez les erreurs.nc -zvexpire — vous avez testé depuis l’intérieur de la VM (le routage en épingle à cheveux n’est pas supporté), ou la règleFORWARDa été ajoutée en fin (-A) au lieu d’être insérée en position 1. Vérifiez avecsudo iptables -L FORWARD --line-numbers.
Phase 2 — Configurer la VM avec Ansible
S’exécute depuis votre machine de contrôle, en ciblant la VM.
Maintenant que la VM existe et est joignable, utilisez les playbooks Ansible pour amener l’OS à un socle connu et sécurisé, et installer l’environnement d’exécution dont les conteneurs de l’entrepôt ont besoin (Docker). Cette section est la séquence opérationnelle.
Étape 2.1 — Pointer l’inventaire vers la VM
Éditez inventory/hosts.yml :
all:
vars:
ansible_user: <VM_ADMIN_USER> # the non-root user created in Phase 1
ansible_ssh_private_key_file: __SSH_KEY_PATH__
ansible_host_key_checking: false
hosts:
server1:
ansible_host: __VM_IP__ # or the public IP if reaching via port-forwardConfirmez la connectivité :
ansible all -m pingserver1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}Vous ne voyez pas cela ?
UNREACHABLE!— l’IP ou le chemin de la clé SSH dansinventory/hosts.ymlest incorrect, ou le pare-feu de la VM n’est pas encore actif (seule l’Étape 1 l’a provisionné ; le port 22 est ouvert par défaut sur Ubuntu Server).Permission denied (publickey)—ansible_userne correspond pas à l’utilisateur non root créé pendant l’installateur à l’Étape 1.2, ou les permissions du fichier de clé sont trop ouvertes (chmod 600).
Étape 2.2 — Exécuter les playbooks dans l’ordre
Les playbooks sont numérotés dans l’ordre d’exécution. Pour la VM entrepôt, les essentiels sont 01 (socle) et 05 (Docker) — l’application embarque son propre nginx/Postgres dans des conteneurs ou utilise le Postgres externe, donc 02/03/04/06 sont optionnels selon la manière dont vous exposez la stack.
# 1. Base OS: updates, essentials, UFW firewall, fail2ban (REQUIRED)
ansible-playbook playbooks/01-server-setup.yml --ask-become-pass
# 2. nginx — only if you want Ansible (not manual Phase 1.5) to manage the reverse proxy
ansible-playbook playbooks/02-nginx.yml --ask-become-pass
# 4. SSL/Let's Encrypt — only if a domain points at the public IP (needs playbook 02 first)
ansible-playbook playbooks/04-ssl-certbot.yml \
-e ssl_domain="__SSL_DOMAIN__" -e ssl_email="__SSL_EMAIL__" --ask-become-pass
# 5. Docker + Docker Compose (REQUIRED — the warehouse runs as containers)
ansible-playbook playbooks/05-docker.yml --ask-become-pass
# On Ubuntu 20.04 "focal" use: playbooks/05-docker-focal.ymlLes playbooks 03 (PostgreSQL) et 06 (create-database) installent un Postgres local sur la VM. L’entrepôt MNCH utilise à la place un serveur Postgres externe (voir la Phase 4). N’exécutez 03/06 que si vous comptez héberger les bases de données sur la VM elle-même — sinon, sautez-les et pointez l’application vers votre base externe via les secrets de la Phase 3.
Étape 2.3 — Note sur le pare-feu
Le playbook 01 active UFW avec une politique entrante de refus par défaut et n’ouvre que SSH (22). Le playbook 02 ouvre 80/443. Si vous exposez directement les ports des conteneurs (14200/18088/13000) au lieu de passer par le proxy nginx, ouvrez-les explicitement :
ansible all -b -m ufw -a "rule=allow port=18088 proto=tcp" # example: SupersetChecklist de sortie de la phase 2
-
ansible all -m pingréussit -
01exécuté :ansible all -b -m command -a "ufw status"montre le pare-feu actif, SSH autorisé -
05exécuté :ansible all -m command -a "docker --version"etdocker-compose --versionréussissent - (le cas échéant) nginx actif et 80/443 ouverts
$ ansible all -b -m command -a "ufw status"
server1 | CHANGED | rc=0 >>
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
$ ansible all -m command -a "docker --version"
server1 | CHANGED | rc=0 >>
Docker version 24.0.7, build afdd53bVous ne voyez pas cela ?
ufw statusafficheinactive— le playbook 01 ne s’est pas terminé correctement ; relancezansible-playbook playbooks/01-server-setup.yml --ask-become-passet vérifiez les tâches en échec.docker: command not found— le playbook 05 a échoué, ou vous êtes sur Ubuntu 20.04 « focal » et devez utiliserplaybooks/05-docker-focal.ymlau lieu de05-docker.yml.
Prenez un nouveau snapshot maintenant (
virsh snapshot-create-as … --name "post-ansible-config") afin d’avoir un point de retour avant d’empiler l’application par-dessus.
Nettoyage
Si vous avez terminé avec cet environnement de labo, démontez ce que les Phases 1–2 ont créé :
# supprimer les règles de redirection de ports ajoutées à l’Étape 1.4
sudo iptables -t nat -D PREROUTING -i <PUBLIC_IFACE> -p tcp --dport 80 -j DNAT --to-destination __VM_IP__:80
sudo iptables -t nat -D PREROUTING -i <PUBLIC_IFACE> -p tcp --dport 443 -j DNAT --to-destination __VM_IP__:443
sudo iptables -D FORWARD -p tcp -d __VM_IP__ --dport 80 -j ACCEPT
sudo iptables -D FORWARD -p tcp -d __VM_IP__ --dport 443 -j ACCEPT
sudo netfilter-persistent save # persister la suppression
# arrêter et supprimer la VM ainsi que ses snapshots
sudo virsh destroy <VM_NAME> # extinction
sudo virsh undefine <VM_NAME> --remove-all-storage --snapshots-metadataSi vous poursuivez avec l’Atelier 2, ignorez cette section — conservez la VM et ses snapshots comme points de retour.
La suite
La VM est provisionnée et configurée. Poursuivez avec Atelier 2 : CI/CD, stack entrepôt et mise en production pour câbler le pipeline de déploiement et mettre en service l’application d’entrepôt.