Azure CLI: Azure Monitor Alert 일괄 생성 스크립트 Part.1 az monitor metrics alert

Azure Monitor Alert

이번에 스크립트로 만들 Azure Monitor 의 Alert 종류는 3가지가 있다.

  • 메트릭(Metric)
  • 활동 로그(Activity Log)
  • 스케쥴 쿼리(Scheduled-query)

Azure Policy 를 이용해서, 모든 리소스의 종류별로 동일한 Alert 를 작성하는 방법은 사용할 수 없었다. 왜냐하면, 감시 설정은 추가 비용이 발생하기 때문에 사용자가 원할 때만 특정 리소스에 대해 Aelrt 설정해야 하기 때문이다.

사용자가 감시 설정을 신청하면, Azure Monitor에서 Alert 설정을 해야 하는데, 일반적으로 30가지 이상의 감시 설정을 Azure Portal에서 수동으로 작업하게 된다. 작업을 하다가 ‘내가 지금 뭣 하고 있는거지..’ 라는 생각이 들어서 스크립트를 만들었다.

az monitor metrics alert

준비 하기

https://github.com/jcy9033/azure-cli/tree/master/azureMonitor/metricAlert

  • 스크립트 파일 main.ps1
  • CSV 파일 main.csv

참고용 Azure CLI 명령어

  • az monitor metrics alert condition create
az monitor metrics alert condition create --aggregation {Average, Count, Maximum, Minimum, Total}
                                          --metric
                                          --op {Equals, GreaterOrLessThan, GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual, NotEquals}
                                          --type {dynamic, static}
                                          [--dimension]
                                          [--namespace]
                                          [--num-periods]
                                          [--num-violations]
                                          [--sensitivity {High, Low, Medium}]
                                          [--since]
                                          [--skip-metric-validation {false, true}]
                                          [--threshold]
  • az monitor metrics alert create
az monitor metrics alert create --condition
                                --name
                                --resource-group
                                --scopes
                                [--action]
                                [--auto-mitigate {false, true}]
                                [--description]
                                [--disabled {false, true}]
                                [--evaluation-frequency]
                                [--region]
                                [--severity]
                                [--tags]
                                [--target-resource-type]
                                [--window-size]

CSV 구성 소개

TypeAlertRuleNameSubscriptionResourceGroupSeveritySubscription_UserResourceGroup_UserResourceNameMetricOperatorAggregationThresholdWindowSizeEvaluationFrequencyActionGroupName_1
xx
Sample
  • Type: 동적값 or 정적값 {dynamic, static}, 스크립트에선 Static 값만을 사용
  • AlertRuleName: 생성할 알람 규칙의 이름
  • Subscription: 타겟 리소스가 위치한 구독 및 알람 규칙을 생성할 구독
  • ResourceGroup: 타겟 리소스가 위치한 리소스 그룹 및 알람 규칙을 생성할 리소스 그룹
  • Severity: <0-4> {Severity of the alert from 0 (critical) to 4 (verbose)} default value: 2
  • Subscription_User: *사용되지 않음 (신청서 폼에 맞추기 위한 용도)
  • ResourceGroup_User: *사용되지 않음 (신청서 폼에 맞추기 위한 용도)
  • ResourceName: 타겟 리소스의 이름
  • Metric: 사용 가능한 메트릭 이름을 설정 ex: Percentage CPU
  • Operator
  • Aggregation
  • Threshold
  • WindowSize
  • EvaluationFrequency
  • ActionGroupName_1: 할당할 작업 그룹의 이름 *여러 작업 그룹을 할당할 경우, ActionGroupName_n 열을 추가

사용 가능한 메트릭 이름을 확인하기 ‘az monitor metrics list-definitions’

# VM에 사용가능한 Metric name을 확인하고 싶은 경우
az vm list --query "[].id" -o tsv

$resourceId='your resource id'
$resourceGroup='your resource group name'

$metricsList = az monitor metrics list-definitions --resource $resourceId --resource-group $resourceGroup --query "[].name" -o table

$metricsList

Script 구성 소개

CSV 파일 경로 및 가져 오기

# Please enter the file path for the CSV
$csvPath = ""

$csvData = Import-Csv $csvPath -Encoding UTF8

$csvData | ForEach-Object {

작성한 CSV 파일의 경로를 지정하고, $csvData 변수에 값을 저장한다.

ForEach-Object 를 이용하여, 각 행의 값을 순차적으로 처리한다.

Subscription 확인 하기

  #----------------------------------------- Subscription check
  
  $TargetSubscription = $_.Subscription
  $ActiveSubscription = az account show --query name -o tsv

  if ($ActiveSubscription -eq $TargetSubscription) {
    Write-Host "---> Already on the target subscription: $TargetSubscription `n"
  }
  else {
    az account set --subscription $TargetSubscription
    Write-Host "---> Switched to the target subscription: $TargetSubscription `n"
  }

Active Subscription을 확인한다. CSV에 기입된 값과 다른 경우, CSV 값으로 Subscription 을 변경한다.

Action groups id 값 가져 오기

  #----------------------------------------- Action Group
  
  $ActionParams = @()
  $i = 1
  while ($true) {
    $ActionGroupNameProperty = "ActionGroupName_$i"
    
    if ($_.PSObject.Properties.Name -contains $ActionGroupNameProperty) {
      $ActionGroupName = $_.$ActionGroupNameProperty
      Write-Host "---> ActionGroupName_$i is set to: $ActionGroupName"
      $ActionGroupJson = az graph query -q "Resources | where type == 'microsoft.insights/actiongroups' and name has '$ActionGroupName' | project id" | ConvertFrom-Json
      
      if ($ActionGroupJson.data -and $ActionGroupJson.data.Count -gt 0) {
        $ActionGroupId = $ActionGroupJson.data[0].id
        $ActionParams += "--action", "$ActionGroupId"
      }
      else {
        Write-Host "---> No valid action group ID found for $ActionGroupName"
        break
      }
    }
    else {
      Write-Host "---> No more action groups to process for this object."
      break
    }
    $i++
  }

CSV에 직접 Action group (작업 그룹)의 ID를 지정해도 되지만, 귀찮아서 그냥 Azrue CLI로 해당 ID값을 찾도록 코드를 수정했다.

$ActionGroupJson = az graph query -q "Resources | where type == 'microsoft.insights/actiongroups' and name has '$ActionGroupName' | project id" | ConvertFrom-Json

Tip. 다른 구독에 Action group이 존재하는 경우에 대비하여, az graph query 를 사용한다.

Resource id 값 가져 오기

  #----------------------------------------- Resource parameters

  $ResourceName = $_.ResourceName
  
  $Scopes = (az resource list --query "[?name=='$ResourceName'].id" --output tsv).Trim()
  
  Write-Host "---> Resource scopes: $Scopes `n"

메트릭 규칙을 생성할 때, 해당 리소스만 범위에 지정하기 위해서 (지정하지 않는 경우 구독 및 리소스 그룹 전체가 범위로 지정된다.) Resource id 값을 가져 와야 한다.

Metric condition 값 작성 하기

  #----------------------------------------- Metric conditions
  
  $Condition = (az monitor metrics alert condition create --output tsv `
      --aggregation $_.Aggregation `
      --metric $_.Metric `
      --operator $_.Operator `
      --type $_.Type `
      --threshold $_.Threshold | Out-String).Trim()
  
  Write-Host "---> Metric alert condition: $Condition"

아직 Preview 의 명령어지만 사용해 봤다.

CSV에 기입한 값을 토대로 az monitor metrics alert create--condition 에 사용할 값(String)을 작성한다.

Metric alert 작성 하기

  #----------------------------------------- Create metric alert
  
  az monitor metrics alert create --name $_.AlertRuleName --resource-group $_.ResourceGroup --scopes $Scopes `
    --severity $_.Severity `
    --condition $Condition `
    $ActionParams `
    --auto-mitigate true `
    --evaluation-frequency $_.EvaluationFrequency `
    --window-size $_.WindowSize
}

CSV 및 위에서 지정한 값을 사용하여 메트릭 알람 규칙을 생성한다.

Script 실행 결과

PS C:\Users\cchi9\OneDrive\Vscode\azure-cli\azureMonitor\metricAlert> .\main.ps1
---> Already on the target subscription: Azure subscription 2
---> ActionGroupName_1 is set to: ag-1
---> ActionGroupName_2 is set to: ag-2
---> ActionGroupName_3 is set to: ag-3
---> No more action groups to process for this object.
---> Resource scopes: /subscriptions/0b5f5005-c30c-4a28-89c1-9457d0cd5e0f/resourceGroups/system-1/providers/Microsoft.Compute/virtualMachines/AZRWIN-1

WARNING: This command is in preview and under development. Reference and support levels: https://aka.ms/CLI_refstatus
---> Metric alert condition: avg 'Percentage CPU' >= 90.0
{
  "actions": [
    {
      "actionGroupId": "/subscriptions/611a7ed8-17fa-480a-901d-d7084803c376/resourceGroups/core-1/providers/microsoft.insights/actiongroups/ag-1"
    },
    {
      "actionGroupId": "/subscriptions/611a7ed8-17fa-480a-901d-d7084803c376/resourceGroups/core-1/providers/microsoft.insights/actiongroups/ag-2"
    },
    {
      "actionGroupId": "/subscriptions/611a7ed8-17fa-480a-901d-d7084803c376/resourceGroups/core-1/providers/microsoft.insights/actiongroups/ag-3"
    }
  ],
  "autoMitigate": true,
  "criteria": {
    "allOf": [
      {
        "criterionType": "StaticThresholdCriterion",
        "metricName": "Percentage CPU",
        "name": "cond0",
        "operator": "GreaterThanOrEqual",
        "threshold": 90.0,
        "timeAggregation": "Average"
      }
    ],
    "odata.type": "Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria"
  },
  "enabled": true,
  "evaluationFrequency": "PT1M",
  "id": "/subscriptions/0b5f5005-c30c-4a28-89c1-9457d0cd5e0f/resourceGroups/system-1/providers/Microsoft.Insights/metricAlerts/script_20231231",
  "location": "global",
  "name": "script_20231231",
  "resourceGroup": "system-1",
  "scopes": [
    "/subscriptions/0b5f5005-c30c-4a28-89c1-9457d0cd5e0f/resourceGroups/system-1/providers/Microsoft.Compute/virtualMachines/AZRWIN-1"
  ],
  "severity": 1,
  "type": "Microsoft.Insights/metricAlerts",
  "windowSize": "PT5M"
}

..SKIP