Aller au contenu
English
Cloud medium

Packer sur Scaleway : construire une image, et vérifier ce qu'elle laisse

Mesuré live le ·fr-par·Packer 1.15.0, plugin scaleway 1.5.0, scw 2.62.0

60 min de lecture

Un build Packer démarre une vraie machine, produit un snapshot puis une image, et trois objets lui survivent : l'image, le snapshot, et un volume orphelin que rien ne signale. C'est ce qui rend Packer différent de Terraform et d'Ansible dans ce volet : il coûte à chaque exécution, et il laisse quelque chose derrière lui, y compris quand il échoue. Cette leçon construit une image durcie avec le plugin officiel 1.5.0, puis s'attarde longuement sur la vérification de sortie, parce que c'est là que se joue la facture. Vous en repartirez avec un modèle épinglé et vérifié, une image démarrable, et surtout la liste des objets à contrôler après chaque build, y compris ceux qu'un build interrompu laisse invisibles.

  • Épingler le plugin et vérifier ce que vous installez.
  • Construire une image durcie, avec un provisionneur minimal.
  • Reconnaître ce qu'un build laisse derrière lui, réussi ou interrompu.
  • Nettoyer dans l'ordre qu'imposent les dépendances.

Plugin ou provider : comment Packer nomme-t-il les choses ?

Section intitulée « Plugin ou provider : comment Packer nomme-t-il les choses ? »

Chez Packer on dit plugin et builder, jamais provider. Le terme provider appartient à Terraform, et le confondre coûte une recherche documentaire infructueuse.

TerraformPacker
un providerun plugin, qui expose un ou plusieurs builders
required_providersrequired_plugins
resource "scaleway_instance_server"source "scaleway" "…"

Comment épingler et vérifier le plugin Packer Scaleway ?

Section intitulée « Comment épingler et vérifier le plugin Packer Scaleway ? »

Le plugin officiel est en version 1.5.0, publiée le 17 juin 2026. Il se déclare dans le modèle, ce qui le rend reproductible.

packer {
required_plugins {
scaleway = {
source = "github.com/scaleway/scaleway"
version = ">= 1.5.0"
}
}
}
Fenêtre de terminal
packer init .
packer plugins installed

La seconde commande liste les plugins réellement présents, avec leur version. C'est la réponse à la question qui ouvre tout dépannage : ai-je bien ce que je crois avoir ?

À quoi ressemble un modèle Packer Scaleway minimal ?

Section intitulée « À quoi ressemble un modèle Packer Scaleway minimal ? »

Le builder démarre une Instance, exécute vos commandes, en fait un snapshot, puis une image. Chacune de ces étapes se voit dans la sortie et se facture.

source "scaleway" "socle" {
zone = "fr-par-1"
commercial_type = "DEV1-S"
image = "ubuntu_jammy"
ssh_username = "root"
# Nommer explicitement, la raison est expliquée plus bas.
image_name = "socle-{{timestamp}}"
server_name = "packer-socle-{{timestamp}}"
server_tags = ["packer", "socle"]
}
build {
sources = ["source.scaleway.socle"]
provisioner "shell" {
inline = [
"apt-get update -qq",
"apt-get install -y --no-install-recommends ca-certificates curl",
"apt-get clean && rm -rf /var/lib/apt/lists/*",
]
}
}
Fenêtre de terminal
time packer build socle.pkr.hcl

Chronométrez le premier build. C'est la mesure qui décidera plus tard si votre mise à l'échelle automatique a un sens : une image qui contient déjà l'application démarre en une minute là où une installation au démarrage en demande cinq.

Mesuré le 2026-09-14 avec Packer 1.15.0 et le plugin 1.5.0, sur ubuntu_jammy et une DEV1-S en fr-par-1 : le build complet a pris 1 minute 9 secondes, de Creating server... à Destroying server..., et s'est terminé par la ligne qui compte :

An image was created: 'socle-1789403110' (ID: 252766f7-f667-4c9c-ae96-2bffd9646447)
in zone 'fr-par-1' based on snapshots [(: 600475ff-a1e1-4593-b4fb-bc286b49a4cf)]

Retenez l'UUID entre parenthèses, pas le nom : scw instance image get refuse socle-1789403110 avec 'socle-1789403110' is not a valid UUID, et c'est cet identifiant qu'il faudra pour supprimer l'image.

Ce que le build consommeTarifSur quinze minutes
une Instance DEV1-Senviron 0,009 €/hmoins d'un centime
une adresse publique, exigée le temps du build0,005 €/hnégligeable
le snapshot produitau gigaoctettant qu'il existe
l'image produiteau gigaoctettant qu'elle existe
le volume racine du serveur temporaire, laissé orphelinau gigaoctettant qu'il existe

Le build coûte des centimes. Ce sont les trois objets qui lui survivent qui coûtent, et ils ne se rappellent jamais à votre souvenir.

Trois objets, dont un que la sortie de Packer ne mentionne pas. Relevé le 2026-09-14, une minute après le An image was created, en relistant les quatre familles concernées :

Fenêtre de terminal
scw instance image list zone=fr-par-1
scw instance snapshot list zone=fr-par-1
scw block snapshot list zone=fr-par-1
scw block volume list zone=fr-par-1
FamilleCe qu'on y trouveNom relevé
instance imagel'image, avec le nom donné par image_namesocle-1789403110
instance snapshotrien, la liste est vide-
block snapshotle snapshot du volume racine, 10 Go, nom générésnp-kind-mccarthy
block volumeun volume orphelin, references=[], nommé d'après l'image sourceUbuntu 22.04 Jammy Jellyfish_sbs_volume_0

Le serveur temporaire et son adresse ont bien disparu, scw instance server list et scw instance ip list reviennent vides. Mais le volume racine du serveur lui a survécu : le plugin en a pris un snapshot, a créé l'image, puis a détruit le serveur sans supprimer le volume, qui reste facturé au gigaoctet alors qu'aucune image ni aucun snapshot ne pointe vers lui. Un script de nettoyage écrit d'après la famille historique instance snapshot conclut que tout est propre, et laisse deux objets sur trois.

Un build qui échoue laisse le même volume facturé, et rien ne le signale, pas même une image. Après un build réussi, l'image et le snapshot rappellent au moins qu'un build a eu lieu ; après un échec, il ne reste que le volume. Mesuré le 2026-09-14 avec le plugin 1.5.0 et Packer 1.15.0.

Provoquez-le, c'est la seule façon de retenir le réflexe.

  1. Faites échouer le provisionnement volontairement

    provisioner "shell" {
    inline = ["exit 1"]
    }
    Fenêtre de terminal
    packer build socle.pkr.hcl

    Packer détruit le serveur, et la sortie se termine sur une erreur nette :

    ==> scaleway.socle: Provisioning step had errors: Running the cleanup provisioner, if present...
    ==> scaleway.socle: Destroying server...
    Build 'scaleway.socle' errored after 24 seconds 552 milliseconds: Script exited with non-zero exit status: 1. Allowed exit codes are: [0]
    ==> Builds finished but no artifacts were created.

    Vingt-quatre secondes, code de retour 1, « no artifacts were created » : tout semble propre.

  2. Regardez ce qui reste

    Fenêtre de terminal
    scw instance server list zone=fr-par-1
    scw block volume list zone=fr-par-1

    Dans les secondes qui suivent, le serveur packer-socle-echec-… peut encore apparaître, en cours de suppression, avec son volume marqué references=1. Quelques instants plus tard, la première liste est vide et la seconde ne l'est pas : le volume racine, Ubuntu 22.04 Jammy Jellyfish_sbs_volume_0, est orphelin, references=[], et ses 10 Go se facturent. Aucune image, aucun snapshot ne le signale : c'est le reste le plus discret de tout ce volet.

  3. Supprimez ce qui traîne

    Fenêtre de terminal
    scw block volume delete volume-id=VOTRE_VOLUME_ID zone=fr-par-1

    La sortie doit afficher Volume has been successfully deleted.

  4. Retenez la règle plutôt que le cas

    On reliste après chaque build, pas seulement après ceux qui échouent. Un Ctrl+C pendant le provisionnement produit exactement le même reste.

Une adresse publique est exigée. Le builder joint la machine temporaire par une adresse publique, Using SSH communicator to connect: 203.0.113.20 dans la sortie du build, et le cas « construire depuis un réseau privé, sans exposition Internet » n'est pas couvert aujourd'hui, sans échéance annoncée. L'adresse est libérée à la fin du build, scw instance ip list revient vide, mais le temps du build elle se facture et le trafic passe par Internet.

cloud-init passe par user_data, et il n'y a pas de raccourci. Le builder expose bien un argument user_data, une table de clés, et la clé réservée cloud-init y reçoit votre configuration. Ce qui manque est le confort :

user_data = {
cloud-init = file("cloud-init.yaml")
}

Ce qui manque côté plugin est un argument dédié du type user_data_file et un exemple documenté, pas le support lui-même. Ne concluez donc pas que cloud-init est hors de portée du builder : il fonctionne, il se déclare simplement par cette porte.

La question mérite d'être posée dans le bon ordre, parce qu'elle recoupe ce que vous avez appris au volet Fondations : cloud-init personnalise une machine au démarrage, Packer personnalise l'image dont elle démarre. Ce qui doit valoir pour toutes les machines va dans l'image ; ce qui dépend de la machine, son nom, ses clés, son rôle, reste dans cloud-init.

Dans quel ordre supprimer une image et son snapshot ?

Section intitulée « Dans quel ordre supprimer une image et son snapshot ? »

L'ordre n'est pas libre : une image verrouille le snapshot dont elle est issue. Tenter de supprimer le snapshot en premier échoue, relevé le 2026-09-14, et c'est le même piège qu'en ligne de commande :

scaleway-sdk-go: precondition failed: , Snapshot is currently in use, deletion is not permitted.
  1. L'image d'abord

    Fenêtre de terminal
    scw instance image list zone=fr-par-1
    scw instance image delete VOTRE_IMAGE_ID zone=fr-par-1

    La sortie doit afficher Image has been successfully deleted. L'identifiant est l'UUID de la ligne An image was created, pas le nom.

  2. Le snapshot ensuite, avec la bonne commande

    Le choix dépend du type du volume d'origine, exactement comme au volet Fondations. Sur ubuntu_jammy et une DEV1-S, le volume racine est un volume Block : scw instance snapshot list renvoie une liste vide, et le snapshot vit dans block snapshot.

    Fenêtre de terminal
    scw instance snapshot list zone=fr-par-1
    scw instance snapshot delete VOTRE_SNAPSHOT_ID zone=fr-par-1
    scw block snapshot list zone=fr-par-1
    scw block snapshot delete snapshot-id=VOTRE_SNAPSHOT_ID zone=fr-par-1

    La sortie doit afficher Snapshot has been successfully deleted.

  3. Les restes du build, s'il en subsiste

    Fenêtre de terminal
    scw instance server list zone=fr-par-1
    scw block volume list zone=fr-par-1
    scw instance ip list zone=fr-par-1
  4. La vérification de sortie

    Six listes, et six doivent correspondre à ce que vous attendez :

    Fenêtre de terminal
    scw instance image list
    scw instance snapshot list zone=fr-par-1
    scw block snapshot list zone=fr-par-1
    scw block volume list zone=fr-par-1
    scw instance ip list zone=fr-par-1
    scw instance server list zone=fr-par-1

Gardez l'image si elle vous sert, et gardez alors son snapshot avec elle : tant que l'image existe, l'API refuse de supprimer le snapshot dont elle est issue, c'est le message relevé plus haut. Le volume orphelin, lui, se supprime tout de suite et dans tous les cas : rien n'en dépend, et rien ne le signale.

Image dorée ou cloud-init : que faut-il figer dans l'image ?

Section intitulée « Image dorée ou cloud-init : que faut-il figer dans l'image ? »

Tout ce qu'on met dans l'image se paie au stockage et se refait à chaque mise à jour ; tout ce qu'on laisse à cloud-init s'exécute à chaque démarrage et ralentit la mise à disposition. L'arbitrage se fait donc sur la fréquence de changement, pas sur la commodité. Le tableau ci-dessous se lit par la colonne de gauche : partez de ce que vous voulez installer, et regardez à quelle vitesse cet élément change dans votre contexte.

BesoinChoixPourquoi
Durcissement système, agents de supervision, dépôts internesdans l'image, avec Packerchange rarement, et doit être identique sur toute la flotte dès le premier démarrage
Version applicative, artefact de livraisondans l'image, une image par versionrend le déploiement reproductible, et le retour arrière possible en repointant l'image précédente
Clés d'hôte SSH, identifiants, secretsjamais dans l'imagel'image se duplique, le secret aussi ; il arrive au démarrage ou par un coffre
Configuration propre à l'environnement, nom d'hôte, adressescloud-init, au démarrageces valeurs diffèrent par machine, les figer imposerait une image par environnement
Correctif de sécurité urgent sur une flotte en productionAnsible tout de suite, puis Packerreconstruire et redéployer prend plus longtemps que la fenêtre d'exposition

Ce qui vous arrêtera n'est pas le nombre d'images, c'est leur poids cumulé. Les valeurs ci-dessous viennent de la page officielle des quotas d'Organisation de Scaleway, dont la date de validation est le 29 octobre 2025. Elles expliquent pourquoi un build qui laisse des restes ne pose aucun problème pendant des semaines, puis bloque brutalement.

PlafondSans vérification d'identitéAvec vérification
Snapshots99 99999 999
Images99 99999 999
Volumes2005 000
Stockage Block total500 Go5 000 Go
Stockage local total1 000 Go5 000 Go

L'asymétrie entre ces lignes est le vrai enseignement. Le nombre de snapshots et d'images est si haut qu'on peut le considérer comme non contraignant, mais le volume total est plafonné à 500 Go tant que l'identité du compte n'est pas vérifiée. Une image de système durci pèse couramment une dizaine de gigaoctets, et un build en laisse potentiellement deux, l'image et son snapshot. À raison de quelques builds par semaine sans ménage, le plafond de stockage est atteint en un ou deux mois, et le message d'erreur porte alors sur le quota, pas sur l'oubli qui l'a rempli. Personne ne fait le lien avec les builds interrompus des semaines précédentes.

Deux autres limites viennent du plugin lui-même. Un build exige une adresse publique sur le serveur temporaire : construire depuis un réseau privé sans exposition Internet n'est pas possible aujourd'hui, et aucune échéance n'est annoncée. Et cloud-init passe par user_data sans raccourci : le passage fonctionne, c'est l'argument dédié et l'exemple officiel qui manquent.

Ces erreurs ont en commun de rendre l'image non reproductible ou non traçable, c'est-à-dire de lui retirer la seule chose qui justifiait de la construire. Une image dont on ne sait ni ce qu'elle contient ni comment la refaire est plus dangereuse qu'une installation manuelle, parce qu'elle se duplique.

AntipatternConséquenceDiscipline
Contrainte de plugin flottante (>= 1.5.0)une publication amont déplace une option et casse le modèle sans commit de votre côté, comme snapshot_name sorti de la racine du bloc source en 1.5.0épingler la version exacte dans required_plugins
Secrets ou clés d'hôte SSH cuits dans l'imagechaque machine née de cette image partage le même secret, et le révoquer impose de tout reconstruiresecrets au démarrage, jamais à la construction
Reconstruire une image à chaque déploiementle stockage s'accumule contre le plafond de 500 Go, et le temps de build s'ajoute à chaque livraisonune image par version applicative
Ne pas vérifier après un build échouéle volume racine reste orphelin et facturé, sans image ni snapshot pour le signalervérification de sortie systématique, y compris et surtout après un échec
Supprimer le snapshot avant l'imagel'API refuse, l'image verrouille son snapshotsupprimer l'image d'abord, le snapshot ensuite

Une image est un livrable, avec les mêmes exigences qu'un binaire. Les trois piliers ci-dessous posent la question qu'un auditeur poserait, et la discipline qui y répond.

Question clé : sauriez-vous refaire à l'identique l'image qui tourne aujourd'hui en production ? Si le modèle n'est pas versionné, ou si le plugin n'est pas épinglé, la réponse est non, et l'image devient un artefact irremplaçable au lieu d'un livrable reproductible.

Discipline : versionner le modèle avec le code applicatif, épingler le plugin à la version exacte, et étiqueter chaque image avec la référence du commit qui l'a produite.

Question clé : que contient cette image que vous n'y avez pas mis ? Le plugin est distribué avec un fichier SHA256SUMS et sa signature PGP : ne pas les vérifier revient à exécuter du code non authentifié sur la machine qui fabrique vos images de production.

Discipline : vérifier la signature avant l'installation, ne jamais cuire de secret dans l'image, et régénérer les clés d'hôte SSH au premier démarrage plutôt que de les hériter du modèle.

Question clé : combien vous coûtent les builds du trimestre, ratés ou non ? Un build réussi laisse un volume Block orphelin à côté de l'image et du snapshot ; un build interrompu laisse le même volume, sans image ni snapshot pour le signaler. Mesuré le 2026-09-14 avec le plugin 1.5.0 : 10 Go par build, dans les deux cas.

Discipline : contrôler les volumes après chaque build, y compris et surtout après un échec, supprimer les images de version obsolète, et surveiller le stockage cumulé plutôt que le nombre d'objets.

SymptômeCauseSolution
Un modèle qui construisait ne construit plussnapshot_name retiré de la racine du bloc source en 1.5.0le déplacer dans root_volume {} ou block_volume {}, où il reste valide
Un volume facturé après un build, réussi ou échouéle plugin ne supprime pas le volume racine du serveur temporaire, mesuré avec la 1.5.0relister scw block volume list après chaque build
Un nettoyage par préfixe laisse des objetsquatre noms pour un build, un seul avec le préfixe packer-nommer explicitement, puis relister par famille
'socle-…' is not a valid UUIDscw instance image get et delete attendent l'identifiant, pas le nomreprendre l'UUID de la ligne An image was created
packer build refuse de démarrer sans adresseune adresse publique est exigéelimite actuelle, prévoir l'adresse et son coût
Snapshot is currently in use, deletion is not permitted.une image le verrouillesupprimer l'image d'abord
cannot find resource 'instance_volume'snapshot d'un volume Block par l'API Instanceutiliser scw block snapshot
Recherche documentaire infructueuse« provider Packer » n'existe paschercher plugin et builder

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  • Packer coûte à chaque exécution, contrairement à Terraform et Ansible : une Instance, une adresse, un snapshot et une image.
  • Trois objets survivent à un build réussi : l'image, un snapshot Block au nom généré, et un volume racine orphelin de 10 Go au nom de l'image source, mesuré le 2026-09-14.
  • Un build interrompu laisse le même volume orphelin, sans image ni snapshot pour le signaler : on reliste après chaque build, réussi ou non.
  • Le nettoyage par préfixe ne fonctionne pas : sur un seul build, seul le serveur temporaire, déjà détruit, porte le préfixe packer-.
  • Une image verrouille son snapshot : Snapshot is currently in use, deletion is not permitted. On supprime l'image d'abord, par son UUID.
  • snapshot_name a quitté la racine du bloc source en 1.5.0 : il reste valide dans root_volume {} et block_volume {}.
  • Une adresse publique est exigée pour joindre la machine temporaire ; construire en réseau privé n'est pas couvert.
  • L'image porte ce qui vaut pour toutes les machines, cloud-init ce qui dépend de chacune.
  • Vérifiez la signature du plugin : c'est lui qui fabrique les images de vos machines.

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn