AzureInPlaceUpgrade
Run it against a fleet
One subscription-scope deployment, and the fleet upgrades itself ring by ring on a schedule you control. This is the only mode in which tags matter.
az deployment sub create -l westeurope -f deploy/main.bicep \
-p moduleVersion=0.3.1-preview targetResourceGroupName=rg-apps-prod-weu ring=Ring0 maxParallel=3One deployment creates
- Automation Account with a system-assigned identity and the module imported from the Gallery
- The custom role "Azure VM In-Place Upgrade Operator" — the exact list of actions, nothing more
- The runbook, a Check schedule every 20 minutes and a daily Start schedule that is only linked when you say so
- Log Analytics workspace, the InPlaceUpgrade_CL table, data collection endpoint and rule
- The workbook "In-place upgrades" — every VM, every transition, every failure reason
Tags are the runbook's business, not the module's: it selects VMs by UpgradeTarget and UpgradeState=Pending, passes the target to the module as -Target, and writes the progress back so the next Check job knows where to resume. The runbook itself is a thin wrapper — it signs in with the identity, applies -Ring and -MaxParallel, calls the module per VM and summarises. Details in deploy/README.md.
Under the hood
From preflight to Windows Server 2025
Two short phases, in both modes. Start takes minutes and returns; Check runs every 20 to 30 minutes until the guest reports the target build. Where the progress is kept is the caller's choice — you hold it in a variable, the runbook holds it in tags.
Preflight
Nineteen read-only checks — power state, disk type, edition, installation type, language, free space, pending reboot, domain controller, cluster, activation channel, media availability in the region.
Snapshot
An incremental snapshot of the OS disk. Start returns its name, and it stays until you delete it — this is the rollback point.
Media
Microsoft's hidden upgrade image becomes a managed data disk on LUN 0. No network access needed inside the guest.
Setup
A scheduled task runs setup.exe as SYSTEM with the right
/imageindex, detached from Run Command. The job returns; the VM goes on rebooting on its own.Check
Reads the build number from the guest registry, the task state and the Setup result. Build equals target → Completed. Task failed or timed out → Failed, with the tail of setuperr.log.
Clean up
Removes the media disk and the scheduled task, sends one record per transition to Log Analytics. In fleet mode the runbook also writes the final tag.
CurrentBuildNumber in the registry does not lie.