Aller au contenu
Cloud medium

Référence Packer sur OUTSCALE — builder outscale-bsu, variables, patterns Well-Architected

16 min de lecture

logo 3ds outscale

Cette référence récapitule l’usage du plugin Packer OUTSCALE : configuration du plugin, builder outscale-bsu (paramètres requis et optionnels), authentification via variables d’environnement, source_omi_filter pour la sélection dynamique de l’OMI source, block device mappings (pour la build et pour l’image résultante), intégration Ansible comme provisionneur, patterns alignés sur les piliers Well-Architected et antipatterns observés. Tous les paramètres listés ici sont validés contre la documentation officielle du plugin.

ComposantVersion cibleNote
Plugin Packer OUTSCALEgithub.com/outscale/outscale v1.5.0Builder principal outscale-bsu, plus outscale-chroot, outscale-bsusurrogate, outscale-bsuvolume.
Packer1.7+ recommandéFormat HCL2 supporté nativement.
AnsibleTout version récenteIntégration via le provisionneur officiel ansible.

WAF — Operational Excellence. Pinner les versions des plugins dans le required_plugins block et committer le résultat de packer init rend le pipeline OMI reproductible.

packer {
required_version = ">= 1.7.0"
required_plugins {
outscale = {
version = ">= 1.5.0"
source = "github.com/outscale/outscale"
}
ansible = {
version = "~> 1"
source = "github.com/hashicorp/ansible"
}
}
}

Initialisation depuis le répertoire du fichier .pkr.hcl :

Fenêtre de terminal
packer init .

WAF — Security. Les credentials ne se mettent jamais en dur dans le code Packer. Utiliser les variables d’environnement standard OUTSCALE, alimentées via direnv ou via le runner CI.

VariableUsage
OUTSCALE_ACCESSKEYIDAccess key (équivalent paramètre access_key)
OUTSCALE_SECRETKEYIDSecret key (équivalent secret_key)
Fenêtre de terminal
export OUTSCALE_ACCESSKEYID="..."
export OUTSCALE_SECRETKEYID="..."

Avec ces deux variables exportées, les attributs access_key et secret_key peuvent être omis du bloc source — Packer les lit automatiquement.

WAF — Operational Excellence, Performance, Cost. Le choix du vm_type de build et de la source_omi détermine la durée et le coût du build, et la base sur laquelle Ansible va construire.

Les paramètres obligatoires (validés sur la doc officielle du plugin) :

ParamètreTypeDescription
access_keystringAccess key OUTSCALE (peut venir de OUTSCALE_ACCESSKEYID).
secret_keystringSecret key OUTSCALE (peut venir de OUTSCALE_SECRETKEYID).
regionstringRégion cible — eu-west-2 ou cloudgouv-eu-west-1.
vm_typestringType TINA de la VM utilisée pour le build (par exemple tinav6.c4r8p2).
source_omistringOMI source utilisée comme base — peut être renseignée dynamiquement via source_omi_filter.
omi_namestringNom unique de l’OMI résultante. Utiliser {{timestamp}} pour éviter les collisions.
source "outscale-bsu" "ubuntu_2204" {
region = "eu-west-2"
vm_type = "tinav5.c2r4p2"
source_omi = "ami-a3ca408c"
omi_name = "ubuntu-2204-hardened-{{timestamp}}"
ssh_username = "outscale"
communicator = "ssh"
ssh_interface = "public_ip"
}

Sélection dynamique de la source : source_omi_filter

Section intitulée « Sélection dynamique de la source : source_omi_filter »

WAF — Operational Excellence. Plutôt que de hardcoder un source_omi = "ami-a3ca408c" (qui change à chaque rotation d’image officielle), utiliser un filtre :

source "outscale-bsu" "ubuntu_2204" {
region = "eu-west-2"
vm_type = "tinav5.c2r4p2"
omi_name = "ubuntu-2204-hardened-{{timestamp}}"
source_omi_filter {
filters = {
image-name = "Ubuntu-22.04-2024.04*"
root-device-type = "bsu"
virtualization-type = "hvm"
}
owners = ["self"] # ou un AccountId Outscale (par exemple celui du catalogue officiel)
most_recent = true
}
}

Le bloc source_omi_filter accepte :

  • filters (map de strings) — par exemple image-name, root-device-type, virtualization-type.
  • owners (liste) — "self" (votre compte) ou un AccountId (typiquement celui d’un catalogue officiel ou d’une équipe IaC interne).
  • most_recent (booléen) — sélectionne l’OMI la plus récente parmi celles qui matchent.

Block device mappings — root et volumes additionnels

Section intitulée « Block device mappings — root et volumes additionnels »

Deux blocs distincts à ne pas confondre :

  • launch_block_device_mappings — décrit les volumes attachés à la VM de build (par exemple, agrandir le / à 40 GiB pour pouvoir installer la stack pendant le build).
  • omi_block_device_mappings — décrit les volumes qui seront attachés automatiquement à toute VM lancée à partir de l’OMI résultante.

Exemple combiné :

source "outscale-bsu" "ubuntu_2204" {
# ... (region, vm_type, source_omi, omi_name)
launch_block_device_mappings {
delete_on_vm_deletion = true
device_name = "/dev/sda1"
volume_size = 40
volume_type = "gp2"
}
omi_block_device_mappings {
device_name = "/dev/sdb"
volume_size = 100
volume_type = "gp2"
delete_on_vm_deletion = false
}
}

Pour construire dans un Net dédié (par exemple un Net d’isolation des builds) :

source "outscale-bsu" "ubuntu_2204" {
# ...
subnet_id = "subnet-12345678"
net_id = "vpc-12345678" # déductible de subnet_id
security_group_ids = ["sg-12345678"]
associate_public_ip_address = true
}

Si aucun security_group_id / security_group_ids n’est fourni, Packer crée un security group temporaire pour la durée du build et le supprime à la fin. C’est pratique pour les builds isolés mais demande que la zone autorise la création/suppression de SG par le compte EIM utilisé.

Les paramètres SSH classiques s’appliquent :

ParamètreDescription
ssh_usernameUtilisateur SSH (typiquement outscale ou ubuntu selon l’OMI source).
communicator"ssh" (défaut) ou "winrm" pour Windows.
ssh_interfacepublic_ip, private_ip, public_dns, private_dns.
ssh_keypair_nameNom d’un keypair Outscale existant à utiliser (optionnel — sinon Packer crée un keypair temporaire).
ssh_private_key_fileChemin de la clé privée correspondante.
temporary_key_pair_nameNom d’un keypair temporaire à créer pour le build.

Trois ensembles de tags distincts :

source "outscale-bsu" "ubuntu_2204" {
# ...
# Tags appliqués à l'OMI résultante (et aux snapshots associés)
tags = {
Name = "ubuntu-2204-hardened"
env = "build"
project = "platform"
owner = "platform-team"
cost-center = "BU-DSI"
}
# Tags appliqués à la VM de build (transitoire)
run_tags = {
Name = "packer-build-{{timestamp}}"
}
# Tags appliqués aux volumes de la VM de build (transitoires)
run_volume_tags = {
Purpose = "packer-build"
}
}

WAF — Operational Excellence, Cost. Le tagging discipliné de l’OMI est essentiel pour le tri ultérieur (oapi-cli ReadImages --Filters.TagKeys[] env --Filters.TagValues[] build) et pour la chasse aux OMI obsolètes.

Quand un build est rejoué avec le même omi_name (sans {{timestamp}}), il échoue par défaut parce qu’une OMI de ce nom existe déjà. Deux options :

  • Préférer {{timestamp}} dans le nom — chaque build produit une OMI versionnée, les anciennes restent disponibles pour rollback.
  • Sinon activer force_deregister = true et force_delete_snapshot = true pour écraser. À utiliser avec précaution — les anciennes OMI sont supprimées sans possibilité de revenir en arrière.

WAF — Operational Excellence, Security. Le provisionneur applique la configuration sur la VM avant la capture d’OMI. C’est le moment où on installe les paquets, durcit l’OS et ajoute les utilisateurs.

build {
sources = ["source.outscale-bsu.ubuntu_2204"]
provisioner "shell" {
inline = [
"cloud-init status --wait",
"sudo apt-get update -y",
"sudo apt-get upgrade -y",
]
}
}

Le cloud-init status --wait est important sur les OMI cloud-init : il force Packer à attendre que cloud-init ait terminé son travail avant que les commandes shell ne s’exécutent (sinon collision sur les locks apt).

C’est l’approche standard pour des OMI durcies maintenues dans la durée.

build {
sources = ["source.outscale-bsu.ubuntu_2204"]
provisioner "shell" {
inline = ["cloud-init status --wait"]
}
provisioner "ansible" {
playbook_file = "./packer-playbook.yml"
user = "outscale"
extra_arguments = [
"--extra-vars",
"ansible_python_interpreter=/usr/bin/python3"
]
}
}

Exemple de playbook minimal (packer-playbook.yml) :

- name: Build OMI durcie
hosts: default
gather_facts: true
become: true
tasks:
- name: Mise à jour des paquets
ansible.builtin.apt:
update_cache: true
upgrade: dist
cache_valid_time: 3600
- name: Installer outils de base
ansible.builtin.apt:
name:
- locales-all
- unattended-upgrades
- fail2ban
state: present

Pour la construction d’OMI durcies ANSSI BP-028, ajouter les rôles publiés par la communauté ANSSI ou des rôles internes versionnés.

variable "region" {
type = string
default = "eu-west-2"
}
variable "source_omi" {
type = string
description = "OMI source officielle Ubuntu 22.04 (rotation périodique)"
}
variable "vm_type" {
type = string
default = "tinav5.c2r4p2"
}

Alimentation via le shell ou un fichier de variables :

Fenêtre de terminal
# .envrc (couplé à direnv)
export PKR_VAR_source_omi="ami-a3ca408c"
export PKR_VAR_region="eu-west-2"
Fenêtre de terminal
# packer build avec un fichier de variables
packer build -var-file=variables.pkrvars.hcl .
Fenêtre de terminal
# 1. Initialiser le plugin
packer init .
# 2. Valider le code
packer validate .
# 3. Build avec logs détaillés (utile pour le debug)
PACKER_LOG=1 packer build .
# 4. Vérifier l'OMI créée
oapi-cli ReadImages --Filters.ImageNames[] "ubuntu-2204-hardened-*"

WAF — Operational Excellence. Inclure {{timestamp}} dans omi_name produit une OMI versionnée à chaque build, sans collision. Les anciennes versions restent disponibles pour rollback. Le tag version ou build-date complète la traçabilité.

omi_name = "ubuntu-2204-hardened-{{timestamp}}"
tags = {
version = "{{timestamp}}"
base_image = "ubuntu-2204"
}

cloud-init status --wait avant toute provisionneur

Section intitulée « cloud-init status --wait avant toute provisionneur »

WAF — Operational Excellence. Toujours premier provisionneur shell sur une OMI cloud-init pour éviter les collisions de locks et garantir un état stable avant apt.

WAF — Security. Le pipeline Packer s’exécute avec un compte EIM dédié, scopé aux opérations nécessaires : création de VM, création d’OMI, création de snapshot, suppression de VM/keypair temporaires. Pas d’accès large au compte. Cette isolation contient le blast radius en cas de compromission du runner CI.

WAF — Cost, Sustainability. Les OMI s’accumulent. Une politique de rétention typique :

  • Garder les 5 dernières versions d’une famille d’OMI pour rollback.
  • Supprimer les OMI plus anciennes que 90 jours sauf marquées keep=true.
  • Auditer périodiquement via oapi-cli ReadImages --Filters.AccountIds[] $ACCOUNT_ID croisé avec un script de nettoyage.

WAF — Operational Excellence. Packer construit l’image immuable, Terraform la déploie. Le omi_name produit par Packer est consommé par Terraform via un datasource :

data "outscale_images" "ubuntu_hardened" {
filter {
name = "image_names"
values = ["ubuntu-2204-hardened-*"]
}
}
resource "outscale_vm" "app" {
image_id = data.outscale_images.ubuntu_hardened.images[0].image_id
vm_type = "tinav5.c2r4p2"
# ...
}

Pour un comportement strictement reproductible, fixer le nom complet (ubuntu-2204-hardened-1714400000) plutôt qu’un wildcard. Le wildcard est utile pour le développement mais peut introduire des dérives en production.

source_omi hardcodé sans rotation. Référencer ami-a3ca408c directement et ne plus jamais le rafraîchir. Au bout de 6 à 12 mois, l’OMI source contient des CVE non patchées que ni Packer ni Ansible ne reconstruisent. Préférer source_omi_filter avec most_recent = true.

omi_name sans {{timestamp}}. Provoque les collisions ou impose force_deregister = true qui détruit l’historique. Préférer le timestamp pour une trace.

Pas de cloud-init status --wait en premier. Sur une OMI cloud-init standard, lancer apt update directement provoque parfois des erreurs de lock que Packer interprète comme un échec de build. Le wait initial évite la classe d’erreur.

Compte EIM trop privilégié pour Packer. Utiliser un compte EIM admin pour le pipeline OMI. En cas de compromission du runner CI, l’attaquant a accès à tout le compte. Préférer un compte EIM scopé.

Pas de tagging de l’OMI. Ne pas tagguer rend impossible la chasse aux OMI obsolètes et la refacturation par projet. Discipline non négociable.

Mélange OMI build / OMI run dans un même compte sans filtrage. Si le compte applicatif voit toutes les OMI (y compris les builds intermédiaires en échec), le data "outscale_images" peut renvoyer des résultats inattendus. Filtrer strictement par tag ou par préfixe de nom.

  • Plugin github.com/outscale/outscale v1.5.0+, builder principal outscale-bsu.
  • Auth via OUTSCALE_ACCESSKEYID / OUTSCALE_SECRETKEYID — pas de secrets en clair dans le HCL.
  • Required : region, vm_type, source_omi (ou source_omi_filter), omi_name.
  • source_omi_filter avec most_recent = true pour ne pas hardcoder un AMI ID.
  • cloud-init status --wait en premier provisionneur sur les OMI cloud-init.
  • {{timestamp}} dans omi_name pour la versioning et le rollback.
  • Tagging systématique sur tags (OMI + snapshots), run_tags (VM build), run_volume_tags (volumes build).
  • Articulation Packer / Terraform — Packer produit l’OMI durcie, Terraform la consomme via data "outscale_images".

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn