AZ-104Chapter 81 of 168Objective 3.1

VM Extensions: Custom Script, DSC, Diagnostics

This chapter covers Azure VM Extensions, focusing on Custom Script Extension (CSE), Desired State Configuration (DSC), and Diagnostics extensions. These are critical tools for post-deployment configuration, automation, and monitoring — topics that appear in approximately 10-15% of AZ-104 exam questions, especially in the 'Manage Azure VMs' objective (3.1). Mastering when to use each extension, how to troubleshoot failures, and the specific differences between them is essential for both the exam and real-world Azure administration. We'll dive deep into each extension's mechanism, configuration syntax, and common pitfalls.

25 min read
Intermediate
Updated May 31, 2026

VM Extensions: The Post-Construction Contractor Crew

Imagine you've just built a new house (provisioned a VM). The structure is solid, but it's empty — no paint, no fixtures, no security system. You can't move in until someone installs those. In Azure, VM Extensions are like specialized contractors you call in after the house is built. Each contractor has a specific job: the electrician (Custom Script Extension) follows your blueprint (script) to wire the house, the interior designer (DSC) ensures every room meets your specifications (desired state), and the HVAC technician (Diagnostics) installs sensors and logs temperature/humidity (performance metrics). These contractors are dispatched by the Azure Resource Manager (the general contractor) via the VM agent (the site manager). The site manager receives instructions, hands them to the right contractor, and reports back on success or failure. Crucially, each contractor works independently — the electrician doesn't care about the paint color. And if you need a change, you send a new work order (update the extension) and the contractor redoes that specific job without touching others. The contractors are temporary; they leave their work behind (installed software, configurations) but don't stay resident. If you want ongoing monitoring, you hire a permanent building superintendent (the Diagnostics extension with Azure Monitor integration). This analogy maps directly: Custom Script Extension runs a script once (like an electrician wiring), DSC enforces a persistent state (like an interior designer ensuring the room stays to spec), and Diagnostics collects and sends telemetry (like sensors reporting to a central dashboard).

How It Actually Works

What Are VM Extensions and Why Do They Exist?

Azure VM Extensions are small applications that provide post-deployment configuration and automation on Azure virtual machines. They are executed by the Azure VM Agent — a process that runs on every Azure VM (Windows or Linux) and acts as a bridge between the Azure fabric and the guest OS. The agent receives extension commands from the Azure Resource Manager (ARM) and executes them locally.

Extensions are not permanent residents; they are installed, run, and then can be removed. However, some extensions (like Diagnostics) remain installed to collect ongoing data. The key purpose is to avoid manual SSH/RDP sessions for common tasks like running scripts, enforcing configuration, or enabling monitoring.

How Extensions Work Internally

When you deploy an extension to a VM, the following sequence occurs:

1.

ARM receives the deployment request — The user (via portal, CLI, or template) specifies the extension type, publisher, version, and settings (JSON).

2.

ARM sends the extension configuration to the VM's metadata service — The VM's host node (part of Azure fabric) receives the configuration and passes it to the VM Agent via a secure channel (not over the network to the guest).

3.

VM Agent processes the extension — The agent (waagent on Linux, WindowsAzureGuestAgent on Windows) checks the extension's type, downloads the required binaries from a Microsoft-managed storage account (or a customer-provided URI for custom scripts), and executes the extension.

4.

Extension executes its logic — For Custom Script Extension, this means downloading and running a script. For DSC, it means applying a configuration MOF file. For Diagnostics, it means installing agents and starting data collection.

5.

Extension reports status — The extension writes status to a local file, which the VM Agent reads and forwards to Azure (via the host) as JSON. This status is visible in the portal and via CLI (az vm extension list).

Custom Script Extension (CSE)

Purpose: Run a script (PowerShell, Bash, or custom) on a VM after deployment. It is ideal for one-time tasks like installing software, joining a domain, or formatting disks.

Key Properties: - Publisher: Microsoft.Compute (for Windows) or Microsoft.Azure.Extensions (for Linux) - Type: CustomScriptExtension (Windows) or CustomScript (Linux) - TypeHandlerVersion: 1.10 (Windows) or 2.1 (Linux) — these are the latest stable versions as of 2025. - Settings: - fileUris: Array of URLs to script files (must be accessible from the VM). - commandToExecute: The command to run (e.g., powershell -ExecutionPolicy Unrestricted -File script.ps1). - timestamp: Optional; forces re-run even if the script hasn't changed (by incrementing the value).

Execution Behavior: - The extension downloads scripts to %SYSTEMROOT%\Temp (Windows) or /var/lib/waagent/custom-script (Linux). - The script runs with SYSTEM (Windows) or root (Linux) privileges. - If the script fails (non-zero exit code), the extension reports Failed status. The VM Agent will not retry automatically — you must re-deploy the extension. - If the script succeeds, the extension reports Succeeded and is considered 'provisioned'. Re-running the same extension with identical settings will not re-execute the script (unless timestamp is changed).

Troubleshooting: - Logs are in C:\WindowsAzure\Logs\Plugins\Microsoft.Compute.CustomScriptExtension (Windows) or /var/log/azure/custom-script (Linux). - Common failures: script timeout (default 90 minutes), network access to fileUris blocked by NSG/firewall, script syntax errors.

Desired State Configuration (DSC) Extension

Purpose: Enforce a desired state on a VM, ensuring configurations remain consistent over time. DSC is a pull-based or push-based configuration management system (similar to PowerShell DSC on-premises).

Key Properties: - Publisher: Microsoft.Powershell - Type: DSC - TypeHandlerVersion: 2.83 (latest for Windows; Linux DSC is separate but less common on exam) - Settings: - modulesUrl: URL to a .zip file containing the DSC module (compiled MOF or script). - configurationFunction: The function to invoke (e.g., MyConfig.ps1\MyConfig). - properties: Optional hashtable of configuration parameters. - wmfVersion: Specify WMF version (e.g., latest). - privacy: dataCollection (for telemetry).

Execution Behavior: - The extension downloads the module .zip, extracts it, and runs the specified configuration function. - DSC applies the configuration and then monitors the state. By default, the Local Configuration Manager (LCM) on the VM will re-apply the configuration every 15 minutes (the RefreshFrequencyMins setting). - If the VM drifts from the desired state (e.g., a service is stopped), DSC will correct it automatically. - The extension reports Succeeded if the initial application succeeds, but ongoing compliance is handled by the LCM.

Key Difference from CSE: DSC is idempotent and continuous — it ensures the state is maintained, not just applied once. CSE is a one-shot execution.

Diagnostics Extension

Purpose: Collect diagnostic data (performance counters, event logs, crash dumps, etc.) from the VM and send it to Azure Storage (or Azure Monitor).

Key Properties: - Windows: Microsoft.Azure.Diagnostics.IaaSDiagnostics (version 1.12) - Linux: Microsoft.OSTCExtensions.LinuxDiagnostic (version 3.0) - Settings: Complex JSON with three main sections: - xmlCfg: Base64-encoded XML (Windows) or JSON (Linux) defining data sources. - StorageAccount: Name of the storage account to send data to. - ladCfg (Linux): Defines performance counters, syslog, etc.

Data Collected: - Performance counters (CPU, memory, disk, network) — sampled every 30 seconds by default. - Event logs (System, Application, Security) — Windows only. - Syslog (Linux). - Crash dumps (Windows). - IIS logs and failed request traces (Windows).

Storage Destinations: - Azure Storage Tables: WADPerformanceCountersTable, WADWindowsEventLogsTable, etc. - Azure Storage Blobs: wad-control-container, wad-iis-logfiles, etc. - Azure Monitor Metrics (via diagnostics settings configured separately).

Troubleshooting: - Verify the storage account exists and the VM has access (via SAS or network connectivity). - Check extension status: az vm extension list --vm-name <vm> --resource-group <rg>. - Common issue: tables not created because the extension is not configured to send data.

Interaction with Related Technologies

Azure VM Agent: All extensions depend on the VM Agent. If the agent is missing or unresponsive, extensions will fail. The agent is automatically installed on Azure Marketplace images but may be missing on custom images.

ARM Templates: Extensions are defined as child resources of Microsoft.Compute/virtualMachines or via Microsoft.Compute/virtualMachines/extensions. They can be deployed inline or via linked templates.

Azure Policy: Can enforce that certain extensions (e.g., Diagnostics) are deployed to all VMs.

Azure Monitor: Diagnostics extension feeds data into Azure Monitor Metrics and Logs for alerting and analysis.

Command Examples

Deploy Custom Script Extension (Windows) via Azure CLI:

az vm extension set \
  --resource-group myRG \
  --vm-name myVM \
  --name CustomScriptExtension \
  --publisher Microsoft.Compute \
  --settings '{"fileUris": ["https://mystorage.blob.core.windows.net/scripts/install.ps1"], "commandToExecute": "powershell -ExecutionPolicy Unrestricted -File install.ps1"}'

Deploy DSC Extension via PowerShell:

$settings = @{
  modulesUrl = "https://mystorage.blob.core.windows.net/dsc/MyConfig.zip"
  configurationFunction = "MyConfig.ps1\\MyConfig"
  properties = @{
    ServerName = "WebServer"
  }
}
Set-AzVMExtension -ResourceGroupName myRG -VMName myVM -Name "DSC" -Publisher Microsoft.Powershell -ExtensionType DSC -TypeHandlerVersion 2.83 -Settings $settings

Deploy Diagnostics Extension (Windows) via portal:

Navigate to VM > Diagnostics settings > Enable guest-level monitoring. This automatically configures the extension with default performance counters and event logs.

Verify extension status:

az vm extension list --vm-name myVM --resource-group myRG -o table

Output shows Name, Publisher, Version, and ProvisioningState (Succeeded/Failed).

Walk-Through

1

Install VM Agent on VM

The VM Agent must be running before any extension can be deployed. On Azure Marketplace images, the agent is pre-installed. For custom images, you must install it manually: Windows requires the WindowsAzureGuestAgent package; Linux requires waagent. The agent runs as a service (WindowsAzureGuestAgent on Windows, waagent on Linux). It listens on a local named pipe (Windows) or Unix socket (Linux) for commands from the Azure Host. Without the agent, extensions will fail with 'VMAgent is not available'.

2

Deploy Extension via ARM

The user triggers deployment via portal, CLI, PowerShell, or ARM template. The request goes to Azure Resource Manager, which validates the extension configuration (publisher, type, version, settings). ARM then sends the configuration to the VM's host node using the Azure control plane. The host node stores the configuration in the VM's metadata service (accessible via 169.254.169.254). The VM Agent polls this metadata service every few seconds for new extension requests.

3

VM Agent Processes Extension

The VM Agent reads the extension configuration from the metadata service. It checks the extension type and downloads the extension package from Azure Storage (or from a customer-provided URI for CSE). The package is extracted to a temporary directory. For CSE, it downloads the script files specified in fileUris. For DSC, it downloads the module .zip. For Diagnostics, it downloads the agent binaries. The agent then executes the extension's handler (a separate process) with the provided settings.

4

Extension Executes Its Logic

The extension handler runs with elevated privileges (SYSTEM on Windows, root on Linux). For CSE: it runs the command specified in commandToExecute. For DSC: it runs the configuration function, which applies the desired state and starts the LCM. For Diagnostics: it installs the diagnostics agent and begins collecting data according to the xmlCfg or ladCfg. The extension writes progress and status to a local file (under %SYSTEMROOT%\Temp or /var/lib/waagent).

5

Extension Reports Status Back

After execution (or on failure), the extension writes a status JSON file to a known location. The VM Agent reads this file and sends the status to the Azure Host via the control plane. The host forwards it to ARM, which updates the extension's provisioning state. You can view this state via portal (Extensions blade) or CLI. If the extension fails, you must troubleshoot using logs on the VM, as the status only shows 'Failed' without detailed error.

What This Looks Like on the Job

Scenario 1: Enterprise Onboarding of Web Servers A company provisions hundreds of Windows Server VMs for a web farm. They need to install IIS, .NET Framework, and join a domain automatically. Using Custom Script Extension in an ARM template, they deploy a PowerShell script that installs IIS via Install-WindowsFeature, configures the default website, and runs Add-Computer to join the domain. The script is stored in Azure Blob Storage with a SAS token for access. At scale, they must ensure the storage account is in the same region to avoid egress costs and latency. A common misconfiguration is forgetting to include the SAS token or placing the script in a private container without proper authentication, causing the extension to fail with 'Access Denied'. They also use the timestamp property to force re-run when the script changes.

Scenario 2: Compliance Enforcement with DSC A financial institution requires all VMs to have specific security settings: Windows Firewall enabled, certain ports blocked, and audit policies configured. They use the DSC extension to apply a baseline configuration. The configuration is compiled into a MOF file and zipped with required modules. The DSC extension ensures that if an administrator accidentally disables the firewall, the LCM will re-enable it within 15 minutes. A pitfall is that the DSC extension does not automatically update when the configuration changes — they must increment the version of the module URL or use a new timestamp to trigger re-application. They also monitor compliance via Azure Automation State Configuration (formerly Azure Automation DSC) for centralized reporting.

Scenario 3: Performance Monitoring for Production VMs A SaaS company needs to monitor CPU, memory, and disk performance across 500 VMs. They enable the Diagnostics extension on each VM with default performance counters (sampled every 30 seconds). The data flows into a storage account where they use Azure Monitor Logs (via diagnostic settings) to create dashboards and alerts. At scale, they must be careful about storage costs — each VM generates ~5 MB of diagnostics data per day. A common issue is that the Diagnostics extension on Linux (LAD) requires a separate storage account for metrics (called 'sinks') and if the storage account key is not provided correctly, data collection silently fails. They also enable boot diagnostics separately for crash analysis.

How AZ-104 Actually Tests This

What AZ-104 Tests on This Topic The exam objectives under 'Manage Azure VMs' (3.1) include: 'Configure VM extensions' and 'Implement VM backup, restore, and monitoring'. Specific questions test:

Choosing between Custom Script Extension and DSC for a given scenario.

Understanding that CSE runs once, DSC runs continuously.

Knowing the default refresh interval for DSC LCM (15 minutes).

Recognizing that extensions require the VM Agent to be running.

Interpreting extension provisioning states (Succeeded, Failed).

Configuring Diagnostics extension to send data to Azure Monitor or Storage.

Troubleshooting extension failures by checking logs on the VM.

Common Wrong Answers and Why 1. 'Use Custom Script Extension to enforce a configuration that must persist.' — Wrong because CSE only runs once; if the state drifts, it won't correct it. DSC is the correct choice. 2. 'Diagnostics extension automatically sends data to Azure Monitor Metrics.' — Wrong; by default it sends to Azure Storage tables. You must configure a diagnostic setting to send to Azure Monitor. 3. 'Extensions can be deployed to a VM even if the VM Agent is not installed.' — Wrong; the VM Agent is a prerequisite. 4. 'DSC extension runs the configuration once and then uninstalls.' — Wrong; DSC leaves the LCM running to enforce state.

Specific Numbers and Terms - CSE default timeout: 90 minutes. - DSC LCM refresh frequency: 15 minutes. - Diagnostics performance counter sampling: every 30 seconds. - Extension type names: CustomScriptExtension, DSC, IaaSDiagnostics. - Publisher names: Microsoft.Compute, Microsoft.Powershell, Microsoft.Azure.Diagnostics. - Provisioning states: Creating, Updating, Succeeded, Failed.

Edge Cases the Exam Loves - Re-running CSE: If you deploy the same extension with identical settings, it will NOT re-run the script unless you change the timestamp property. - Linux CSE: The publisher is Microsoft.Azure.Extensions, not Microsoft.Compute. - DSC on Linux: The exam rarely tests DSC on Linux, but know it exists as Microsoft.OSTCExtensions.DSCForLinux. - Diagnostics storage: The storage account must be in the same region as the VM? No, it can be different, but latency and cost considerations apply.

How to Eliminate Wrong Answers - If the question says 'ensure the configuration is maintained even if someone changes it', choose DSC, not CSE. - If the question says 'run a PowerShell script once after deployment', choose CSE. - If the question mentions 'performance counters', 'event logs', or 'diagnostics', choose the Diagnostics extension. - If the question mentions 'VM Agent missing', any extension deployment will fail.

Key Takeaways

Custom Script Extension runs a script once; use for one-time post-deployment tasks.

DSC extension enforces a desired state continuously; use for ongoing configuration compliance.

Diagnostics extension collects performance counters, event logs, and crash dumps to Azure Storage by default.

All extensions require the Azure VM Agent to be installed and running on the VM.

CSE script timeout is 90 minutes; DSC LCM refresh frequency is 15 minutes.

To re-run CSE with the same script, change the 'timestamp' property in settings.

Diagnostics extension on Windows uses publisher 'Microsoft.Azure.Diagnostics'; on Linux 'Microsoft.OSTCExtensions.LinuxDiagnostic'.

Extension provisioning states: Creating, Updating, Succeeded, Failed.

For custom images, manually install the VM Agent or include it in the image.

Use 'az vm extension list' to verify extension status and troubleshoot failures.

Easy to Mix Up

These come up on the exam all the time. Here's how to tell them apart.

Custom Script Extension

Runs a script once (one-shot execution).

No ongoing monitoring; state can drift.

Ideal for initial setup, software installation, or one-time tasks.

Script runs with SYSTEM/root privileges.

Re-run only if settings change (or timestamp updated).

Desired State Configuration Extension

Applies and maintains a desired state continuously.

LCM monitors and corrects drift every 15 minutes by default.

Ideal for configuration enforcement, compliance, and security baselines.

Configuration function runs with SYSTEM/root privileges; LCM runs as a service.

Re-applies automatically on drift; configuration updates require new module URL or timestamp.

Watch Out for These

Mistake

Custom Script Extension re-runs the script every time the VM restarts.

Correct

CSE runs only once after deployment (or when the extension is updated). It does not run on VM reboot. To run on startup, use a startup script or task scheduler.

Mistake

DSC extension is the same as Custom Script Extension but for PowerShell.

Correct

DSC is fundamentally different: it enforces a desired state continuously, while CSE runs a script once. DSC uses the Local Configuration Manager to monitor and correct drift.

Mistake

The Diagnostics extension sends data directly to Azure Monitor by default.

Correct

By default, the Diagnostics extension sends data to Azure Storage tables. To send to Azure Monitor, you must configure a diagnostic setting on the VM or use a separate Azure Monitor agent.

Mistake

Extensions are automatically removed after successful execution.

Correct

Extensions remain installed on the VM. You must explicitly uninstall them if you no longer need them. They do not consume significant resources but can be removed via CLI or portal.

Mistake

The VM Agent is automatically installed on all Azure VMs, including custom images.

Correct

The VM Agent is pre-installed only on Azure Marketplace images. For custom images (generalized or specialized), you must install the agent manually or ensure it is included in the image creation process.

Do You Actually Know This?

Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.

Frequently Asked Questions

Can I use Custom Script Extension to run a script on every boot?

No. Custom Script Extension runs only once after deployment. To run a script on every boot, you should configure a startup script (e.g., via Task Scheduler on Windows or systemd on Linux) or use a tool like cloud-init (Linux). CSE is not designed for recurring tasks.

How do I re-run a Custom Script Extension if the script hasn't changed?

Add a 'timestamp' property to the settings with a new value (e.g., the current Unix epoch). This forces the extension to re-execute even if the script content is identical. Without changing timestamp, the extension sees the same settings and skips execution.

What happens if the DSC extension fails to apply the configuration?

The extension reports a provisioning state of 'Failed'. The LCM will not start, and the desired state is not enforced. You must troubleshoot by checking the DSC logs on the VM (usually in %SystemRoot%\System32\Configuration or /var/lib/waagent/dsc). Common causes: invalid MOF, missing modules, or network issues downloading the module zip.

Does the Diagnostics extension support sending data to Azure Monitor?

By default, the Diagnostics extension sends data to Azure Storage (tables and blobs). To send to Azure Monitor, you must configure a diagnostic setting on the VM (under 'Monitoring' > 'Diagnostic settings') that routes the data to a Log Analytics workspace. Alternatively, use the Azure Monitor agent (AMA) for modern monitoring.

Can I deploy an extension to a VM that is stopped (deallocated)?

Yes. Extensions can be deployed to a stopped VM. The extension configuration is stored and will be applied when the VM starts. However, the extension will not run until the VM is started and the VM Agent is running.

What is the difference between 'Succeeded' and 'Provisioning succeeded'?

In the context of extensions, 'Provisioning succeeded' (or 'Succeeded' in CLI) means the extension was successfully installed and executed. For CSE, it means the script exited with code 0. For DSC, it means the initial configuration applied. For Diagnostics, it means the agent started. If the script fails, the state is 'Failed'.

How do I remove an extension from a VM?

Use the Azure CLI: 'az vm extension delete --resource-group <rg> --vm-name <vm> --name <extension-name>'. Or in the portal, go to VM > Extensions > select extension > Uninstall. Removing an extension does not undo its actions (e.g., installed software remains).

Terms Worth Knowing

Ready to put this to the test?

You've just covered VM Extensions: Custom Script, DSC, Diagnostics — now see how well it sticks with free AZ-104 practice questions. Full explanations included, no account needed.

Done with this chapter?