0

I have 2 Linux VM in my RG connected to Log-Analytics workspace (Refer below Hierarchy)

Scope-Dev

->Resource-Group-Dev

--->VM-Dev-1

--->VM-Dev-2

I want to create Alert Rule with below options using Terraform ;

  • Scope : All virtual machines under Resource-Group-Dev

  • Condition : Log query written in KQL (Pasted below)

  • dimensions : Computer(Result from KQL query) which i will be using it from action group.

        Pref | where TimeGenerated > ago(60m) | where (ObjectName == "Processor") | summarize AggregatedValue = avg(CounterValue) by Computer , _ResourceId | where AggregatedValue < 100 | project Computer, AggregatedValue , _ResourceId
    
praveen
  • 179
  • 1
  • 3
  • 16

2 Answers2

0

Here i have used azurerm_monitor_scheduled_query_rules_alert_v2 and selected scope as log-analytics-workspace where my VM got connected.As a result it worked.

  provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "example" {
  name     = "Resource-Group-Dev"
  location = "West Europe"
}

resource "azurerm_log_analytics_workspace" "log_analytics_workspace" {
  name                = "log-analytics-workspace-custom"
  location            = "West Europe"
  resource_group_name = azurerm_resource_group.example.name
  sku                 = "PerGB2018"
  retention_in_days   = 30
}

resource "azurerm_monitor_scheduled_query_rules_alert_v2" "alert_v2" {
  name                = "cpu-alertv2"
  resource_group_name = azurerm_resource_group.example.name
  location            = "West Europe"

  evaluation_frequency = "PT5M"
  window_duration      = "PT5M"
  scopes               = [azurerm_log_analytics_workspace.log_analytics_workspace.id]
  severity             = 4
  criteria {
    query                   = <<-QUERY
        Perf
        | where TimeGenerated > ago(1h)
        | where CounterName == "% Processor Time" and InstanceName == "_Total" 
        | project TimeGenerated, Computer, CounterValue, _ResourceId
        | summarize AggregatedValue = avg(CounterValue)  by bin(TimeGenerated, 1h), Computer, _ResourceId   
      QUERY
    time_aggregation_method = "Maximum"
    threshold               = 99.0
    operator                = "LessThan"

    resource_id_column    = "_ResourceId"
    metric_measure_column = "AggregatedValue"
    dimension {
      name     = "Computer"
      operator = "Include"
      values   = ["*"]
    }
    failing_periods {
      minimum_failing_periods_to_trigger_alert = 1
      number_of_evaluation_periods             = 1
    }
  }

  auto_mitigation_enabled          = false
  workspace_alerts_storage_enabled = false
  description                      = "This is V2 custom log alert"
  display_name                     = "cpu-alertv2"
  enabled                          = true
  query_time_range_override        = "P2D" 
  skip_query_validation            = false
  action {
    action_groups =  [azurerm_monitor_action_group.delete_dsvm_action.id]
  }
  # custom_properties = {}
  tags = {
  }
}

resource "azurerm_monitor_action_group" "delete_dsvm_action" {
  name                = "delete-vm-action"
  resource_group_name = azurerm_resource_group.example.name
  short_name          = "destoy-vm"

  logic_app_receiver {
    name                    = "auto-deletion-logicapp"
    resource_id             = azurerm_logic_app_workflow.auto_deletion_logicapp.id
    callback_url            = azurerm_logic_app_workflow.auto_deletion_logicapp.access_endpoint
    use_common_alert_schema = true
  }

  email_receiver {
    name                    = "sendtoPraveen"
    email_address           = "kumarpraveen@meta.gov.org"
    use_common_alert_schema = true
  }

}

resource "azurerm_logic_app_workflow" "auto_deletion_logicapp" {
  name                = "auto-deletion-logicapp"
  location            = "East US 2"
  resource_group_name = azurerm_resource_group.example.name
}


variable "prefix" {
  default = "tfvmex"
}
resource "azurerm_virtual_network" "main" {
  name                = "${var.prefix}-network"
  address_space       = ["10.2.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_subnet" "internal" {
  name                 = "internal"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = ["10.2.2.0/24"]
}

resource "azurerm_network_interface" "main" {
  name                = "${var.prefix}-nic"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name

  ip_configuration {
    name                          = "testconfiguration1"
    subnet_id                     = azurerm_subnet.internal.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_virtual_machine" "main" {
  name                  = "VM-Dev-1"
  location              = azurerm_resource_group.example.location
  resource_group_name   = azurerm_resource_group.example.name
  network_interface_ids = [azurerm_network_interface.main.id]
  vm_size               = "Standard_DS1_v2"

  storage_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "16.04-LTS"
    version   = "latest"
  }
  storage_os_disk {
    name              = "myosdisk1"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }
  os_profile {
    computer_name  = "hostname"
    admin_username = "testadmin"
    admin_password = "Password1234!"
  }
  os_profile_linux_config {
    disable_password_authentication = false
  }
  tags = {
    environment = "dev1"
  }
}

//VM2

resource "azurerm_virtual_network" "main2" {
  name                = "${var.prefix}-network2"
  address_space       = ["10.1.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_subnet" "internal2" {
  name                 = "internal"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.main2.name
  address_prefixes     = ["10.1.2.0/24"]
}

resource "azurerm_network_interface" "main2" {
  name                = "${var.prefix}-nic2"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name

  ip_configuration {
    name                          = "testconfiguration2"
    subnet_id                     = azurerm_subnet.internal2.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_virtual_machine" "main2" {
  name                  = "VM-Dev-2"
  location              = azurerm_resource_group.example.location
  resource_group_name   = azurerm_resource_group.example.name
  network_interface_ids = [azurerm_network_interface.main2.id]
  vm_size               = "Standard_DS1_v2"

  storage_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "16.04-LTS"
    version   = "latest"
  }
  storage_os_disk {
    name              = "myosdisk2"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }
  os_profile {
    computer_name  = "hostname1"
    admin_username = "testadmin2"
    admin_password = "Password123!"
  }
  os_profile_linux_config {
    disable_password_authentication = false
  }
  tags = {
    environment = "dev2"
  }

For setting : For setting complex Logic App using Terraform

praveen
  • 179
  • 1
  • 3
  • 16
-1

Replicated the requested change via terraform. Here is a code snippet for adding the KPL query using the Terraform implementation.

**NOTE: The query snippet mentioned is invalid; we can review it on the Azure portal before applying. Got to Application Insights -> Logs [Monitor] -> Click on any query and validate before implement. **

enter image description here

Step1: Insert the following code into the main tf file. added a sample query for testing via Terraform.

  provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "example" {
  name     = "Resource-Group-Dev"
  location = "West Europe"
}

resource "azurerm_application_insights" "example" {
  name                = "appinsights"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  application_type    = "web"
}

resource "azurerm_monitor_scheduled_query_rules_alert" "example" {
  name                = "examplealert"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name

action {
    action_group           = []
    email_subject          = "Email Header"
    custom_webhook_payload = "{}"
  }
  data_source_id = azurerm_application_insights.example.id
  description    = "Alert when total results cross threshold"
  enabled        = true
   query = format(<<-QUERY
  let a=requests
    | where toint(resultCode) >= 500
    | extend fail=1; let b=app('%s').requests
    | where toint(resultCode) >= 500 | extend fail=1; a
    | join b on fail
QUERY
  , azurerm_application_insights.example.id)
  severity    = 1
  frequency   = 5
  time_window = 30
  trigger {
    operator  = "GreaterThan"
    threshold = 3
  }
}
variable "prefix" {
  default = "tfvmex"
}
resource "azurerm_virtual_network" "main" {
  name                = "${var.prefix}-network"
  address_space       = ["10.2.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_subnet" "internal" {
  name                 = "internal"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = ["10.2.2.0/24"]
}

resource "azurerm_network_interface" "main" {
  name                = "${var.prefix}-nic"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name

  ip_configuration {
    name                          = "testconfiguration1"
    subnet_id                     = azurerm_subnet.internal.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_virtual_machine" "main" {
  name                  = "VM-Dev-1"
  location              = azurerm_resource_group.example.location
  resource_group_name   = azurerm_resource_group.example.name
  network_interface_ids = [azurerm_network_interface.main.id]
  vm_size               = "Standard_DS1_v2"

  storage_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "16.04-LTS"
    version   = "latest"
  }
  storage_os_disk {
    name              = "myosdisk1"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }
  os_profile {
    computer_name  = "hostname"
    admin_username = "testadmin"
    admin_password = "Password1234!"
  }
  os_profile_linux_config {
    disable_password_authentication = false
  }
  tags = {
    environment = "dev1"
  }
}

//VM2

resource "azurerm_virtual_network" "main2" {
  name                = "${var.prefix}-network2"
  address_space       = ["10.1.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_subnet" "internal2" {
  name                 = "internal"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.main2.name
  address_prefixes     = ["10.1.2.0/24"]
}

resource "azurerm_network_interface" "main2" {
  name                = "${var.prefix}-nic2"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name

  ip_configuration {
    name                          = "testconfiguration2"
    subnet_id                     = azurerm_subnet.internal2.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_virtual_machine" "main2" {
  name                  = "VM-Dev-2"
  location              = azurerm_resource_group.example.location
  resource_group_name   = azurerm_resource_group.example.name
  network_interface_ids = [azurerm_network_interface.main2.id]
  vm_size               = "Standard_DS1_v2"

  storage_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "16.04-LTS"
    version   = "latest"
  }
  storage_os_disk {
    name              = "myosdisk2"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }
  os_profile {
    computer_name  = "hostname1"
    admin_username = "testadmin2"
    admin_password = "Password123!"
  }
  os_profile_linux_config {
    disable_password_authentication = false
  }
  tags = {
    environment = "dev2"
  }
}

Step2: Execute below commands

terraform plan 

enter image description here

terraform apply -auto-approve

enter image description here

enter image description here

Verification from the portal enter image description here

enter image description here

Hope this helps!

Swarna Anipindi
  • 792
  • 2
  • 9
  • My goal is to create alert for all VM(s) on targeted Resource Group. Where Alert’s signal is Custom log search (written in KQL for get average CPU usage as mentioned in above query) – praveen Dec 06 '22 at 15:36