共用方式為


教學:利用 Azure 函式建立維護前與維護後事件

適用於:✔️ Windows VM ✔️ Linux VM ✔️ 內部部署環境 ✔️ Azure VMs ✔️ 已啟用 Azure Arc 的伺服器。

本教學說明如何利用 Azure Functions 建立預備與維護後事件,以啟動與停止排程修補程式工作流程中的虛擬機(VM)。

在本教學課程中,您會了解如何:

  • 建立函式應用程式。
  • 建立一個函式。
  • 建立活動訂閱。

先決條件

  1. 請確保你使用的是 PowerShell 7.4 的作業手冊。

  2. 將權限指派給適當的受控識別。 Runbook 可以使用自動化帳戶的系統指派受控識別或使用者指派的受控識別。

    以下腳本範例(啟動與停止虛擬機)需要虛擬機貢獻者角色或具備以下特定權限的自訂角色:

    • Microsoft.Compute/virtualMachines/start/action
    • Microsoft.Compute/virtualMachines/deallocate/action
    • Microsoft.Compute/virtualMachines/restart/action
    • Microsoft.Compute/virtualMachines/powerOff/action

    你可以使用 Azure 入口網站或 Azure PowerShell cmdlets 來為每個身份分配權限:

    要指派權限,請依照 使用 Azure 入口網站的「指派 Azure 角色」步驟操作。


  1. 匯入模組 Az.ResourceGraph 。 確保模組已更新為 ThreadJob,模組版本為 2.0.3。

建立函數應用程式

  1. 請依照步驟 建立一個函式應用程式

  2. 請前往資源,並按照以下步驟載入相依項目。

    附註

    你必須第一次載入相依性。 如果 PowerShell 相依性無法載入,請檢查 AzAz.ResourceGraph 的最新版本。

    1. 功能應用程式中,選擇 應用程式檔案

    2. host.json下,將 ManagedDependecy為 True ,並選擇 requirements.psd1

    3. requirements.psd1 中,貼上以下程式碼:

      @{
      'Az'='12.*' 
      'Az.ResourceGraph'='1.0.0' 
      'Az.Resources'='6.*' 
      'ThreadJob' = '2.*'
      }
      
    4. 選取 [儲存]

  3. 從 [概觀] 索引標籤重新啟動函式應用程式,以載入 requirements.psd1 檔案中所提及的相依性。

建立函式

  1. 建立函式應用程式後,前往資源,進入 總覽,然後選擇 在 Azure 入口網站中建立

  2. 「建立功能 」面板中,請做出以下選擇:

    1. 選擇開發環境中,對於 開發環境,請選擇 入口網站中的開發

    2. 選擇範本中,選擇 事件網格

    3. 範本細節中,新增 函式,選擇名稱。 然後選擇 [建立]

      截圖顯示建立函式的選項。

  3. 事件格子功能 面板中,從左側選單選擇 Code+Test 。 貼上以下程式碼,然後選擇 儲存

    # Make sure that you're using eventGridEvent for parameter binding in the Azure function.
    param($eventGridEvent, $TriggerMetadata)
    
    Connect-AzAccount -Identity
    
    # Install the Resource Graph module from PowerShell Gallery
    # Install-Module -Name Az.ResourceGraph
    
    $maintenanceRunId = $eventGridEvent.data.CorrelationId
    $resourceSubscriptionIds = $eventGridEvent.data.ResourceSubscriptionIds
    
    if ($resourceSubscriptionIds.Count -eq 0) {
        Write-Output "Resource subscriptions are not present."
        break
    }
    
    Write-Output "Querying ARG to get machine details [MaintenanceRunId=$maintenanceRunId][ResourceSubscriptionIdsCount=$($resourceSubscriptionIds.Count)]"
    
    $argQuery = @"
        maintenanceresources 
        | where type =~ 'microsoft.maintenance/applyupdates'
        | where properties.correlationId =~ '$($maintenanceRunId)'
        | where id has '/providers/microsoft.compute/virtualmachines/'
        | project id, resourceId = tostring(properties.resourceId)
        | order by id asc
    "@
    
    Write-Output "Arg Query Used: $argQuery"
    
    $allMachines = [System.Collections.ArrayList]@()
    $skipToken = $null
    
    do
    {
        $res = Search-AzGraph -Query $argQuery -First 1000 -SkipToken $skipToken -Subscription $resourceSubscriptionIds
        $skipToken = $res.SkipToken
        $allMachines.AddRange($res.Data)
    } while ($skipToken -ne $null -and $skipToken.Length -ne 0)
    if ($allMachines.Count -eq 0) {
        Write-Output "No Machines were found."
        break
    }
    
    $jobIDs= New-Object System.Collections.Generic.List[System.Object]
    $startableStates = "stopped" , "stopping", "deallocated", "deallocating"
    
    $allMachines | ForEach-Object {
        $vmId =  $_.resourceId
    
        $split = $vmId -split "/";
        $subscriptionId = $split[2]; 
        $rg = $split[4];
        $name = $split[8];
    
        Write-Output ("Subscription Id: " + $subscriptionId)
    
        $mute = Set-AzContext -Subscription $subscriptionId
        $vm = Get-AzVM -ResourceGroupName $rg -Name $name -Status -DefaultProfile $mute
    
        $state = ($vm.Statuses[1].DisplayStatus -split " ")[1]
        if($state -in $startableStates) {
            Write-Output "Starting '$($name)' ..."
    
            $newJob = Start-ThreadJob -ScriptBlock { param($resource, $vmname, $sub) $context = Set-AzContext -Subscription $sub; Start-AzVM -ResourceGroupName $resource -Name $vmname -DefaultProfile $context} -ArgumentList $rg, $name, $subscriptionId
            $jobIDs.Add($newJob.Id)
        } else {
            Write-Output ($name + ": no action taken. State: " + $state) 
        }
    }
    
    $jobsList = $jobIDs.ToArray()
    if ($jobsList)
    {
        Write-Output "Waiting for machines to finish starting..."
        Wait-Job -Id $jobsList
    }
    
    foreach($id in $jobsList)
    {
        $job = Get-Job -Id $id
        if ($job.Error)
        {
            Write-Output $job.Error
        }
    }
    
  4. 在左側選單中,選擇 整合。 對於 Trigger,請輸入 Event Trigger 參數名稱 值。 使用 [程式碼+測試] 視窗中指定的相同參數名稱。 在範例中,參數為 eventGridEvent

    截圖顯示輸入事件觸發器參數名稱的過程。

  5. 選取 [儲存]

建立事件訂閱

  1. 登入 [Azure 入口網站],然後移至 [Azure 更新管理員]

  2. 管理中,選擇 機器>維護設定

  3. 維護設定 面板中,選擇設定。

  4. 在 [設定] 之下,選取 [事件]

  5. 選擇 +Event 訂閱 以建立維護前或維護後事件。

  6. 「建立活動訂閱 」面板,活動 訂閱詳情 區塊中,輸入適當的名稱。 將結構描述保留為 [事件方格結構描述]

  7. 事件類型 區塊中,篩選 到事件類型時,選擇 維護前事件維護後事件

  8. 端點詳細資料 區塊中,選擇 Azure 函式 端點,然後選擇 配置端點

  9. 提供適當的細節,例如觸發事件的資源群組和函式應用程式。

  10. 選取 [建立]

你也可以使用 Azure Storage 帳號和活動中心來儲存、傳送和接收事件。 欲了解更多資訊,請參閱快速入門,了解如何 在 Azure Storage 建立佇列 及使用 Azure 入口建立 事件中心