Automation
Azure Automation : valider une migration de runtime avant de basculer les runbooks de production
Un runbook de production pour qualifier un nouvel environnement d'exécution Azure Automation avec versions, packages, Hybrid Workers, tests sans effet, canari, validation et rollback.
Un runbook Azure Automation fonctionne encore sous son environnement historique, mais l’équipe doit changer de version PowerShell ou mettre à jour le package Az. Le test manuel passe, puis le premier job de production échoue sur un module absent, un type sérialisé différemment ou une commande non disponible sur un Hybrid Runbook Worker. Revenir au code précédent ne suffit pas : le code n’a pas changé, c’est son environnement d’exécution qui a dérivé.
Le cas fil rouge est un runbook reconcile-private-dns-records exécuté chaque nuit. Il lit un inventaire, calcule un diff et met à jour uniquement les enregistrements approuvés. L’équipe veut le faire passer vers un environnement PowerShell récent sans transformer la migration en test grandeur nature. L’objectif est de construire un candidat immuable, de le tester avec les mêmes entrées et identités, de limiter le premier effet réel, puis de décider promotion, maintien ou rollback.
Traiter le runtime comme une dépendance versionnée
Un environnement d’exécution Azure Automation regroupe le langage, sa version et les packages requis par le runbook. Le changer peut modifier l’authentification, la résolution des modules, la sérialisation JSON, le comportement des exceptions et les commandes disponibles. Le contrat de migration doit donc décrire davantage que « PowerShell mis à jour ».
runbook: reconcile-private-dns-records
current_runtime: ps-old-approved
candidate_runtime: ps-candidate-2026-09
execution_targets:
- azure_sandbox
- hybrid_worker_group: hwg-network-prod
packages_to_freeze:
- Az
- Az.Accounts
- Az.PrivateDns
identity: aa-network-prod-managed-identity
inputs_fixture: fixtures/private-dns-small.json
allowed_canary_scope: privatelink.example.internal
success_signal: expected_diff_applied_and_second_run_empty
rollback: relink_runbook_to_ps-old-approved Créez un environnement candidat au lieu de modifier celui qui porte déjà plusieurs runbooks. La version du langage est immuable, mais une mise à jour de packages sur un environnement partagé se propage à tous les runbooks qui lui sont liés. Un candidat séparé rend le diff, le canari et le retour arrière lisibles.
Inventorier les consommateurs avant le changement
Avant de toucher au lien du runbook, listez les environnements et les runbooks concernés. L’unité de risque n’est pas seulement le script : c’est l’ensemble des consommateurs d’un environnement partagé.
SUBSCRIPTION="<subscription-id>"
RG="rg-automation-prod"
ACCOUNT="aa-network-prod"
API="2024-10-23"
BASE="https://management.azure.com/subscriptions/$SUBSCRIPTION/resourceGroups/$RG/providers/Microsoft.Automation/automationAccounts/$ACCOUNT"
az rest --method get --url "$BASE/runtimeEnvironments?api-version=$API" --query "value[].{name:name, runtime:properties.runtime, defaultPackages:properties.defaultPackages}" --output json
az rest --method get --url "$BASE/runbooks?api-version=$API" --query "value[].{name:name, state:properties.state, type:properties.runbookType, runtime:properties.runtimeEnvironment, modified:properties.lastModifiedTime}" --output table Conservez le nom exact de l’environnement actuel, les versions de packages et la liste des runbooks liés. Si le candidat est modifié pendant les tests, changez son nom ou sa version de manifeste : un résultat obtenu contre une cible mouvante n’est pas une preuve de promotion.
Construire une matrice de compatibilité utile
Le test doit couvrir les branches qui dépendent réellement du runtime. Un simple Get-Date vert ne valide ni l’identité ni les effets du runbook.
Surface Preuve attendue
Langage Version exacte et edition de PowerShell
Packages Nom, version et etat de provisioning
Imports Chaque module requis se charge sans fallback implicite
Authentification Principal, tenant et abonnement attendus
Lecture Azure Inventaire retourne avec le meme scope
Serialisation Fixture d'entree et diff normalise identiques
Gestion d'erreur Refus attendu conserve code et message exploitables
Hybrid Worker Binaire runtime present sur chaque worker cible
Effet canari Une seule cible bornee, puis second run sans changement
Observabilite Job ID, runtime, worker, correlation et resultat conserves Ajoutez des tests négatifs : ressource hors scope, package volontairement absent dans un environnement de test, identité sans droit d’écriture et entrée invalide. Une migration est sûre quand le candidat réussit les actions autorisées et continue de refuser celles qui ne le sont pas.
Tester le candidat sans rebascule
Azure Automation permet de lancer le brouillon avec un environnement d’exécution différent avant de modifier le lien publié. Utilisez une fixture sans effet ou un mode WhatIf réellement implémenté par le runbook.
SUBSCRIPTION="<subscription-id>"
RG="rg-automation-prod"
ACCOUNT="aa-network-prod"
RUNBOOK="reconcile-private-dns-records"
CANDIDATE="ps-candidate-2026-09"
API="2024-10-23"
TEST_URL="https://management.azure.com/subscriptions/$SUBSCRIPTION/resourceGroups/$RG/providers/Microsoft.Automation/automationAccounts/$ACCOUNT/runbooks/$RUNBOOK/draft/testJob?api-version=$API"
az rest --method put --url "$TEST_URL" --headers "Content-Type=application/json" --body "{"properties":{"runtimeEnvironment":"$CANDIDATE","runOn":""}}" Le Test pane ne doit pas devenir un contournement des contrôles de production. Utilisez une identité et des entrées bornées, capturez les streams, et ne placez aucun secret dans la sortie. Pour un runbook qui ne sait pas simuler ses écritures, créez d’abord une cible canari isolée.
Qualifier chaque Hybrid Worker
Un même environnement logique ne garantit pas que tous les workers possèdent le bon exécutable ou les mêmes dépendances locales. Pour PowerShell 7.4 sur Hybrid Worker, le binaire doit être installé et son chemin déclaré sur la machine. Vérifiez chaque membre du groupe avant d’autoriser la distribution du job.
$expectedMajor = 7
$expectedMinor = 4
$runtimePath = [Environment]::GetEnvironmentVariable(
'powershell_7_4_path',
'Machine'
)
[pscustomobject]@{
ComputerName = $env:COMPUTERNAME
RuntimePath = $runtimePath
PathExists = Test-Path $runtimePath
CurrentVersion = $PSVersionTable.PSVersion.ToString()
Compatible = (
$PSVersionTable.PSVersion.Major -eq $expectedMajor -and
$PSVersionTable.PSVersion.Minor -eq $expectedMinor
)
} | ConvertTo-Json -Compress
Get-Module -ListAvailable Az.Accounts, Az.PrivateDns |
Select-Object Name, Version, Path |
ConvertTo-Json -Compress Exécutez ce contrôle comme un job sans effet sur chaque worker ciblé. Si un worker diverge, retirez-le du groupe ou corrigez-le avant le canari. Ne comptez pas sur l’ordonnanceur pour choisir spontanément la bonne machine.
Comparer des sorties normalisées
Les deux runtimes peuvent produire des objets techniquement différents tout en représentant le même état. Comparez une sortie normalisée : identifiants, propriétés métier triées, diff proposé et codes d’erreur. Ignorez les timestamps de job et l’ordre non contractuel des propriétés.
{
"fixture": "private-dns-small-v3",
"oldRuntime": {
"readCount": 12,
"proposedChanges": 1,
"deniedOutOfScope": true
},
"candidateRuntime": {
"readCount": 12,
"proposedChanges": 1,
"deniedOutOfScope": true
},
"normalizedDiff": [],
"decision": "eligible_for_bounded_canary"
} Tout écart doit être expliqué avant la promotion. Une propriété absente peut révéler un changement de module ; un nouvel ordre de résultats peut casser une logique non déterministe ; un message d’erreur différent peut rendre une alerte ou un parseur inopérant.
Basculer un seul runbook et limiter le premier effet
Quand les tests sans effet sont verts, reliez uniquement le runbook canari au candidat. Une exécution déjà en cours n’est pas modifiée par la nouvelle association ; la validation porte sur les jobs lancés après la bascule.
SUBSCRIPTION="<subscription-id>"
RG="rg-automation-prod"
ACCOUNT="aa-network-prod"
RUNBOOK="reconcile-private-dns-records"
CANDIDATE="ps-candidate-2026-09"
API="2024-10-23"
RUNBOOK_URL="https://management.azure.com/subscriptions/$SUBSCRIPTION/resourceGroups/$RG/providers/Microsoft.Automation/automationAccounts/$ACCOUNT/runbooks/$RUNBOOK?api-version=$API"
az rest --method patch --url "$RUNBOOK_URL" --headers "Content-Type=application/json" --body "{"properties":{"type":"PowerShell","runtimeEnvironment":"$CANDIDATE"}}" Le premier job réel doit utiliser un scope réduit, une clé d’idempotence et une validation métier. Pour le cas DNS, limitez la cible à une zone et un record contrôlés. Exécutez ensuite le même job une seconde fois : l’absence de nouveau diff prouve davantage que le seul statut Completed.
Tracer le runtime réellement exécuté
Ajoutez au début du runbook une enveloppe de preuve qui ne contient ni token ni secret. Elle doit permettre de relier la décision de migration au job observé.
$evidence = [ordered]@{
correlationId = [guid]::NewGuid().ToString()
runbook = 'reconcile-private-dns-records'
runtime = $PSVersionTable.PSVersion.ToString()
edition = $PSVersionTable.PSEdition
worker = $env:COMPUTERNAME
azAccounts = (Get-Module -ListAvailable Az.Accounts |
Sort-Object Version -Descending |
Select-Object -First 1 -ExpandProperty Version).ToString()
startedAtUtc = [DateTime]::UtcNow.ToString('o')
}
Write-Output ($evidence | ConvertTo-Json -Compress) Corrélez cette enveloppe avec le Job ID, l’identité visible dans Azure Activity et le signal applicatif. Un job vert sous un runtime inconnu ou exécuté sur un worker non identifié ne clôt pas la migration.
Décider promotion, maintien ou rollback
Promouvoir progressivement
Runtime et packages du candidat sont figes
Tests positifs et negatifs sont conformes
Chaque Hybrid Worker cible est qualifie
Le canari applique uniquement le diff attendu
Le second run est sans effet
Traces techniques et validation metier concordent
Maintenir le runtime actuel
Le candidat fonctionne mais un package reste non maitrise
Les sorties different sans explication
Un worker du groupe n'est pas qualifie
Le test ne couvre pas une branche avec effet externe
Rollbacker immediatement
Identite, scope ou refus attendus ont change
Le canari touche une cible hors contrat
Une dependance locale manque sur un worker
Les traces ne permettent pas d'attribuer l'effet
Le second run reproduit une ecriture Le rollback consiste à relier le runbook à l’environnement précédent, puis à lancer un contrôle de lecture et à traiter séparément tout effet déjà appliqué. Ne supprimez pas immédiatement le candidat : conservez son manifeste et ses sorties pour expliquer l’échec. La suppression d’un environnement d’exécution n’est pas un mécanisme de retour arrière.
Conclusion
Une migration de runtime Azure Automation est une release de production, même lorsque le script reste identique. Le périmètre utile est le triplet code, environnement et cible d’exécution, complété par l’identité et le signal métier.
La décision devient alors simple à défendre : promouvoir si le candidat est figé, testé sur les refus comme sur les succès, qualifié sur chaque worker et validé par un canari idempotent ; maintenir si une preuve manque ; relier immédiatement l’ancien environnement si le scope, l’identité ou l’effet dérive. Le runtime redevient ainsi une dépendance exploitable au lieu d’un contexte implicite découvert pendant l’incident.