Porter un manifest Puppet vers un playbook Ansible en traduisant chaque ressource ligne à ligne semble être le chemin le plus direct, et pourtant ce portage casse fréquemment de façon silencieuse : la différence ne vient pas du langage (Ruby DSL contre YAML), mais de la façon dont chaque outil détermine l’ordre d’exécution réel des opérations.
Puppet : un graphe de dépendances résolu avant exécution
Puppet ne décrit pas une séquence d’actions, mais un ensemble de ressources et leurs relations déclarées (require, before, notify) : l’agent Puppet construit un graphe de dépendances à partir de ces relations, puis détermine l’ordre d’application en résolvant ce graphe, indépendamment de l’ordre dans lequel les ressources apparaissent dans le manifest.
# L'ordre d'écriture ici n'a aucune importance :
# Puppet installe le paquet avant de démarrer le service
# uniquement à cause de la relation 'require' déclarée
service { 'nginx':
ensure => running,
require => Package['nginx'],
}
package { 'nginx':
ensure => installed,
}
Ansible : l’ordre écrit est l’ordre exécuté
Ansible exécute les tâches d’un playbook séquentiellement, dans l’ordre exact où elles sont écrites, sans résolution de graphe de dépendances implicite : l’ordre d’écriture n’est pas une suggestion, c’est le comportement réel garanti.
# Ici, l'ordre d'écriture EST l'ordre d'exécution :
# installer le paquet doit être écrit avant de démarrer
# le service, Ansible ne le déduira jamais tout seul
- name: Installer nginx
apt:
name: nginx
state: present
- name: Démarrer nginx
service:
name: nginx
state: started
Pourquoi le portage ligne à ligne échoue silencieusement
Traduire un manifest Puppet en playbook Ansible en préservant l’ordre d’apparition des ressources (plutôt que l’ordre réel résolu par le graphe de dépendances Puppet) peut produire un playbook qui tente de démarrer un service avant que le paquet correspondant ne soit installé, un bug qui n’apparaît souvent qu’au premier déploiement sur une machine neuve où l’ordre implicite précédemment garanti par Puppet n’a plus aucun effet.
Le vrai travail de migration
Une migration réussie de Puppet vers Ansible ne traduit jamais un manifest ligne à ligne : elle reconstruit d’abord l’ordre de dépendance réel entre les ressources (souvent en inspectant le graphe généré par puppet catalog ou puppet apply --graph), avant d’écrire les tâches Ansible dans cet ordre explicite. Ce travail préalable, plus long qu’une simple traduction syntaxique, est ce qui distingue une migration qui tient debout d’un portage qui casse au premier redéploiement sur une machine dans un état différent.
À retenir
Puppet résout un graphe de dépendances déclaré (require, before, notify) avant d’exécuter quoi que ce soit, l’ordre d’écriture du manifest n’ayant aucune influence sur l’ordre réel d’application. Ansible exécute les tâches strictement dans l’ordre où elles sont écrites, sans résolution implicite d’aucune sorte, la même distinction fondamentale de rôle déjà posée entre Terraform et Ansible (état déclaratif contre exécution procédurale ordonnée). Porter un manifest Puppet vers Ansible en préservant l’ordre d’apparition plutôt que l’ordre de dépendance réel casse silencieusement, souvent uniquement visible au premier déploiement sur une machine neuve : la migration exige de reconstruire explicitement cet ordre avant de traduire la syntaxe, pas l’inverse.