Introduction
I found it rather difficult to create an alert rule using PowerShell as opposed to using Azure CLI. That's why I thought it is worth a post.
In the following tiny howto, we are going to create an alert that gets triggered when the average CPU load of a virtual machine stays above 90% for a duration of 5 minutes. I assume there exists a resource group called rg-training
and a virtual machine named VM1
.
In general, an alert rule consists of the following components.
Component | Description |
---|---|
Scope | The resource(s) you want to monitor |
Condition | Configures when the alert rule should trigger the action |
Action Group | A list of actions to invoke when the alert rule triggers (optional) |
Alert Rule Details | Some identification information |
Azure CLI
First, we need to create an action group that we later are going to use with the alert rule. This rule will send an email to defined recipients upon the rule triggers.
# Create an action group
az monitor action-group create \
--name notify-admins \
--resource-group rg-training \
--action email my-action-name [email protected]
Have a look at az monitor action-group create -h
for further actions that are available. For example you can also send out an SMS, trigger a webhook and so on.
Then we need to retrieve the ID of the virtual machine and store it for later use...
# Retrieve VM identifier used for scope parameter
$scope = az vm show \
--name vm1 \
--output tsv \
--query id
Finally, we create a metric alert, that will trigger when the average CPU load stays above 90% for a duration of 5 minutes (measured once per minute).
# Create the actual alert
az monitor metrics alert create \
--name alert2 \
--resource-group rg-training \
--scopes $scope \
--condition "avg Percentage CPU > 90" \
--window-size 5m \
--evaluation-frequency 1m \
--action notify-admins \
--description "High CPU"
That was easy. Now let's have a look at the PowerShell variant, where things are a bit more complicated and long-winded.
Azure PowerShell
First, we need to create an action group receiver object and an action group.
# Creates an new action group receiver object in memory
$receiver = New-AzActionGroupReceiver `
-Name "Admin" `
-EmailAddress "[email protected]"
# Creates a new or updates an existing action group.
$actionGroup = Set-AzActionGroup `
-Name "notify-admins" `
-ShortName "ActionGroup1" `
-ResourceGroupName "rg-training" `
-Receiver $receiver
Have a look at the official documentation for further receivers that can be configured.
Now let's read back the action group and store it in a variable.
# Creates an ActionGroup reference object in memory.
$actionGroupId = New-AzActionGroup -ActionGroupId $actionGroup.Id
$actionGroupId
will hold an object of typeActivityLogAlertActionGroup
that is later required for theAdd-AzMetricAlertRuleV2
cmdlet.
Okay great! now we need a condition.
# Creates a local criteria object that can be used to create a new metric alert
$condition = New-AzMetricAlertRuleV2Criteria `
-MetricName "Percentage CPU" `
-TimeAggregation Average `
-Operator GreaterThan `
-Threshold 0.1
And finally, we can put all the pieces together and call Add-AzMetricAlertRuleV2
as follows.
$windowSize = New-TimeSpan -Minutes 1
$frequency = New-TimeSpan -Minutes 1
$targetResourceId = (Get-AzResource -Name VM1).ResourceId
# Adds or updates a V2 (non-classic) metric-based alert rule.
Add-AzMetricAlertRuleV2 `
-Name "metricRule" `
-ResourceGroupName "rg-training" `
-WindowSize $windowSize `
-Frequency $frequency `
-TargetResourceId $targetResourceId `
-Condition $condition `
-ActionGroup $actionGroupId `
-Severity 3
If Add-AzMetricAlertRuleV2
throws an exception at you like the one below, then make sure you are using the correct metric name.
Add-AzMetricAlertRuleV2: Exception type: ErrorResponseException, Message: Couldn't find a metric named <some_metric_you_entered>. Make sure the name is correct. Activity ID: <some-guid>., Code: BadRequest, Status code:BadRequest, Reason phrase: BadRequest
You can look up the correct metric names by issuing the cmdlet below. Make sure you replace the metric namespace with the resource type and ID of your choice.
# Gets metric definitions
$validMetrics = Get-AzMetricDefinition `
-MetricNamespace "Microsoft.Compute/virtualMachine" `
-ResourceId $targetResourceId)
# Get the values
$validMetrics.Name
Or alternatively, look them up in the documentation 😉That's it for today. I hope you enjoyed this post. Happy hacking! 😎