This article is a continuation of my previous post, where I deployed CPU quota usage alerts for a subscription using Azure ARM templates. In this post, I'll demonstrate how to deploy Action Groups and Subscription Quota Alerts for CPU usage using Bicep.
Compared to ARM templates, I find Bicep to be more user-friendly, intuitive, and concise. If you're familiar with Terraform, you'll find Azure Bicep easy to pick up, as there are many similarities between the two.
Below is my Biceps code to configure and deploy Action Group with Scheduled query rule (Quota Alert).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
@description('The subscription ID to use in the query.') param subscriptionId string // no parameter @description('The name of the action group to be created.') param actionGroupName string = 'Action_Group_01' @description('The short name of the action group.') param actionGroupShortName string = 'AG01' @description('Email address for alerts.') param emailAddress string = '[email protected]' @description('The name of the quota alert to be created.') param quotaAlertName string = 'Quota_Alert_01' @description('The user-managed identity resource ID.') param userManagedIdentity string = 'dev' // @description('The scopes for the scheduled query rules.') // param scopes string = '/subscriptions/9Exxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' @description('The dimension type for the query.') param dimensionsType string = 'microsoft.compute/locations/usages' // @description('The dimension location for the query.') // param dimensionsLocation string = 'East US' @description('The dimension quota name for the query.') param dimensionsQuotaName string = 'cores' /////////////////////////////////////////// var rgInfo = resourceGroup() var scopeInfo = '/subscriptions/${subscriptionId}' /////////////////////////////////////////// resource userAssignedIdentityInfo 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { name: userManagedIdentity } /////////////////////////////////////////// resource actionGroup 'microsoft.insights/actionGroups@2023-09-01-preview' = { name: actionGroupName location: 'Global' properties: { groupShortName: actionGroupShortName enabled: true emailReceivers: [ { name: 'EmailAction' emailAddress: emailAddress useCommonAlertSchema: true } ] smsReceivers: [] webhookReceivers: [] eventHubReceivers: [] itsmReceivers: [] azureAppPushReceivers: [] automationRunbookReceivers: [] voiceReceivers: [] logicAppReceivers: [] azureFunctionReceivers: [] armRoleReceivers: [ { name: 'EmailARMRole' roleId: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635' useCommonAlertSchema: true } ] } } resource scheduledQueryRule 'microsoft.insights/scheduledqueryrules@2023-03-15-preview' = { name: quotaAlertName location: rgInfo.location identity: { type: 'UserAssigned' userAssignedIdentities: { '${userAssignedIdentityInfo.id}': {} } } properties: { severity: 4 enabled: true evaluationFrequency: 'PT15M' scopes: [ scopeInfo ] windowSize: 'PT15M' criteria: { allOf: [ { query: format(''' arg("").QuotaResources | where subscriptionId =~ '{0}' | where type =~ 'microsoft.compute/locations/usages' | where isnotempty(properties) | mv-expand propertyJson = properties.value limit 400 | extend usage = propertyJson.currentValue, quota = propertyJson['limit'], quotaName = tostring(propertyJson['name'].value) | extend usagePercent = toint(usage)*100 / toint(quota) | project-away properties | where location in~ ('{1}') | where quotaName in~ ('{2}') ''', subscriptionId, rgInfo.location, dimensionsQuotaName) timeAggregation: 'Maximum' metricMeasureColumn: 'usagePercent' dimensions: [ { name: 'type' operator: 'Include' values: [ dimensionsType ] } { name: 'location' operator: 'Include' values: [ rgInfo.location ] } { name: 'quotaName' operator: 'Include' values: [ dimensionsQuotaName ] } ] operator: 'GreaterThanOrEqual' threshold: 80 failingPeriods: { numberOfEvaluationPeriods: 1 minFailingPeriodsToAlert: 1 } } ] } actions: { actionGroups: [ actionGroup.id ] } } } |
It can be deployed using below code with Azure az cli and PowerShell az module.
Check earlier article of Create CPU quota usage alerts for subscription using Azure ARM templates.
az deployment group create ` --resource-group vcloud-lab.com ` --template-file D:\Projects\PowerShell\\subscription_quota_rule\azure_bicep\deploy.bicep ` --parameters ` subscriptionId='9exxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' ` actionGroupName='Action_Group_01' ` actionGroupShortName='AG01' ` emailAddress='[email protected]' ` quotaAlertName='Quota_Alert_01' ` userManagedIdentity='dev' ` dimensionsType='microsoft.compute/locations/usages' ` dimensionsQuotaName='cores' <# $resourceGroupName = "vcloud-lab.com" # Change this to your resource group name #$location = "eastus" # Change this to your desired location $bicepFilePath = "D:\Projects\PowerShell\\subscription_quota_rule\azure_bicep\deploy.bicep" # Change this to the path of your Bicep file # Define parameter values $subscriptionId='9exxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' ` $actionGroupName = "Action_Group_01" $actionGroupShortName = "AG01" $emailAddress = "[email protected]" $quotaAlertName = "Quota_Alert_01" $userManagedIdentity = "dev" $dimensionsType = "microsoft.compute/locations/usages" $dimensionsQuotaName = "virtualMachines" # Deploy the Bicep template New-AzResourceGroupDeployment ` -ResourceGroupName $resourceGroupName ` -TemplateFile $bicepFilePath ` -actionGroupName $actionGroupName ` -actionGroupShortName $actionGroupShortName ` -emailAddress $emailAddress ` -quotaAlertName $quotaAlertName ` -actionGroupId $actionGroupId ` -userManagedIdentity $userManagedIdentity ` -dimensionsType $dimensionsType ` -dimensionsQuotaName $dimensionsQuotaName #>
This the output after executed Bicep code.
Download this entire Azure_Bicep_Subscription_Usage_Quota_Rule.zip here or it is also available on github.com.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
.\subscription_quota_rule> az deployment group create ` >> --resource-group vcloud-lab.com ` >> --template-file D:\Projects\PowerShell\\subscription_quota_rule\azure_bicep\deploy.bicep ` >> --parameters ` >> subscriptionId='9exxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' ` >> actionGroupName='Action_Group_01' ` >> actionGroupShortName='AG01' ` >> emailAddress='[email protected]' ` >> quotaAlertName='Quota_Alert_01' ` >> userManagedIdentity='dev' ` >> dimensionsType='microsoft.compute/locations/usages' ` >> dimensionsQuotaName='cores' A new Bicep release is available: v0.30.23. Upgrade now by running "az bicep upgrade". { "id": "/subscriptions/9exxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Resources/deployments/deploy", "location": null, "name": "deploy", "properties": { "correlationId": "0c9c56d3-40f1-4834-aa6e-7def1287f921", "debugSetting": null, "dependencies": [ { "dependsOn": [ { "id": "/subscriptions/9exxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Insights/actionGroups/Action_Group_01", "resourceGroup": "vcloud-lab.com", "resourceName": "Action_Group_01", "resourceType": "Microsoft.Insights/actionGroups" } ], "id": "/subscriptions/9exxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Insights/scheduledQueryRules/Quota_Alert_01", "resourceGroup": "vcloud-lab.com", "resourceName": "Quota_Alert_01", "resourceType": "Microsoft.Insights/scheduledQueryRules" } ], "duration": "PT18.2135974S", "error": null, "mode": "Incremental", "onErrorDeployment": null, "outputResources": [ { "id": "/subscriptions/9exxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Insights/actionGroups/Action_Group_01", "resourceGroup": "vcloud-lab.com" }, { "id": "/subscriptions/9exxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Insights/scheduledQueryRules/Quota_Alert_01", "resourceGroup": "vcloud-lab.com" } ], "outputs": null, "parameters": { "actionGroupName": { "type": "String", "value": "Action_Group_01" }, "actionGroupShortName": { "type": "String", "value": "AG01" }, "dimensionsQuotaName": { "type": "String", "value": "cores" }, "dimensionsType": { "type": "String", "value": "microsoft.compute/locations/usages" }, "emailAddress": { "type": "String", "value": "[email protected]" }, "quotaAlertName": { "type": "String", "value": "Quota_Alert_01" }, "subscriptionId": { "type": "String", "value": "9exxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }, "userManagedIdentity": { "type": "String", "value": "dev" } }, "parametersLink": null, "providers": [ { "id": null, "namespace": "Microsoft.Insights", "providerAuthorizationConsentState": null, "registrationPolicy": null, "registrationState": null, "resourceTypes": [ { "aliases": null, "apiProfiles": null, "apiVersions": null, "capabilities": null, "defaultApiVersion": null, "locationMappings": null, "locations": [ "global" ], "properties": null, "resourceType": "actionGroups", "zoneMappings": null }, { "aliases": null, "apiProfiles": null, "apiVersions": null, "capabilities": null, "defaultApiVersion": null, "locationMappings": null, "locations": [ "eastus" ], "properties": null, "resourceType": "scheduledQueryRules", "zoneMappings": null } ] } ], "provisioningState": "Succeeded", "templateHash": "6124727542715715474", "templateLink": null, "timestamp": "2024-10-06T15:40:44.138269+00:00", "validatedResources": null }, "resourceGroup": "vcloud-lab.com", "tags": null, "type": "Microsoft.Resources/deployments" } .\subscription_quota_rule> |
Useful Articles
Hashicorp Terraform map and object inside module and variable example
Terraform one module deploy null or multiple resources based on input
Terraform A reference to a resource type must be followed by at least one attribute access, specifying the resource name
Terraform fore_each for loop filter with if condition example
Terraform remote-exec provisioner with ssh connection in null_resource
Terraform count vs for_each for examples with map of objects
Terraform one module deploy null or multiple resources based on input (nested for loop) Example of Terraform functions flatten() and coalesce()
Terraform Azure Create Private Endpoint to existing Storage Account with Custom Private DNS zone record link
Creating a Private Endpoint for Azure Storage Account with required sub services using Terraform Example Terraform functions of lookup() and lower()
Using element function with count meta argument example Terraform Azure subnets Example Terraform functions of element(), count() and sum()
Terraform create Azure Virtual Network subnets from map of object and show name in the header Header name change in the output
Creating a Private Endpoint for Azure Storage Account with Terraform example 2 Example of for_each with toset() function
Creating a Private Endpoint for Azure Storage Account with Terraform example 3