Simon Vedder

Cloud Engineer · Zürich

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.

Deploy to Azure
Azure CLI
az deployment sub create -l westeurope -f deploy/main.bicep \
  -p moduleVersion=0.3.1-preview targetResourceGroupName=rg-apps-prod-weu ring=Ring0 maxParallel=3

One 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.

  1. 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.

  2. Snapshot

    An incremental snapshot of the OS disk. Start returns its name, and it stays until you delete it — this is the rollback point.

  3. Media

    Microsoft's hidden upgrade image becomes a managed data disk on LUN 0. No network access needed inside the guest.

  4. 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.

  5. 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.

  6. 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.

Setup runs from a scheduled task, not from Run Command. Run Command is capped at 90 minutes and dies with the first reboot. Decision record
Start and Check are separate jobs. Azure Automation cancels cloud jobs after three hours; an upgrade takes 40 minutes on a good day and three hours on a bad one. Decision record
Validation reads the guest, not ARM. The image reference on the VM never changes after an in-place upgrade. CurrentBuildNumber in the registry does not lie.

← Overview·Prerequisites·Commands