Menu

Virtual Geek

Tales from real IT system administrators world and non-production environment

Configure CPU quota usage alerts for subscription using Azure Bicep templates

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.

Azure Biceps create usage alert rule subscription vcpu region location alert rule name provider compute threshold severity frequency of evaluation resource gorup managed identity user email rule action.png

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

Go Back

Comment

Blog Search

Page Views

12146662

Follow me on Blogarama