diff --git a/Scenarios/How to onboard VMs to VM Insights V2/README.md b/Scenarios/How to onboard VMs to VM Insights V2/README.md new file mode 100644 index 00000000..b1a8c653 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/README.md @@ -0,0 +1,348 @@ +# VM Insights V2 Onboarding Templates + +ARM and Bicep templates for onboarding Azure Virtual Machines to **VM Insights V2**. A single parameterized template handles all combinations of resource provisioning, metrics tiers, and alert rules. + +## Glossary + +| Term | Meaning | +|------|---------| +| **AMW** | Azure Monitor Workspace. Stores OTel (OpenTelemetry) metrics from the VM | +| **LA** | Log Analytics workspace. Stores `InsightsMetrics` for per-process/detailed metrics | +| **DCR** | Data Collection Rule. Defines which metrics to collect and where to send them | +| **DCRA** | Data Collection Rule Association. Links a DCR to a specific VM | +| **AMA** | Azure Monitor Agent. The VM extension that collects and ships metrics | +| **OTel** | OpenTelemetry. The metrics format used by VM Insights V2 | +| **UAMI** | User-Assigned Managed Identity. Required for PromQL-based guest OS alerts | +| **PromQL** | Prometheus Query Language. Used by guest OS alert rules to query OTel metrics | + +## What This Does + +These templates onboard an **existing** VM to VM Insights V2 by: + +1. Enabling a managed identity on the VM (required by AMA) +2. Optionally creating an Azure Monitor Workspace (AMW) and/or Log Analytics workspace +3. Creating (or reusing) a Data Collection Rule (DCR) for VM Insights metrics +4. Associating the DCR with the VM +5. Installing the Azure Monitor Agent (AMA) extension on the VM +6. Optionally creating recommended alert rules + +### What this does NOT do + +- Create the VM itself, which must already exist +- Create resource groups. All referenced resource groups must already exist +- Create a User-Assigned Managed Identity (UAMI). Create it beforehand if using alerts +- Assign RBAC roles to the UAMI. You must grant Monitoring Reader on the AMW +- Create or attach action groups. Alert rules are created but do not send notifications by default (see [Alert Rules](#alert-rules-when-enabled)) +- Onboard VMSS or Azure Arc-connected machines (VM-only) + +### Cost implications + +- **Standard tier** sends OTel metrics to Azure Monitor Workspace at no additional charge beyond the AMW. +- **Per-process tier** adds more OTel counters and sends `DetailedMetrics` to Log Analytics, which incurs Log Analytics ingestion and retention charges. Review [Azure Monitor pricing](https://azure.microsoft.com/pricing/details/monitor/) before enabling. + +## Choose Your Scenario + +| Scenario | Metrics | Resources created | Parameter file | +|----------|---------|-------------------|----------------| +| **Standard, new everything** | Free | AMW + DCR | `standard-new-amw-new-dcr` | +| **Standard, existing AMW** | Free | DCR only | `standard-existing-amw-new-dcr` | +| **Reuse existing DCR** | Free | DCRA + AMA only (fastest) | `existing-dcr` | +| **Standard + alerts** | Free | AMW + DCR + 8 alert rules | `standard-new-amw-with-alerts` | +| **Per-process, new everything + alerts** | Paid | AMW + LA + DCR + 8 alert rules | `per-process-new-all-with-alerts` | +| **Per-process, existing infra** | Paid | DCR only (reuses AMW + LA) | `per-process-existing-amw-existing-la` | + +## Prerequisites + +- **Azure subscription** with Contributor role (or equivalent) to create resources +- **Azure CLI** v2.20+ ([install guide](https://learn.microsoft.com/cli/azure/install-azure-cli)), which includes Bicep support +- **An existing VM** to onboard +- **All referenced resource groups** must already exist (the template does not create them) +- If enabling alerts: + 1. Create a [User-Assigned Managed Identity](https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities): + ```bash + az identity create --name --resource-group --location + ``` + 2. Grant it **Monitoring Reader** on the Azure Monitor Workspace: + ```bash + # Get the UAMI principal ID + UAMI_PRINCIPAL_ID=$(az identity show --name --resource-group --query principalId -o tsv) + + # Assign Monitoring Reader on the AMW + az role assignment create \ + --assignee-object-id $UAMI_PRINCIPAL_ID \ + --assignee-principal-type ServicePrincipal \ + --role "Monitoring Reader" \ + --scope + ``` + +## Deploy + +### Step 1: Fill in parameters + +Copy the parameter file for your scenario and replace all `` values: + +```jsonc +// Example: parameters/standard-new-amw-new-dcr.parameters.json +{ + "parameters": { + "vmName": { "value": "my-vm" }, + "vmResourceGroup": { "value": "my-rg" }, + "vmSubscriptionId": { "value": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }, + "location": { "value": "eastus2" }, + "osType": { "value": "Linux" }, + "createNewAmw": { "value": true }, + "amwName": { "value": "my-amw" }, + "createNewDcr": { "value": true } + } +} +``` + +### Step 2: Run the deployment + +#### ARM template (Azure CLI) + +```bash +az deployment group create \ + --resource-group \ + --template-file vmi-v2-onboard.json \ + --parameters @parameters/standard-new-amw-new-dcr.parameters.json +``` + +> **Why `az deployment group create`?** The ARM JSON template is deployed at resource-group scope. It uses nested `Microsoft.Resources/deployments` with explicit `subscriptionId` and `resourceGroup` on each resource to place them in the correct resource groups (VM RG, AMW RG, DCR RG, etc.). The `--resource-group` value is simply the parent deployment's home resource group. Use the VM resource group. + +#### ARM template (PowerShell) + +```powershell +New-AzResourceGroupDeployment ` + -ResourceGroupName ` + -TemplateFile vmi-v2-onboard.json ` + -TemplateParameterFile parameters\standard-new-amw-new-dcr.parameters.json +``` + +#### Bicep + +```bash +az deployment sub create \ + --location \ + --template-file bicep/main.bicep \ + --parameters bicep/parameters/standard-new-amw-new-dcr.bicepparam +``` + +> **Why `az deployment sub create`?** The Bicep template uses `targetScope = 'subscription'` because its modules deploy into potentially different resource groups. This requires a subscription-level deployment. + +#### Inline parameters (no parameter file) + +```bash +az deployment group create \ + --resource-group my-rg \ + --template-file vmi-v2-onboard.json \ + --parameters vmName=my-vm vmResourceGroup=my-rg \ + vmSubscriptionId=$(az account show --query id -o tsv) \ + location=eastus2 osType=Linux \ + createNewAmw=true amwName=my-amw \ + createNewDcr=true +``` + +> **ARM and Bicep deploy the same resources.** The only operational difference is deployment scope: ARM JSON is orchestrated from a resource-group deployment using nested deployments, while Bicep is authored at subscription scope because its modules target multiple resource groups. + +### Step 3: Verify + +After deployment, confirm onboarding succeeded: + +```bash +# Check AMA extension is installed (use AzureMonitorWindowsAgent for Windows VMs) +az vm extension show \ + --resource-group --vm-name \ + --name AzureMonitorLinuxAgent \ + --query "{name:name, status:provisioningState}" -o table + +# Check the DCR association exists +az monitor data-collection rule association list \ + --resource "/subscriptions//resourceGroups//providers/Microsoft.Compute/virtualMachines/" \ + --query "[].{name:name, ruleId:dataCollectionRuleId}" -o table +``` + +In the Azure portal: +- **VM > Extensions**: AMA extension should show "Provisioning succeeded" +- **VM > Monitoring > Data collection rules**: DCR association should appear +- **Azure Monitor > Metrics** (AMW): OTel metrics should appear within ~5 minutes +- If per-process: **Log Analytics workspace > Logs**: query `InsightsMetrics | take 10` +- If alerts: **Monitor > Alerts > Alert rules**: 8 alert rules should be listed + +## Common Scenarios + +### Onboard multiple VMs to the same DCR + +Deploy the first VM with a new DCR, then reuse it for additional VMs: + +```bash +# First VM, creates AMW + DCR +az deployment group create --resource-group my-rg \ + --template-file vmi-v2-onboard.json \ + --parameters @parameters/standard-new-amw-new-dcr.parameters.json + +# Subsequent VMs, reuse the existing DCR +az deployment group create --resource-group my-rg \ + --template-file vmi-v2-onboard.json \ + --parameters vmName=vm-2 vmResourceGroup=my-rg \ + vmSubscriptionId=xxxx location=eastus2 osType=Linux \ + createNewAmw=false createNewDcr=false \ + existingDcrId="/subscriptions//resourceGroups//providers/Microsoft.Insights/dataCollectionRules/msvmi-eastus2-vm-1" +``` + +### Onboard a Windows VM with per-process metrics and alerts + +```bash +az deployment group create --resource-group my-rg \ + --template-file vmi-v2-onboard.json \ + --parameters vmName=my-windows-vm vmResourceGroup=my-rg \ + vmSubscriptionId=xxxx location=eastus2 osType=Windows \ + createNewAmw=true amwName=my-amw \ + createNewLogAnalyticsWorkspace=true logAnalyticsWorkspaceName=my-la \ + createNewDcr=true enablePerProcessMetrics=true \ + enableAlerts=true \ + uamiResourceId="/subscriptions//resourceGroups//providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-uami" +``` + +## Parameter Reference + +### Required (always) + +| Parameter | Type | Description | +|-----------|------|-------------| +| `vmName` | string | Name of the existing VM to onboard | +| `vmResourceGroup` | string | Resource group containing the VM | +| `vmSubscriptionId` | string | Subscription ID of the VM | +| `location` | string | Azure region, must match the VM (e.g. `eastus2`) | + +### VM & Identity + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `osType` | string | `Linux` | `Windows` or `Linux`, determines the AMA extension type | +| `enableSystemAssignedIdentity` | bool | `true` | Enable system-assigned managed identity (required by AMA) | +| `identityType` | string | `SystemAssigned` | Use `SystemAssigned, UserAssigned` if the VM already has user-assigned identities | + +> ⚠️ **Warning:** Setting `identityType=SystemAssigned` on a VM that already uses user-assigned identities may disrupt existing identity configuration. Use `SystemAssigned, UserAssigned` to preserve existing UAMIs. + +### Azure Monitor Workspace + +| Parameter | Type | Default | Required when | +|-----------|------|---------|---------------| +| `createNewAmw` | bool | `false` | n/a | +| `amwName` | string | `""` | `createNewAmw=true` | +| `amwResourceGroup` | string | VM RG | `createNewAmw=true` (optional, defaults to VM RG) | +| `existingAmwResourceId` | string | `""` | `createNewAmw=false` AND `createNewDcr=true` | + +### Log Analytics Workspace + +Only relevant when `enablePerProcessMetrics=true`. + +| Parameter | Type | Default | Required when | +|-----------|------|---------|---------------| +| `createNewLogAnalyticsWorkspace` | bool | `false` | n/a | +| `logAnalyticsWorkspaceName` | string | `""` | `enablePerProcessMetrics=true` AND `createNewLogAnalyticsWorkspace=true` | +| `logAnalyticsResourceGroup` | string | VM RG | (optional, defaults to VM RG) | +| `existingLogAnalyticsWorkspaceId` | string | `""` | `enablePerProcessMetrics=true` AND `createNewLogAnalyticsWorkspace=false` | + +### Data Collection Rule + +| Parameter | Type | Default | Required when | +|-----------|------|---------|---------------| +| `createNewDcr` | bool | `true` | n/a | +| `dcrName` | string | `msvmi-{location}-{vmName}` | `createNewDcr=true` (optional, has default) | +| `dcrResourceGroup` | string | VM RG | `createNewDcr=true` (optional, defaults to VM RG) | +| `existingDcrId` | string | `""` | `createNewDcr=false` | + +> ⚠️ **Existing DCR requirements:** When reusing an existing DCR, it must already be configured for VM Insights V2. For standard metrics, the DCR must include `performanceCountersOTel` with stream `Microsoft-OtelPerfMetrics` and an AMW destination. For per-process metrics, it must also include the relevant `process.*` counters and a Log Analytics destination for `InsightsMetrics`. The DCR must be in the same region as the VM. + +### Metrics & Alerts + +| Parameter | Type | Default | Required when | +|-----------|------|---------|---------------| +| `enablePerProcessMetrics` | bool | `false` | n/a | +| `enableAlerts` | bool | `false` | n/a | +| `uamiResourceId` | string | `""` | `enableAlerts=true` | + +## What Gets Deployed + +### Standard (free) tier + +``` +VM ← AMA Extension +VM ← DCRA (VirtualMachineInsightsExtension) + └── DCR (performanceCountersOTel) + 10 system.* OTel metrics → AMW +``` + +**OTel counters:** `system.cpu.time`, `system.memory.usage`, `system.disk.io`, `system.disk.operations`, `system.disk.operation_time`, `system.filesystem.usage`, `system.network.io`, `system.network.dropped`, `system.network.errors`, `system.uptime` + +### Per-process (paid) tier + +``` +VM ← AMA Extension +VM ← DCRA (VirtualMachineInsightsExtension) + └── DCR (combined) + ├── performanceCountersOTel + │ 25+ counters (system.* + process.*) → AMW + └── performanceCounters + \VmInsights\DetailedMetrics → LA Workspace +``` + +**Additional per-process counters:** `process.uptime`, `process.cpu.time`, `process.cpu.utilization`, `process.memory.usage`, `process.memory.virtual`, `process.memory.utilization`, `process.disk.io`, `process.disk.operations`, `process.paging.faults`, `process.open_file_descriptors`, `process.threads`, `process.handles`, `process.context_switches`, `process.signals_pending`, `system.processes.count`, `system.processes.created` + +### Alert rules (when enabled) + +| Alert | Type | Condition | +|-------|------|-----------| +| **VM Availability** | Platform metric | Availability < 1 over 5 min | +| **Guest OS CPU Usage** | PromQL | CPU utilization > 80% over 5 min | +| **Guest OS Memory Usage** | PromQL | Available memory < 1 GB over 5 min | +| **Guest OS Disk IOPS** | PromQL | Disk operations > 5000/sec over 5 min | +| **Guest OS Network In** | PromQL | Inbound traffic > 100 GB/day | +| **Guest OS Network Out** | PromQL | Outbound traffic > 50 GB/day | +| **Guest OS Network Errors** | PromQL | Network errors > 10 in 5 min | +| **Guest OS Disk Operation Time** | PromQL | Avg disk op time > 100ms over 5 min | + +All guest OS alerts use a 2-minute failing period and auto-resolve after 2 minutes. VM Availability is a platform metric alert (no UAMI needed); all guest OS alerts use PromQL and require a UAMI with Monitoring Reader on the AMW. + +> ⚠️ **No notifications by default.** Alert rules are created without action groups, so no email/SMS/webhook notifications are sent when alerts fire. To receive notifications, [attach an action group](https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups) to each alert rule after deployment, or extend the template to include action group references. + +## ARM vs Bicep: Which to Use? + +| | ARM (`vmi-v2-onboard.json`) | Bicep (`bicep/main.bicep`) | +|---|---|---| +| **Best for** | Portal "Deploy a custom template", REST API, existing ARM pipelines | Azure CLI, CI/CD pipelines, composing into larger deployments | +| **Single file** | ✅ One JSON file | ❌ Main + 8 modules | +| **Readability** | Verbose JSON | Concise, commented | +| **Extensibility** | Edit one large file | Add/swap modules independently | + +The Bicep modules in `bicep/modules/` can also be referenced individually from your own Bicep templates if you only need specific pieces (e.g., just the DCR or just the alerts). + +## Repository Structure + +``` +├── vmi-v2-onboard.json # ARM: parameterized template +├── parameters/ # ARM: parameter files for common scenarios +│ ├── standard-new-amw-new-dcr.parameters.json +│ ├── standard-existing-amw-new-dcr.parameters.json +│ ├── existing-dcr.parameters.json +│ ├── standard-new-amw-with-alerts.parameters.json +│ ├── per-process-new-all-with-alerts.parameters.json +│ └── per-process-existing-amw-existing-la.parameters.json +├── bicep/ # Bicep: modular equivalent +│ ├── main.bicep # orchestrator +│ ├── modules/ # individual resource modules +│ │ ├── vm-identity.bicep +│ │ ├── amw.bicep +│ │ ├── log-analytics.bicep +│ │ ├── dcr-standard.bicep +│ │ ├── dcr-per-process.bicep +│ │ ├── dcra.bicep +│ │ ├── ama-extension.bicep +│ │ ├── alert-host.bicep +│ │ └── alert-guest.bicep +│ └── parameters/ # .bicepparam files +│ └── (same scenarios as ARM) +└── README.md +``` diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/main.bicep b/Scenarios/How to onboard VMs to VM Insights V2/bicep/main.bicep new file mode 100644 index 00000000..39f6048e --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/main.bicep @@ -0,0 +1,268 @@ +// ============================================================================ +// VM Insights V2 Onboarding (Bicep) +// +// Single parameterized template covering: +// - New or existing Azure Monitor Workspace (AMW) +// - New or existing Log Analytics workspace (for per-process metrics) +// - New or existing Data Collection Rule (DCR) +// - Standard (free) or per-process (paid) metrics tier +// - Optional recommended alert rules +// ============================================================================ + +targetScope = 'subscription' + +// --------------------------------------------------------------------------- +// VM Configuration +// --------------------------------------------------------------------------- + +@description('Name of the existing virtual machine to onboard.') +param vmName string + +@description('Resource group containing the VM.') +param vmResourceGroup string + +@description('Subscription ID of the VM.') +param vmSubscriptionId string + +@description('Azure region (must match VM location, e.g. eastus2).') +param location string + +@allowed(['Windows', 'Linux']) +@description('OS type of the VM, which determines the AMA extension to install.') +param osType string = 'Linux' + +// --------------------------------------------------------------------------- +// Managed Identity +// --------------------------------------------------------------------------- + +@description('Enable system-assigned managed identity on the VM (required by AMA). Safe to set true even if already enabled.') +param enableSystemAssignedIdentity bool = true + +@allowed(['SystemAssigned', 'SystemAssigned, UserAssigned']) +@description('Use "SystemAssigned, UserAssigned" if the VM already has user-assigned identities to avoid overwriting them.') +param identityType string = 'SystemAssigned' + +// --------------------------------------------------------------------------- +// Azure Monitor Workspace +// --------------------------------------------------------------------------- + +@description('Set to true to create a new Azure Monitor Workspace. Set to false to use an existing one via existingAmwResourceId.') +param createNewAmw bool = false + +@description('Name for the new Azure Monitor Workspace. Required when createNewAmw=true.') +param amwName string = '' + +@description('Resource group for the new AMW. Defaults to VM resource group.') +param amwResourceGroup string = vmResourceGroup + +@description('Full resource ID of an existing Azure Monitor Workspace. Required when createNewAmw=false.') +param existingAmwResourceId string = '' + +// --------------------------------------------------------------------------- +// Log Analytics Workspace (required for per-process metrics) +// --------------------------------------------------------------------------- + +@description('Set to true to create a new Log Analytics workspace. Only used when enablePerProcessMetrics=true.') +param createNewLogAnalyticsWorkspace bool = false + +@description('Name for the new Log Analytics workspace. Required when createNewLogAnalyticsWorkspace=true.') +param logAnalyticsWorkspaceName string = '' + +@description('Resource group for the new Log Analytics workspace. Defaults to VM resource group.') +param logAnalyticsResourceGroup string = vmResourceGroup + +@description('Full resource ID of an existing Log Analytics workspace. Required when enablePerProcessMetrics=true and createNewLogAnalyticsWorkspace=false.') +param existingLogAnalyticsWorkspaceId string = '' + +// --------------------------------------------------------------------------- +// Data Collection Rule +// --------------------------------------------------------------------------- + +@description('Set to true to create a new Data Collection Rule. Set to false to use an existing one via existingDcrId.') +param createNewDcr bool = true + +@description('Name for the new DCR. Defaults to msvmi-{location}-{vmName}.') +param dcrName string = 'msvmi-${location}-${vmName}' + +@description('Resource group for the new DCR. Defaults to VM resource group.') +param dcrResourceGroup string = vmResourceGroup + +@description('Full resource ID of an existing DCR. Required when createNewDcr=false.') +param existingDcrId string = '' + +// --------------------------------------------------------------------------- +// Metrics Tier +// --------------------------------------------------------------------------- + +@description('Enable per-process metrics (paid tier). Adds process.* OTel counters and InsightsMetrics/DetailedMetrics via Log Analytics. Requires a Log Analytics workspace.') +param enablePerProcessMetrics bool = false + +// --------------------------------------------------------------------------- +// Alerts +// --------------------------------------------------------------------------- + +@description('Create recommended VM Insights alert rules (VM Availability + guest OS alerts for CPU, memory, disk, network).') +param enableAlerts bool = false + +@description('Full resource ID of a User-Assigned Managed Identity for guest OS PromQL-based alerts. Required when enableAlerts=true.') +param uamiResourceId string = '' + +// --------------------------------------------------------------------------- +// Computed values +// --------------------------------------------------------------------------- + +var vmResourceId = '/subscriptions/${vmSubscriptionId}/resourceGroups/${vmResourceGroup}/providers/Microsoft.Compute/virtualMachines/${vmName}' +var amaExtensionType = osType == 'Windows' ? 'AzureMonitorWindowsAgent' : 'AzureMonitorLinuxAgent' + +var amwResourceId = createNewAmw + ? '/subscriptions/${vmSubscriptionId}/resourceGroups/${amwResourceGroup}/providers/microsoft.monitor/accounts/${amwName}' + : existingAmwResourceId + +var logAnalyticsWorkspaceId = createNewLogAnalyticsWorkspace + ? '/subscriptions/${vmSubscriptionId}/resourceGroups/${logAnalyticsResourceGroup}/providers/microsoft.operationalinsights/workspaces/${logAnalyticsWorkspaceName}' + : existingLogAnalyticsWorkspaceId + +var dcrResourceId = createNewDcr + ? '/subscriptions/${vmSubscriptionId}/resourceGroups/${dcrResourceGroup}/providers/Microsoft.Insights/dataCollectionRules/${dcrName}' + : existingDcrId + +var standardOtelCounters = [ + 'system.filesystem.usage' + 'system.disk.io' + 'system.disk.operation_time' + 'system.disk.operations' + 'system.memory.usage' + 'system.network.io' + 'system.cpu.time' + 'system.network.dropped' + 'system.network.errors' + 'system.uptime' +] + +var processOtelCounters = [ + 'process.uptime' + 'process.cpu.time' + 'process.cpu.utilization' + 'process.memory.usage' + 'process.memory.virtual' + 'process.memory.utilization' + 'process.disk.io' + 'process.disk.operations' + 'process.paging.faults' + 'process.open_file_descriptors' + 'process.threads' + 'process.handles' + 'process.context_switches' + 'process.signals_pending' + 'system.processes.count' + 'system.processes.created' +] + +var allOtelCounters = concat(standardOtelCounters, processOtelCounters) + +// ============================================================================ +// Module deployments (scoped to their respective resource groups) +// ============================================================================ + +// --- Enable system-assigned managed identity on the VM --- +module enableIdentity 'modules/vm-identity.bicep' = if (enableSystemAssignedIdentity) { + name: 'EnableVMSystemIdentity' + scope: resourceGroup(vmSubscriptionId, vmResourceGroup) + params: { + vmName: vmName + location: location + identityType: identityType + } +} + +// --- Create a new Azure Monitor Workspace --- +module createAmw 'modules/amw.bicep' = if (createNewAmw) { + name: 'CreateAMW' + scope: resourceGroup(vmSubscriptionId, amwResourceGroup) + params: { + amwName: amwName + location: location + } +} + +// --- Create a new Log Analytics workspace (for per-process metrics) --- +module createLa 'modules/log-analytics.bicep' = if (createNewLogAnalyticsWorkspace && enablePerProcessMetrics) { + name: 'CreateLogAnalyticsWorkspace' + scope: resourceGroup(vmSubscriptionId, logAnalyticsResourceGroup) + params: { + workspaceName: logAnalyticsWorkspaceName + location: location + } +} + +// --- DCR: Standard OTel metrics only (free tier) --- +module createStandardDcr 'modules/dcr-standard.bicep' = if (createNewDcr && !enablePerProcessMetrics) { + name: 'CreateStandardDCR' + scope: resourceGroup(vmSubscriptionId, dcrResourceGroup) + dependsOn: [createAmw] + params: { + dcrName: dcrName + location: location + amwResourceId: amwResourceId + counterSpecifiers: standardOtelCounters + } +} + +// --- DCR: Per-process metrics (paid tier) --- +module createPerProcessDcr 'modules/dcr-per-process.bicep' = if (createNewDcr && enablePerProcessMetrics) { + name: 'CreatePerProcessDCR' + scope: resourceGroup(vmSubscriptionId, dcrResourceGroup) + dependsOn: [createAmw, createLa] + params: { + dcrName: dcrName + location: location + amwResourceId: amwResourceId + logAnalyticsWorkspaceId: logAnalyticsWorkspaceId + counterSpecifiers: allOtelCounters + } +} + +// --- Associate DCR with VM --- +module createDcra 'modules/dcra.bicep' = { + name: 'CreateDCRA' + scope: resourceGroup(vmSubscriptionId, vmResourceGroup) + dependsOn: [createStandardDcr, createPerProcessDcr] + params: { + vmResourceId: vmResourceId + dcrResourceId: dcrResourceId + } +} + +// --- Install Azure Monitor Agent extension --- +module installAma 'modules/ama-extension.bicep' = { + name: 'InstallAMAExtension' + scope: resourceGroup(vmSubscriptionId, vmResourceGroup) + dependsOn: [createDcra, enableIdentity] + params: { + vmName: vmName + location: location + amaExtensionType: amaExtensionType + } +} + +// --- Host alert: VM Availability --- +module hostAlerts 'modules/alert-host.bicep' = if (enableAlerts) { + name: 'CreateHostAlertRules' + scope: resourceGroup(vmSubscriptionId, vmResourceGroup) + params: { + vmName: vmName + vmResourceId: vmResourceId + } +} + +// --- Guest OS alerts (PromQL-based, requires UAMI) --- +module guestAlerts 'modules/alert-guest.bicep' = if (enableAlerts) { + name: 'CreateGuestAlertRules' + scope: resourceGroup(vmSubscriptionId, vmResourceGroup) + params: { + vmName: vmName + location: location + vmResourceId: vmResourceId + uamiResourceId: uamiResourceId + } +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/alert-guest.bicep b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/alert-guest.bicep new file mode 100644 index 00000000..93772e47 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/alert-guest.bicep @@ -0,0 +1,203 @@ +param vmName string +param location string +param vmResourceId string +param uamiResourceId string + +var uamiIdentity = { + type: 'UserAssigned' + userAssignedIdentities: { + '${uamiResourceId}': {} + } +} + +var failingPeriods = { for: 'PT2M' } +var resolveConfig = { autoResolved: true, timeToResolve: 'PT2M' } + +// --- Guest OS CPU Usage --- +resource cpuAlert 'Microsoft.Insights/metricAlerts@2024-03-01-preview' = { + name: 'Guest OS CPU Usage - ${vmName}' + location: location + identity: uamiIdentity + properties: { + description: 'CPU usage has exceeded 80% threshold over the last 5 minutes' + severity: 3 + enabled: true + scopes: [vmResourceId] + evaluationFrequency: 'PT1M' + criteria: { + 'odata.type': 'Microsoft.Azure.Monitor.PromQLCriteria' + allOf: [ + { + name: 'Metric1' + query: 'avg_over_time(((sum (irate({"system.cpu.time","state" !~ "idle|iowait|steal"}[2m]))) / (sum (irate({"system.cpu.time"}[2m]))))[5m:]) * 100 > 80' + criterionType: 'StaticThresholdCriterion' + } + ] + failingPeriods: failingPeriods + } + resolveConfiguration: resolveConfig + actions: [] + } +} + +// --- Guest OS Memory Usage --- +resource memoryAlert 'Microsoft.Insights/metricAlerts@2024-03-01-preview' = { + name: 'Guest OS Memory Usage - ${vmName}' + location: location + identity: uamiIdentity + properties: { + description: 'Available memory has dropped below 1 GB over the last 5 minutes' + severity: 3 + enabled: true + scopes: [vmResourceId] + evaluationFrequency: 'PT1M' + criteria: { + 'odata.type': 'Microsoft.Azure.Monitor.PromQLCriteria' + allOf: [ + { + name: 'Metric1' + query: 'min_over_time((sum ({"system.memory.usage", state=~"free|cached|buffered|slab_reclaimable"}))[5m:]) < (1 * 1024 * 1024 * 1024)' + criterionType: 'StaticThresholdCriterion' + } + ] + failingPeriods: failingPeriods + } + resolveConfiguration: resolveConfig + actions: [] + } +} + +// --- Guest OS Disk IOPS --- +resource diskIopsAlert 'Microsoft.Insights/metricAlerts@2024-03-01-preview' = { + name: 'Guest OS Disk IOPS - ${vmName}' + location: location + identity: uamiIdentity + properties: { + description: 'Disk IOPS has exceeded 5000 operations per second over the last 5 minutes' + severity: 3 + enabled: true + scopes: [vmResourceId] + evaluationFrequency: 'PT1M' + criteria: { + 'odata.type': 'Microsoft.Azure.Monitor.PromQLCriteria' + allOf: [ + { + name: 'Metric1' + query: 'max_over_time((sum (irate({"system.disk.operations"}[2m])))[5m:]) > 5000' + criterionType: 'StaticThresholdCriterion' + } + ] + failingPeriods: failingPeriods + } + resolveConfiguration: resolveConfig + actions: [] + } +} + +// --- Guest OS Network In --- +resource networkInAlert 'Microsoft.Insights/metricAlerts@2024-03-01-preview' = { + name: 'Guest OS Network In - ${vmName}' + location: location + identity: uamiIdentity + properties: { + description: 'Total network inbound traffic has exceeded 100 GB over the last day' + severity: 3 + enabled: true + scopes: [vmResourceId] + evaluationFrequency: 'PT1M' + criteria: { + 'odata.type': 'Microsoft.Azure.Monitor.PromQLCriteria' + allOf: [ + { + name: 'Metric1' + query: 'sum_over_time((sum (irate({"system.network.io", direction="receive"}[2m])))[1d:]) > (100 * 1024 * 1024 * 1024)' + criterionType: 'StaticThresholdCriterion' + } + ] + failingPeriods: failingPeriods + } + resolveConfiguration: resolveConfig + actions: [] + } +} + +// --- Guest OS Network Out --- +resource networkOutAlert 'Microsoft.Insights/metricAlerts@2024-03-01-preview' = { + name: 'Guest OS Network Out - ${vmName}' + location: location + identity: uamiIdentity + properties: { + description: 'Total network outbound traffic has exceeded 50 GB over the last day' + severity: 3 + enabled: true + scopes: [vmResourceId] + evaluationFrequency: 'PT1M' + criteria: { + 'odata.type': 'Microsoft.Azure.Monitor.PromQLCriteria' + allOf: [ + { + name: 'Metric1' + query: 'sum_over_time((sum (irate({"system.network.io", direction="transmit"}[2m])))[1d:]) > (50 * 1024 * 1024 * 1024)' + criterionType: 'StaticThresholdCriterion' + } + ] + failingPeriods: failingPeriods + } + resolveConfiguration: resolveConfig + actions: [] + } +} + +// --- Guest OS Network Errors --- +resource networkErrorsAlert 'Microsoft.Insights/metricAlerts@2024-03-01-preview' = { + name: 'Guest OS Network Errors - ${vmName}' + location: location + identity: uamiIdentity + properties: { + description: 'Network errors have exceeded 10 total errors over the last 5 minutes' + severity: 3 + enabled: true + scopes: [vmResourceId] + evaluationFrequency: 'PT1M' + criteria: { + 'odata.type': 'Microsoft.Azure.Monitor.PromQLCriteria' + allOf: [ + { + name: 'Metric1' + query: 'sum_over_time((sum (irate({"system.network.errors"}[2m])))[5m:]) > 10' + criterionType: 'StaticThresholdCriterion' + } + ] + failingPeriods: failingPeriods + } + resolveConfiguration: resolveConfig + actions: [] + } +} + +// --- Guest OS Disk Operation Time --- +resource diskOpTimeAlert 'Microsoft.Insights/metricAlerts@2024-03-01-preview' = { + name: 'Guest OS Disk Operation Time - ${vmName}' + location: location + identity: uamiIdentity + properties: { + description: 'Average disk operation time has exceeded 100ms over the last 5 minutes' + severity: 3 + enabled: true + scopes: [vmResourceId] + evaluationFrequency: 'PT1M' + criteria: { + 'odata.type': 'Microsoft.Azure.Monitor.PromQLCriteria' + allOf: [ + { + name: 'Metric1' + query: 'avg_over_time(((sum (irate({"system.disk.operation_time"}[2m]))) / (sum (irate({"system.disk.operations"}[2m]))))[5m:]) * 1000 > 100' + criterionType: 'StaticThresholdCriterion' + } + ] + failingPeriods: failingPeriods + } + resolveConfiguration: resolveConfig + actions: [] + } +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/alert-host.bicep b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/alert-host.bicep new file mode 100644 index 00000000..361f961f --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/alert-host.bicep @@ -0,0 +1,30 @@ +param vmName string +param vmResourceId string + +resource vmAvailabilityAlert 'Microsoft.Insights/metricAlerts@2018-03-01' = { + name: 'VM Availability - ${vmName}' + location: 'global' + properties: { + description: 'VM is unavailable or not responding' + severity: 3 + enabled: true + scopes: [vmResourceId] + evaluationFrequency: 'PT5M' + windowSize: 'PT5M' + criteria: { + 'odata.type': 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria' + allOf: [ + { + name: 'Metric1' + metricName: 'VmAvailabilityMetric' + metricNamespace: 'Microsoft.Compute/virtualMachines' + operator: 'LessThan' + threshold: 1 + timeAggregation: 'Average' + criterionType: 'StaticThresholdCriterion' + } + ] + } + actions: [] + } +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/ama-extension.bicep b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/ama-extension.bicep new file mode 100644 index 00000000..753b24b6 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/ama-extension.bicep @@ -0,0 +1,15 @@ +param vmName string +param location string +param amaExtensionType string + +resource amaExtension 'Microsoft.Compute/virtualMachines/extensions@2022-11-01' = { + name: '${vmName}/${amaExtensionType}' + location: location + properties: { + publisher: 'Microsoft.Azure.Monitor' + type: amaExtensionType + typeHandlerVersion: '1.0' + autoUpgradeMinorVersion: true + enableAutomaticUpgrade: true + } +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/amw.bicep b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/amw.bicep new file mode 100644 index 00000000..5f487c81 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/amw.bicep @@ -0,0 +1,10 @@ +param amwName string +param location string + +resource amw 'microsoft.monitor/accounts@2023-04-03' = { + name: amwName + location: location + properties: {} +} + +output amwResourceId string = amw.id diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/dcr-per-process.bicep b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/dcr-per-process.bicep new file mode 100644 index 00000000..51985cba --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/dcr-per-process.bicep @@ -0,0 +1,57 @@ +param dcrName string +param location string +param amwResourceId string +param logAnalyticsWorkspaceId string +param counterSpecifiers array + +resource dcr 'Microsoft.Insights/dataCollectionRules@2024-03-11' = { + name: dcrName + location: location + properties: { + dataSources: { + performanceCounters: [ + { + name: 'Microsoft-InsightsMetrics' + streams: ['Microsoft-InsightsMetrics'] + scheduledTransferPeriod: 'PT1M' + samplingFrequencyInSeconds: 60 + counterSpecifiers: ['\\VmInsights\\DetailedMetrics'] + } + ] + performanceCountersOTel: [ + { + name: 'OtelDataSource' + streams: ['Microsoft-OtelPerfMetrics'] + samplingFrequencyInSeconds: 60 + counterSpecifiers: counterSpecifiers + } + ] + } + destinations: { + logAnalytics: [ + { + workspaceResourceId: logAnalyticsWorkspaceId + name: 'vmInsightworkspace' + } + ] + monitoringAccounts: [ + { + accountResourceId: amwResourceId + name: 'MonitoringAccountDestination' + } + ] + } + dataFlows: [ + { + streams: ['Microsoft-InsightsMetrics'] + destinations: ['vmInsightworkspace'] + } + { + streams: ['Microsoft-OtelPerfMetrics'] + destinations: ['MonitoringAccountDestination'] + } + ] + } +} + +output dcrId string = dcr.id diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/dcr-standard.bicep b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/dcr-standard.bicep new file mode 100644 index 00000000..fbdc479d --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/dcr-standard.bicep @@ -0,0 +1,37 @@ +param dcrName string +param location string +param amwResourceId string +param counterSpecifiers array + +resource dcr 'Microsoft.Insights/dataCollectionRules@2024-03-11' = { + name: dcrName + location: location + properties: { + dataSources: { + performanceCountersOTel: [ + { + name: 'OtelDataSource' + streams: ['Microsoft-OtelPerfMetrics'] + samplingFrequencyInSeconds: 60 + counterSpecifiers: counterSpecifiers + } + ] + } + destinations: { + monitoringAccounts: [ + { + accountResourceId: amwResourceId + name: 'MonitoringAccountDestination' + } + ] + } + dataFlows: [ + { + streams: ['Microsoft-OtelPerfMetrics'] + destinations: ['MonitoringAccountDestination'] + } + ] + } +} + +output dcrId string = dcr.id diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/dcra.bicep b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/dcra.bicep new file mode 100644 index 00000000..d5c4a140 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/dcra.bicep @@ -0,0 +1,15 @@ +param vmResourceId string +param dcrResourceId string + +resource dcra 'Microsoft.Insights/dataCollectionRuleAssociations@2022-06-01' = { + name: 'VirtualMachineInsightsExtension' + scope: existing_vm + properties: { + description: 'Association of data collection rule. Deleting this association will break the data collection for this virtual machine.' + dataCollectionRuleId: dcrResourceId + } +} + +resource existing_vm 'Microsoft.Compute/virtualMachines@2022-11-01' existing = { + name: last(split(vmResourceId, '/')) +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/log-analytics.bicep b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/log-analytics.bicep new file mode 100644 index 00000000..c056b52f --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/log-analytics.bicep @@ -0,0 +1,13 @@ +param workspaceName string +param location string + +resource workspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { + name: workspaceName + location: location + properties: { + sku: { name: 'PerGB2018' } + retentionInDays: 30 + } +} + +output workspaceId string = workspace.id diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/vm-identity.bicep b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/vm-identity.bicep new file mode 100644 index 00000000..60135b09 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/modules/vm-identity.bicep @@ -0,0 +1,11 @@ +param vmName string +param location string +param identityType string + +resource vm 'Microsoft.Compute/virtualMachines@2022-11-01' = { + name: vmName + location: location + identity: { + type: identityType + } +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/existing-dcr.bicepparam b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/existing-dcr.bicepparam new file mode 100644 index 00000000..7a529cb4 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/existing-dcr.bicepparam @@ -0,0 +1,16 @@ +using '../main.bicep' + +// Reuse existing DCR, the fastest onboarding path + +param vmName = '' +param vmResourceGroup = '' +param vmSubscriptionId = '' +param location = '' +param osType = 'Linux' + +param createNewAmw = false +param createNewDcr = false +param existingDcrId = '/subscriptions//resourceGroups//providers/Microsoft.Insights/dataCollectionRules/' + +param enablePerProcessMetrics = false +param enableAlerts = false diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/per-process-existing-amw-existing-la.bicepparam b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/per-process-existing-amw-existing-la.bicepparam new file mode 100644 index 00000000..452ebdbd --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/per-process-existing-amw-existing-la.bicepparam @@ -0,0 +1,20 @@ +using '../main.bicep' + +// Per-process (paid) tier: existing AMW + existing LA, new DCR, no alerts + +param vmName = '' +param vmResourceGroup = '' +param vmSubscriptionId = '' +param location = '' +param osType = 'Linux' + +param createNewAmw = false +param existingAmwResourceId = '/subscriptions//resourceGroups//providers/microsoft.monitor/accounts/' + +param createNewLogAnalyticsWorkspace = false +param existingLogAnalyticsWorkspaceId = '/subscriptions//resourceGroups//providers/microsoft.operationalinsights/workspaces/' + +param createNewDcr = true +param enablePerProcessMetrics = true + +param enableAlerts = false diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/per-process-new-all-with-alerts.bicepparam b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/per-process-new-all-with-alerts.bicepparam new file mode 100644 index 00000000..0fa9ae44 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/per-process-new-all-with-alerts.bicepparam @@ -0,0 +1,21 @@ +using '../main.bicep' + +// Per-process (paid) tier: new AMW + LA + DCR + all alerts + +param vmName = '' +param vmResourceGroup = '' +param vmSubscriptionId = '' +param location = '' +param osType = 'Linux' + +param createNewAmw = true +param amwName = '' + +param createNewLogAnalyticsWorkspace = true +param logAnalyticsWorkspaceName = '' + +param createNewDcr = true +param enablePerProcessMetrics = true + +param enableAlerts = true +param uamiResourceId = '/subscriptions//resourceGroups//providers/Microsoft.ManagedIdentity/userAssignedIdentities/' diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/standard-existing-amw-new-dcr.bicepparam b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/standard-existing-amw-new-dcr.bicepparam new file mode 100644 index 00000000..f8f2af17 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/standard-existing-amw-new-dcr.bicepparam @@ -0,0 +1,16 @@ +using '../main.bicep' + +// Standard free-tier: existing AMW, new DCR + +param vmName = '' +param vmResourceGroup = '' +param vmSubscriptionId = '' +param location = '' +param osType = 'Linux' + +param createNewAmw = false +param existingAmwResourceId = '/subscriptions//resourceGroups//providers/microsoft.monitor/accounts/' + +param createNewDcr = true +param enablePerProcessMetrics = false +param enableAlerts = false diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/standard-new-amw-new-dcr.bicepparam b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/standard-new-amw-new-dcr.bicepparam new file mode 100644 index 00000000..5a0b7526 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/standard-new-amw-new-dcr.bicepparam @@ -0,0 +1,16 @@ +using '../main.bicep' + +// Standard free-tier: new AMW + new DCR, no per-process, no alerts + +param vmName = '' +param vmResourceGroup = '' +param vmSubscriptionId = '' +param location = '' +param osType = 'Linux' + +param createNewAmw = true +param amwName = '' + +param createNewDcr = true +param enablePerProcessMetrics = false +param enableAlerts = false diff --git a/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/standard-new-amw-with-alerts.bicepparam b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/standard-new-amw-with-alerts.bicepparam new file mode 100644 index 00000000..e5eee9f3 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/bicep/parameters/standard-new-amw-with-alerts.bicepparam @@ -0,0 +1,18 @@ +using '../main.bicep' + +// Standard free-tier with all recommended alerts + +param vmName = '' +param vmResourceGroup = '' +param vmSubscriptionId = '' +param location = '' +param osType = 'Linux' + +param createNewAmw = true +param amwName = '' + +param createNewDcr = true +param enablePerProcessMetrics = false + +param enableAlerts = true +param uamiResourceId = '/subscriptions//resourceGroups//providers/Microsoft.ManagedIdentity/userAssignedIdentities/' diff --git a/Scenarios/How to onboard VMs to VM Insights V2/parameters/existing-dcr.parameters.json b/Scenarios/How to onboard VMs to VM Insights V2/parameters/existing-dcr.parameters.json new file mode 100644 index 00000000..c6203faa --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/parameters/existing-dcr.parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "description": "Reuse an existing DCR. Only creates the DCRA association and installs the AMA extension. Fastest onboarding for VMs sharing a DCR." + }, + "parameters": { + "vmName": { "value": "" }, + "vmResourceGroup": { "value": "" }, + "vmSubscriptionId": { "value": "" }, + "location": { "value": "" }, + "osType": { "value": "Linux" }, + "createNewAmw": { "value": false }, + "createNewDcr": { "value": false }, + "existingDcrId": { "value": "/subscriptions//resourceGroups//providers/Microsoft.Insights/dataCollectionRules/" }, + "enablePerProcessMetrics": { "value": false }, + "enableAlerts": { "value": false } + } +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/parameters/per-process-existing-amw-existing-la.parameters.json b/Scenarios/How to onboard VMs to VM Insights V2/parameters/per-process-existing-amw-existing-la.parameters.json new file mode 100644 index 00000000..01849062 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/parameters/per-process-existing-amw-existing-la.parameters.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "description": "Per-process metrics (paid tier) using existing AMW and existing LA workspace. Creates a new DCR. No alerts." + }, + "parameters": { + "vmName": { "value": "" }, + "vmResourceGroup": { "value": "" }, + "vmSubscriptionId": { "value": "" }, + "location": { "value": "" }, + "osType": { "value": "Linux" }, + "createNewAmw": { "value": false }, + "existingAmwResourceId": { "value": "/subscriptions//resourceGroups//providers/microsoft.monitor/accounts/" }, + "createNewLogAnalyticsWorkspace": { "value": false }, + "existingLogAnalyticsWorkspaceId": { "value": "/subscriptions//resourceGroups//providers/microsoft.operationalinsights/workspaces/" }, + "createNewDcr": { "value": true }, + "enablePerProcessMetrics": { "value": true }, + "enableAlerts": { "value": false } + } +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/parameters/per-process-new-all-with-alerts.parameters.json b/Scenarios/How to onboard VMs to VM Insights V2/parameters/per-process-new-all-with-alerts.parameters.json new file mode 100644 index 00000000..6e9e5fa5 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/parameters/per-process-new-all-with-alerts.parameters.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "description": "Per-process metrics (paid tier) with all recommended alerts. Creates new AMW, LA workspace, and DCR with both OTel and InsightsMetrics/DetailedMetrics data sources." + }, + "parameters": { + "vmName": { "value": "" }, + "vmResourceGroup": { "value": "" }, + "vmSubscriptionId": { "value": "" }, + "location": { "value": "" }, + "osType": { "value": "Linux" }, + "createNewAmw": { "value": true }, + "amwName": { "value": "" }, + "createNewLogAnalyticsWorkspace": { "value": true }, + "logAnalyticsWorkspaceName": { "value": "" }, + "createNewDcr": { "value": true }, + "enablePerProcessMetrics": { "value": true }, + "enableAlerts": { "value": true }, + "uamiResourceId": { "value": "/subscriptions//resourceGroups//providers/Microsoft.ManagedIdentity/userAssignedIdentities/" } + } +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/parameters/standard-existing-amw-new-dcr.parameters.json b/Scenarios/How to onboard VMs to VM Insights V2/parameters/standard-existing-amw-new-dcr.parameters.json new file mode 100644 index 00000000..5e18c753 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/parameters/standard-existing-amw-new-dcr.parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "description": "Standard free-tier VMI onboarding: creates a new DCR using an existing AMW. No per-process metrics, no alerts." + }, + "parameters": { + "vmName": { "value": "" }, + "vmResourceGroup": { "value": "" }, + "vmSubscriptionId": { "value": "" }, + "location": { "value": "" }, + "osType": { "value": "Linux" }, + "createNewAmw": { "value": false }, + "existingAmwResourceId": { "value": "/subscriptions//resourceGroups//providers/microsoft.monitor/accounts/" }, + "createNewDcr": { "value": true }, + "enablePerProcessMetrics": { "value": false }, + "enableAlerts": { "value": false } + } +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/parameters/standard-new-amw-new-dcr.parameters.json b/Scenarios/How to onboard VMs to VM Insights V2/parameters/standard-new-amw-new-dcr.parameters.json new file mode 100644 index 00000000..24f7c075 --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/parameters/standard-new-amw-new-dcr.parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "description": "Standard free-tier VMI onboarding: creates a new AMW and new DCR with system-level OTel metrics. No per-process metrics, no alerts." + }, + "parameters": { + "vmName": { "value": "" }, + "vmResourceGroup": { "value": "" }, + "vmSubscriptionId": { "value": "" }, + "location": { "value": "" }, + "osType": { "value": "Linux" }, + "createNewAmw": { "value": true }, + "amwName": { "value": "" }, + "createNewDcr": { "value": true }, + "enablePerProcessMetrics": { "value": false }, + "enableAlerts": { "value": false } + } +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/parameters/standard-new-amw-with-alerts.parameters.json b/Scenarios/How to onboard VMs to VM Insights V2/parameters/standard-new-amw-with-alerts.parameters.json new file mode 100644 index 00000000..59bbe0de --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/parameters/standard-new-amw-with-alerts.parameters.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "description": "Standard free-tier with recommended alerts. Creates new AMW and DCR, plus VM Availability and guest OS alert rules." + }, + "parameters": { + "vmName": { "value": "" }, + "vmResourceGroup": { "value": "" }, + "vmSubscriptionId": { "value": "" }, + "location": { "value": "" }, + "osType": { "value": "Linux" }, + "createNewAmw": { "value": true }, + "amwName": { "value": "" }, + "createNewDcr": { "value": true }, + "enablePerProcessMetrics": { "value": false }, + "enableAlerts": { "value": true }, + "uamiResourceId": { "value": "/subscriptions//resourceGroups//providers/Microsoft.ManagedIdentity/userAssignedIdentities/" } + } +} diff --git a/Scenarios/How to onboard VMs to VM Insights V2/vmi-v2-onboard.json b/Scenarios/How to onboard VMs to VM Insights V2/vmi-v2-onboard.json new file mode 100644 index 00000000..f487993e --- /dev/null +++ b/Scenarios/How to onboard VMs to VM Insights V2/vmi-v2-onboard.json @@ -0,0 +1,746 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "vmName": { + "type": "string", + "metadata": { "description": "Name of the existing virtual machine to onboard." } + }, + "vmResourceGroup": { + "type": "string", + "metadata": { "description": "Resource group containing the VM." } + }, + "vmSubscriptionId": { + "type": "string", + "metadata": { "description": "Subscription ID of the VM." } + }, + "location": { + "type": "string", + "metadata": { "description": "Azure region (must match VM location, e.g. eastus2)." } + }, + "osType": { + "type": "string", + "defaultValue": "Linux", + "allowedValues": [ "Windows", "Linux" ], + "metadata": { "description": "OS type of the VM, which determines the AMA extension to install." } + }, + "enableSystemAssignedIdentity": { + "type": "bool", + "defaultValue": true, + "metadata": { "description": "Enable system-assigned managed identity on the VM (required by AMA). Safe to set true even if already enabled." } + }, + "identityType": { + "type": "string", + "defaultValue": "SystemAssigned", + "allowedValues": [ "SystemAssigned", "SystemAssigned, UserAssigned" ], + "metadata": { "description": "Use 'SystemAssigned, UserAssigned' if the VM already has user-assigned identities to avoid overwriting them." } + }, + "createNewAmw": { + "type": "bool", + "defaultValue": false, + "metadata": { "description": "Set to true to create a new Azure Monitor Workspace. Set to false to use an existing one via 'existingAmwResourceId'." } + }, + "amwName": { + "type": "string", + "defaultValue": "", + "metadata": { "description": "Name for the new Azure Monitor Workspace. Required when createNewAmw=true." } + }, + "amwResourceGroup": { + "type": "string", + "defaultValue": "[parameters('vmResourceGroup')]", + "metadata": { "description": "Resource group for the new AMW. Defaults to VM resource group." } + }, + "existingAmwResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { "description": "Full resource ID of an existing Azure Monitor Workspace. Required when createNewAmw=false." } + }, + "createNewLogAnalyticsWorkspace": { + "type": "bool", + "defaultValue": false, + "metadata": { "description": "Set to true to create a new Log Analytics workspace. Only used when enablePerProcessMetrics=true." } + }, + "logAnalyticsWorkspaceName": { + "type": "string", + "defaultValue": "", + "metadata": { "description": "Name for the new Log Analytics workspace. Required when createNewLogAnalyticsWorkspace=true." } + }, + "logAnalyticsResourceGroup": { + "type": "string", + "defaultValue": "[parameters('vmResourceGroup')]", + "metadata": { "description": "Resource group for the new Log Analytics workspace. Defaults to VM resource group." } + }, + "existingLogAnalyticsWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { "description": "Full resource ID of an existing Log Analytics workspace. Required when enablePerProcessMetrics=true and createNewLogAnalyticsWorkspace=false." } + }, + "createNewDcr": { + "type": "bool", + "defaultValue": true, + "metadata": { "description": "Set to true to create a new Data Collection Rule. Set to false to use an existing one via 'existingDcrId'." } + }, + "dcrName": { + "type": "string", + "defaultValue": "[concat('msvmi-', parameters('location'), '-', parameters('vmName'))]", + "metadata": { "description": "Name for the new DCR. Defaults to msvmi-{location}-{vmName}." } + }, + "dcrResourceGroup": { + "type": "string", + "defaultValue": "[parameters('vmResourceGroup')]", + "metadata": { "description": "Resource group for the new DCR. Defaults to VM resource group." } + }, + "existingDcrId": { + "type": "string", + "defaultValue": "", + "metadata": { "description": "Full resource ID of an existing DCR. Required when createNewDcr=false." } + }, + "enablePerProcessMetrics": { + "type": "bool", + "defaultValue": false, + "metadata": { "description": "Enable per-process metrics (paid tier). Adds process.* OTel counters and InsightsMetrics/DetailedMetrics via Log Analytics. Requires a Log Analytics workspace." } + }, + "enableAlerts": { + "type": "bool", + "defaultValue": false, + "metadata": { "description": "Create recommended VM Insights alert rules (VM Availability + guest OS alerts for CPU, memory, disk, network)." } + }, + "uamiResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { "description": "Full resource ID of a User-Assigned Managed Identity for guest OS PromQL-based alerts. Required when enableAlerts=true." } + } + }, + "variables": { + "amaExtensionType": "[if(equals(parameters('osType'), 'Windows'), 'AzureMonitorWindowsAgent', 'AzureMonitorLinuxAgent')]", + "vmResourceId": "[concat('/subscriptions/', parameters('vmSubscriptionId'), '/resourceGroups/', parameters('vmResourceGroup'), '/providers/Microsoft.Compute/virtualMachines/', parameters('vmName'))]", + "amwResourceId": "[if(parameters('createNewAmw'), concat('/subscriptions/', parameters('vmSubscriptionId'), '/resourceGroups/', parameters('amwResourceGroup'), '/providers/microsoft.monitor/accounts/', parameters('amwName')), parameters('existingAmwResourceId'))]", + "logAnalyticsWorkspaceId": "[if(parameters('createNewLogAnalyticsWorkspace'), concat('/subscriptions/', parameters('vmSubscriptionId'), '/resourceGroups/', parameters('logAnalyticsResourceGroup'), '/providers/microsoft.operationalinsights/workspaces/', parameters('logAnalyticsWorkspaceName')), parameters('existingLogAnalyticsWorkspaceId'))]", + "dcrResourceId": "[if(parameters('createNewDcr'), concat('/subscriptions/', parameters('vmSubscriptionId'), '/resourceGroups/', parameters('dcrResourceGroup'), '/providers/Microsoft.Insights/dataCollectionRules/', parameters('dcrName')), parameters('existingDcrId'))]", + "dcraResourceId": "[concat(variables('vmResourceId'), '/providers/Microsoft.Insights/dataCollectionRuleAssociations/VirtualMachineInsightsExtension')]" + }, + "resources": [ + { + "comments": "--- Enable system-assigned managed identity on the VM (required by AMA) ---", + "type": "microsoft.resources/deployments", + "apiVersion": "2021-04-01", + "name": "EnableVMSystemIdentity", + "condition": "[parameters('enableSystemAssignedIdentity')]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('vmName')]", + "location": "[parameters('location')]", + "identity": { + "type": "[parameters('identityType')]" + } + } + ] + } + }, + "subscriptionId": "[parameters('vmSubscriptionId')]", + "resourceGroup": "[parameters('vmResourceGroup')]" + }, + { + "comments": "--- Create a new Azure Monitor Workspace ---", + "type": "microsoft.resources/deployments", + "apiVersion": "2021-04-01", + "name": "CreateAMW", + "condition": "[parameters('createNewAmw')]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "microsoft.monitor/accounts", + "apiVersion": "2023-04-03", + "name": "[parameters('amwName')]", + "location": "[parameters('location')]", + "properties": {} + } + ] + } + }, + "subscriptionId": "[parameters('vmSubscriptionId')]", + "resourceGroup": "[parameters('amwResourceGroup')]" + }, + { + "comments": "--- Create a new Log Analytics workspace (for per-process metrics) ---", + "type": "microsoft.resources/deployments", + "apiVersion": "2021-04-01", + "name": "CreateLogAnalyticsWorkspace", + "condition": "[and(parameters('createNewLogAnalyticsWorkspace'), parameters('enablePerProcessMetrics'))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('logAnalyticsWorkspaceName')]", + "location": "[parameters('location')]", + "properties": { + "sku": { "name": "PerGB2018" }, + "retentionInDays": 30 + } + } + ] + } + }, + "subscriptionId": "[parameters('vmSubscriptionId')]", + "resourceGroup": "[parameters('logAnalyticsResourceGroup')]" + }, + { + "comments": "--- DCR: Standard OTel metrics only (free tier) ---", + "type": "microsoft.resources/deployments", + "apiVersion": "2021-04-01", + "name": "CreateStandardDCR", + "condition": "[and(parameters('createNewDcr'), not(parameters('enablePerProcessMetrics')))]", + "dependsOn": [ + "microsoft.resources/deployments/CreateAMW" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "Microsoft.Insights/dataCollectionRules", + "apiVersion": "2024-03-11", + "name": "[parameters('dcrName')]", + "location": "[parameters('location')]", + "properties": { + "dataSources": { + "performanceCountersOTel": [ + { + "name": "OtelDataSource", + "streams": [ "Microsoft-OtelPerfMetrics" ], + "samplingFrequencyInSeconds": 60, + "counterSpecifiers": [ + "system.filesystem.usage", + "system.disk.io", + "system.disk.operation_time", + "system.disk.operations", + "system.memory.usage", + "system.network.io", + "system.cpu.time", + "system.network.dropped", + "system.network.errors", + "system.uptime" + ] + } + ] + }, + "destinations": { + "monitoringAccounts": [ + { + "accountResourceId": "[variables('amwResourceId')]", + "name": "MonitoringAccountDestination" + } + ] + }, + "dataFlows": [ + { + "streams": [ "Microsoft-OtelPerfMetrics" ], + "destinations": [ "MonitoringAccountDestination" ] + } + ] + } + } + ] + } + }, + "subscriptionId": "[parameters('vmSubscriptionId')]", + "resourceGroup": "[parameters('dcrResourceGroup')]" + }, + { + "comments": "--- DCR: Per-process metrics (paid tier), OTel + InsightsMetrics/DetailedMetrics ---", + "type": "microsoft.resources/deployments", + "apiVersion": "2021-04-01", + "name": "CreatePerProcessDCR", + "condition": "[and(parameters('createNewDcr'), parameters('enablePerProcessMetrics'))]", + "dependsOn": [ + "microsoft.resources/deployments/CreateAMW", + "microsoft.resources/deployments/CreateLogAnalyticsWorkspace" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "Microsoft.Insights/dataCollectionRules", + "apiVersion": "2024-03-11", + "name": "[parameters('dcrName')]", + "location": "[parameters('location')]", + "properties": { + "dataSources": { + "performanceCounters": [ + { + "name": "Microsoft-InsightsMetrics", + "streams": [ "Microsoft-InsightsMetrics" ], + "scheduledTransferPeriod": "PT1M", + "samplingFrequencyInSeconds": 60, + "counterSpecifiers": [ + "\\VmInsights\\DetailedMetrics" + ] + } + ], + "performanceCountersOTel": [ + { + "name": "OtelDataSource", + "streams": [ "Microsoft-OtelPerfMetrics" ], + "samplingFrequencyInSeconds": 60, + "counterSpecifiers": [ + "system.filesystem.usage", + "system.disk.io", + "system.disk.operation_time", + "system.disk.operations", + "system.memory.usage", + "system.network.io", + "system.cpu.time", + "system.network.dropped", + "system.network.errors", + "system.uptime", + "process.uptime", + "process.cpu.time", + "process.cpu.utilization", + "process.memory.usage", + "process.memory.virtual", + "process.memory.utilization", + "process.disk.io", + "process.disk.operations", + "process.paging.faults", + "process.open_file_descriptors", + "process.threads", + "process.handles", + "process.context_switches", + "process.signals_pending", + "system.processes.count", + "system.processes.created" + ] + } + ] + }, + "destinations": { + "logAnalytics": [ + { + "workspaceResourceId": "[variables('logAnalyticsWorkspaceId')]", + "name": "vmInsightworkspace" + } + ], + "monitoringAccounts": [ + { + "accountResourceId": "[variables('amwResourceId')]", + "name": "MonitoringAccountDestination" + } + ] + }, + "dataFlows": [ + { + "streams": [ "Microsoft-InsightsMetrics" ], + "destinations": [ "vmInsightworkspace" ] + }, + { + "streams": [ "Microsoft-OtelPerfMetrics" ], + "destinations": [ "MonitoringAccountDestination" ] + } + ] + } + } + ] + } + }, + "subscriptionId": "[parameters('vmSubscriptionId')]", + "resourceGroup": "[parameters('dcrResourceGroup')]" + }, + { + "comments": "--- Associate DCR with VM ---", + "type": "microsoft.resources/deployments", + "apiVersion": "2021-04-01", + "name": "CreateDCRA", + "dependsOn": [ + "microsoft.resources/deployments/CreateStandardDCR", + "microsoft.resources/deployments/CreatePerProcessDCR" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "Microsoft.Insights/dataCollectionRuleAssociations", + "apiVersion": "2022-06-01", + "name": "VirtualMachineInsightsExtension", + "id": "[variables('dcraResourceId')]", + "properties": { + "description": "Association of data collection rule. Deleting this association will break the data collection for this virtual machine.", + "dataCollectionRuleId": "[variables('dcrResourceId')]" + }, + "scope": "[variables('vmResourceId')]" + } + ] + } + }, + "subscriptionId": "[parameters('vmSubscriptionId')]", + "resourceGroup": "[parameters('vmResourceGroup')]" + }, + { + "comments": "--- Install Azure Monitor Agent extension ---", + "type": "microsoft.resources/deployments", + "apiVersion": "2021-04-01", + "name": "InstallAMAExtension", + "dependsOn": [ + "microsoft.resources/deployments/CreateDCRA", + "microsoft.resources/deployments/EnableVMSystemIdentity" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "microsoft.compute/virtualmachines/extensions", + "apiVersion": "2022-11-01", + "name": "[concat(parameters('vmName'), '/', variables('amaExtensionType'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "Microsoft.Azure.Monitor", + "type": "[variables('amaExtensionType')]", + "typeHandlerVersion": "1.0", + "autoUpgradeMinorVersion": true, + "enableAutomaticUpgrade": true + } + } + ] + } + }, + "subscriptionId": "[parameters('vmSubscriptionId')]", + "resourceGroup": "[parameters('vmResourceGroup')]" + }, + { + "comments": "--- Host alert: VM Availability (platform metric, no UAMI required) ---", + "type": "microsoft.resources/deployments", + "apiVersion": "2021-04-01", + "name": "CreateHostAlertRules", + "condition": "[parameters('enableAlerts')]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "Microsoft.Insights/metricAlerts", + "apiVersion": "2018-03-01", + "name": "[concat('VM Availability - ', parameters('vmName'))]", + "location": "global", + "properties": { + "description": "VM is unavailable or not responding", + "severity": 3, + "enabled": true, + "scopes": [ "[variables('vmResourceId')]" ], + "evaluationFrequency": "PT5M", + "windowSize": "PT5M", + "criteria": { + "odata.type": "Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria", + "allOf": [ + { + "name": "Metric1", + "metricName": "VmAvailabilityMetric", + "metricNamespace": "Microsoft.Compute/virtualMachines", + "operator": "LessThan", + "threshold": 1, + "timeAggregation": "Average", + "criterionType": "StaticThresholdCriterion" + } + ] + }, + "actions": [] + } + } + ] + } + }, + "subscriptionId": "[parameters('vmSubscriptionId')]", + "resourceGroup": "[parameters('vmResourceGroup')]" + }, + { + "comments": "--- Guest OS alerts: CPU, Memory, Disk, Network (PromQL-based, requires UAMI) ---", + "type": "microsoft.resources/deployments", + "apiVersion": "2021-04-01", + "name": "CreateGuestAlertRules", + "condition": "[parameters('enableAlerts')]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "Microsoft.Insights/metricAlerts", + "apiVersion": "2024-03-01-preview", + "name": "[concat('Guest OS CPU Usage - ', parameters('vmName'))]", + "location": "[parameters('location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[parameters('uamiResourceId')]": {} + } + }, + "properties": { + "description": "CPU usage has exceeded 80% threshold over the last 5 minutes", + "severity": 3, + "enabled": true, + "scopes": [ "[variables('vmResourceId')]" ], + "evaluationFrequency": "PT1M", + "criteria": { + "odata.type": "Microsoft.Azure.Monitor.PromQLCriteria", + "allOf": [ + { + "name": "Metric1", + "query": "avg_over_time(((sum (irate({\"system.cpu.time\",\"state\" !~ \"idle|iowait|steal\"}[2m]))) / (sum (irate({\"system.cpu.time\"}[2m]))))[5m:]) * 100 > 80", + "criterionType": "StaticThresholdCriterion" + } + ], + "failingPeriods": { "for": "PT2M" } + }, + "resolveConfiguration": { + "autoResolved": true, + "timeToResolve": "PT2M" + }, + "actions": [] + } + }, + { + "type": "Microsoft.Insights/metricAlerts", + "apiVersion": "2024-03-01-preview", + "name": "[concat('Guest OS Memory Usage - ', parameters('vmName'))]", + "location": "[parameters('location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[parameters('uamiResourceId')]": {} + } + }, + "properties": { + "description": "Available memory has dropped below 1 GB over the last 5 minutes", + "severity": 3, + "enabled": true, + "scopes": [ "[variables('vmResourceId')]" ], + "evaluationFrequency": "PT1M", + "criteria": { + "odata.type": "Microsoft.Azure.Monitor.PromQLCriteria", + "allOf": [ + { + "name": "Metric1", + "query": "min_over_time((sum ({\"system.memory.usage\", state=~\"free|cached|buffered|slab_reclaimable\"}))[5m:]) < (1 * 1024 * 1024 * 1024)", + "criterionType": "StaticThresholdCriterion" + } + ], + "failingPeriods": { "for": "PT2M" } + }, + "resolveConfiguration": { + "autoResolved": true, + "timeToResolve": "PT2M" + }, + "actions": [] + } + }, + { + "type": "Microsoft.Insights/metricAlerts", + "apiVersion": "2024-03-01-preview", + "name": "[concat('Guest OS Disk IOPS - ', parameters('vmName'))]", + "location": "[parameters('location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[parameters('uamiResourceId')]": {} + } + }, + "properties": { + "description": "Disk IOPS has exceeded 5000 operations per second over the last 5 minutes", + "severity": 3, + "enabled": true, + "scopes": [ "[variables('vmResourceId')]" ], + "evaluationFrequency": "PT1M", + "criteria": { + "odata.type": "Microsoft.Azure.Monitor.PromQLCriteria", + "allOf": [ + { + "name": "Metric1", + "query": "max_over_time((sum (irate({\"system.disk.operations\"}[2m])))[5m:]) > 5000", + "criterionType": "StaticThresholdCriterion" + } + ], + "failingPeriods": { "for": "PT2M" } + }, + "resolveConfiguration": { + "autoResolved": true, + "timeToResolve": "PT2M" + }, + "actions": [] + } + }, + { + "type": "Microsoft.Insights/metricAlerts", + "apiVersion": "2024-03-01-preview", + "name": "[concat('Guest OS Network In - ', parameters('vmName'))]", + "location": "[parameters('location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[parameters('uamiResourceId')]": {} + } + }, + "properties": { + "description": "Total network inbound traffic has exceeded 100 GB over the last day", + "severity": 3, + "enabled": true, + "scopes": [ "[variables('vmResourceId')]" ], + "evaluationFrequency": "PT1M", + "criteria": { + "odata.type": "Microsoft.Azure.Monitor.PromQLCriteria", + "allOf": [ + { + "name": "Metric1", + "query": "sum_over_time((sum (irate({\"system.network.io\", direction=\"receive\"}[2m])))[1d:]) > (100 * 1024 * 1024 * 1024)", + "criterionType": "StaticThresholdCriterion" + } + ], + "failingPeriods": { "for": "PT2M" } + }, + "resolveConfiguration": { + "autoResolved": true, + "timeToResolve": "PT2M" + }, + "actions": [] + } + }, + { + "type": "Microsoft.Insights/metricAlerts", + "apiVersion": "2024-03-01-preview", + "name": "[concat('Guest OS Network Out - ', parameters('vmName'))]", + "location": "[parameters('location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[parameters('uamiResourceId')]": {} + } + }, + "properties": { + "description": "Total network outbound traffic has exceeded 50 GB over the last day", + "severity": 3, + "enabled": true, + "scopes": [ "[variables('vmResourceId')]" ], + "evaluationFrequency": "PT1M", + "criteria": { + "odata.type": "Microsoft.Azure.Monitor.PromQLCriteria", + "allOf": [ + { + "name": "Metric1", + "query": "sum_over_time((sum (irate({\"system.network.io\", direction=\"transmit\"}[2m])))[1d:]) > (50 * 1024 * 1024 * 1024)", + "criterionType": "StaticThresholdCriterion" + } + ], + "failingPeriods": { "for": "PT2M" } + }, + "resolveConfiguration": { + "autoResolved": true, + "timeToResolve": "PT2M" + }, + "actions": [] + } + }, + { + "type": "Microsoft.Insights/metricAlerts", + "apiVersion": "2024-03-01-preview", + "name": "[concat('Guest OS Network Errors - ', parameters('vmName'))]", + "location": "[parameters('location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[parameters('uamiResourceId')]": {} + } + }, + "properties": { + "description": "Network errors have exceeded 10 total errors over the last 5 minutes", + "severity": 3, + "enabled": true, + "scopes": [ "[variables('vmResourceId')]" ], + "evaluationFrequency": "PT1M", + "criteria": { + "odata.type": "Microsoft.Azure.Monitor.PromQLCriteria", + "allOf": [ + { + "name": "Metric1", + "query": "sum_over_time((sum (irate({\"system.network.errors\"}[2m])))[5m:]) > 10", + "criterionType": "StaticThresholdCriterion" + } + ], + "failingPeriods": { "for": "PT2M" } + }, + "resolveConfiguration": { + "autoResolved": true, + "timeToResolve": "PT2M" + }, + "actions": [] + } + }, + { + "type": "Microsoft.Insights/metricAlerts", + "apiVersion": "2024-03-01-preview", + "name": "[concat('Guest OS Disk Operation Time - ', parameters('vmName'))]", + "location": "[parameters('location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[parameters('uamiResourceId')]": {} + } + }, + "properties": { + "description": "Average disk operation time has exceeded 100ms over the last 5 minutes", + "severity": 3, + "enabled": true, + "scopes": [ "[variables('vmResourceId')]" ], + "evaluationFrequency": "PT1M", + "criteria": { + "odata.type": "Microsoft.Azure.Monitor.PromQLCriteria", + "allOf": [ + { + "name": "Metric1", + "query": "avg_over_time(((sum (irate({\"system.disk.operation_time\"}[2m]))) / (sum (irate({\"system.disk.operations\"}[2m]))))[5m:]) * 1000 > 100", + "criterionType": "StaticThresholdCriterion" + } + ], + "failingPeriods": { "for": "PT2M" } + }, + "resolveConfiguration": { + "autoResolved": true, + "timeToResolve": "PT2M" + }, + "actions": [] + } + } + ] + } + }, + "subscriptionId": "[parameters('vmSubscriptionId')]", + "resourceGroup": "[parameters('vmResourceGroup')]" + } + ] +}