Pipeline CI/CD avec Packer¶
Intégrer Packer dans un pipeline CI/CD garantit que chaque image est construite, testée et publiee de manière reproductible sans intervention manuelle.
Principe du pipeline¶
Chaque étape dépend du succès de la précédente. En cas d'échec, le pipeline s'arrêté et aucun artefact n'est publie.
GitHub Actions¶
Exemple de workflow avec deux jobs : validation du template puis build et push.
# .github/workflows/packer.yml
name: Packer Build
on:
push:
branches: [main]
paths:
- "packer/**"
pull_request:
paths:
- "packer/**"
env:
PACKER_VERSION: "1.10.0"
jobs:
validate:
name: Validate template
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Packer
uses: hashicorp/setup-packer@main
with:
version: ${{ env.PACKER_VERSION }}
- name: Init plugins
run: packer init packer/
- name: Format check
run: packer fmt -check packer/
- name: Validate
run: packer validate packer/
env:
PKR_VAR_project_id: ${{ vars.GCP_PROJECT_ID }}
build:
name: Build image
needs: validate
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Authenticate to GCP
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}
- name: Setup Packer
uses: hashicorp/setup-packer@main
with:
version: ${{ env.PACKER_VERSION }}
- name: Init plugins
run: packer init packer/
- name: Build
run: packer build packer/
env:
PKR_VAR_project_id: ${{ vars.GCP_PROJECT_ID }}
PKR_VAR_region: ${{ vars.GCP_REGION }}
- name: Upload manifest
uses: actions/upload-artifact@v4
with:
name: packer-manifest
path: packer/manifest.json
Le job build ne s'exécuté que sur la branche main pour éviter de consommer des ressources cloud sur chaque pull request.
GitLab CI¶
Exemple équivalent pour GitLab CI avec deux stages.
# .gitlab-ci.yml
variables:
PACKER_VERSION: "1.10.0"
PACKER_DIR: "packer"
stages:
- validate
- build
.packer-base:
image: hashicorp/packer:${PACKER_VERSION}
before_script:
- packer init ${PACKER_DIR}/
validate:
extends: .packer-base
stage: validate
script:
- packer fmt -check ${PACKER_DIR}/
- packer validate ${PACKER_DIR}/
variables:
PKR_VAR_project_id: ${GCP_PROJECT_ID}
build:
extends: .packer-base
stage: build
script:
- packer build ${PACKER_DIR}/
variables:
PKR_VAR_project_id: ${GCP_PROJECT_ID}
PKR_VAR_region: ${GCP_REGION}
artifacts:
paths:
- packer/manifest.json
expire_in: 7 days
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Les variables GCP_PROJECT_ID et GCP_REGION sont définies dans Settings > CI/CD > Variables de GitLab. Les secrets (compte de service) sont marques comme proteges et masques.
GCP Cloud Build¶
Cloud Build est le service CI/CD natif de GCP. Il s'intégré nativement avec les comptes de service et les rôles IAM.
# cloudbuild.yaml
steps:
- name: "hashicorp/packer:1.10.0"
id: packer-init
args: ["init", "packer/"]
- name: "hashicorp/packer:1.10.0"
id: packer-validate
args: ["validate", "packer/"]
env:
- "PKR_VAR_project_id=$PROJECT_ID"
- name: "hashicorp/packer:1.10.0"
id: packer-build
args: ["build", "packer/"]
env:
- "PKR_VAR_project_id=$PROJECT_ID"
- "PKR_VAR_region=europe-west1"
artifacts:
objects:
location: "gs://${_ARTIFACTS_BUCKET}/packer/"
paths:
- "packer/manifest.json"
Le compte de service Cloud Build doit avoir les rôles roles/compute.instanceAdmin.v1 et roles/iam.serviceAccountUser pour créer des instances et capturer des images.
Pour la configuration complète de Cloud Build avec GCP, voir la page DevOps GCP.
Bonnes pratiques¶
Variables d'environnement PKR_VAR_¶
Toutes les variables Packer peuvent être passees via des variables d'environnement prefixees PKR_VAR_. Cela evite de passer des valeurs sensibles en clair dans les commandes.
export PKR_VAR_project_id="mon-projet"
export PKR_VAR_sa_key_path="/run/secrets/sa.json"
packer build packer/
Post-processor manifest¶
Activer le post-processor manifest pour tracer les artefacts produits par chaque build. Le fichier JSON peut être archivé comme artefact CI ou pousse dans un bucket.
build {
sources = ["source.googlecompute.base"]
# ... provisioners ...
post-processor "manifest" {
output = "manifest.json"
strip_path = true
custom_data = {
git_commit = "${env("CI_COMMIT_SHA")}"
pipeline = "${env("CI_PIPELINE_ID")}"
}
}
}
Builds parallèles¶
Packer peut construire plusieurs sources en parallèle dans un même bloc build. Cela réduit significativement la durée totale pour des images multi-regions ou multi-providers.
build {
sources = [
"source.googlecompute.europe",
"source.googlecompute.us",
"source.amazon-ebs.eu-west",
]
provisioner "shell" {
script = "scripts/base.sh"
}
}
Les trois images sont construites simultanément. Les provisioners s'appliquent à chaque source independamment.