【问题标题】:Onboard Azure VMs to Update Management using runbook使用 Runbook 载入 Azure VM 以更新管理
【发布时间】:2021-01-07 10:12:30
【问题描述】:

我创建了一个运行手册来载入 Azure VM 以进行更新管理。 这个想法来自 MS 提供的运行手册 (https://github.com/azureautomation/runbooks/blob/master/Utility/ARM/Enable-AutomationSolution.ps1)。 MS Runbook 使用旧的 AzureRM 模块,不能满足我的需求,而且不能直接开箱即用。

我的 Runbook 本质上是做同样的事情,查找带有标签的 VM,安装 Microsoft Monitoring Agent 并将其配置为向工作区报告。

然后它会更新工作区中的查询以包含 VM。

所有这些工作并成功完成,但更新管理门户中显示“1 台计算机未启用‘更新管理’”和“这些计算机正在向 Log Analytics 工作区‘工作区名称’报告,但它们确实没有对它们启用“更新管理”。”

我不确定我还遗漏了哪些其他步骤,或者某些内容是否发生了变化,而且我看不到我的 MS Runbook 做了什么。

运行手册中的模块:

Az.Accounts
    
1/6/2021, 3:15 PM
    
Available
    
2.2.3
Az.Compute
    
1/6/2021, 3:17 PM
    
Available
    
4.8.0
Az.OperationalInsights
    
1/6/2021, 3:17 PM
    
Available
    
2.3.0
Az.Resources
    
1/6/2021, 3:17 PM
    
Available
    
3.1.1
Az.Storage
    
1/6/2021, 3:18 PM
    
Available
    
3.2.0

我的运行手册:

#Import-module -Name Az.Profile, Az.Automation, Az.OperationalInsights, Az.Compute, Az.Resources
#exit
#if ($oErr)
#{
#    Write-Error -Message "Failed to load needed modules for Runbook, check that Az.Automation, Az.OperationalInsights, Az.Compute and Az.Resources are imported into the Automation Account" -ErrorAction Stop
#}

# Fetch AA RunAs account detail from connection object asset
$ServicePrincipalConnection = Get-AutomationConnection -Name "AzureRunAsConnection" -ErrorAction Stop
$Connection = Add-AzAccount  -ServicePrincipal -TenantId $ServicePrincipalConnection.TenantId `
-ApplicationId $ServicePrincipalConnection.ApplicationId -CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint -ErrorAction Continue -ErrorVariable oErr
if ($oErr)
{
    Write-Error -Message "Failed to connect to Azure" -ErrorAction Stop
}
else
{
    write-output "connected to Azure"
}


#get the LA subscription
$LogAnalyticsSolutionSubscriptionId = Get-AutomationVariable -Name "LASolutionSubscriptionId"
#get the LA workspace RG
$LogAnalyticsSolutionWorkspaceRG = Get-AutomationVariable -Name "LASolutionWorkspaceRG"
#get the LA workspace Name
$LogAnalyticsSolutionWorkspaceName = Get-AutomationVariable -Name "LASolutionWorkspaceName"
#get the LA workspace Id
$LogAnalyticsSolutionWorkspace = Get-AzOperationalInsightsWorkspace -Name $LogAnalyticsSolutionWorkspaceName -ResourceGroupName $LogAnalyticsSolutionWorkspaceRG
#$LogAnalyticsSolutionWorkspaceId = Get-AutomationVariable -Name "LASolutionWorkspaceId"
#get the LA workspace key
$LogAnalyticsSolutionWorkspaceKey = AzOperationalInsightsWorkspaceSharedKey -ResourceGroupName $LogAnalyticsSolutionWorkspaceRG -Name $LogAnalyticsSolutionWorkspaceName

#$PublicSettings=@{"workspaceId" = $LogAnalyticsSolutionWorkspace.CustomerId};
#write-output "public settings are: "
#write-output $PublicSettings

write-output "sid is $LogAnalyticsSolutionSubscriptionId, wid is $($LogAnalyticsSolutionWorkspace.CustomerId), key is $($LogAnalyticsSolutionWorkspaceKey.PrimarySharedKey)"

if ($null -eq $LogAnalyticsSolutionSubscriptionId -or $Null -eq $LogAnalyticsSolutionWorkspace -or $null -eq $LogAnalyticsSolutionWorkspaceKey)
{
    Write-Error -Message "Unable to retrieve variables from automation account."
    exit
}



#get VM list

$VMsWantingPatching=Get-AzResource -TagName "patching" -TagValue "true" -ResourceType "Microsoft.Compute/virtualMachines"  -ErrorAction Continue -ErrorVariable oErr
if ($oErr)
{
    Write-Error -Message "Could not retrieve VM list" -ErrorAction Stop
}
elseif ($Null -eq $VMsWantingPatching)
{
    Write-Error -Message "No VMs need patching"  -ErrorAction Stop
}
else
{
    write-output "Successfully retrieved VM list"
}

foreach ($VM in $VMsWantingPatching)
{

Try
{
#Configure MMA on the VM to report to the UM LA workspace, unfortunately the workspace ID and key need to be hardcoded
#as passing a parameter does not work.
#Using this method preserves existing workspaces on the MMA agent, this method only adds, not replaces like using ARM would do
$CurrentVM=Get-AzVM -name $VM.name
Set-AzVMExtension -ExtensionName "MicrosoftMonitoringAgent" `
                -ResourceGroupName $VM.ResourceGroupName `
                -VMName $VM.Name `
                -Publisher "Microsoft.EnterpriseCloud.Monitoring" `
                -ExtensionType "MicrosoftMonitoringAgent" `
                -TypeHandlerVersion "1.0" `
                -Settings @{"workspaceId" = "xxx" } `
                -ProtectedSettings @{"workspaceKey" = "xxx"} `
                -Location $VM.location
#Add VM to string list for LA function
$VMList += "`"$($CurrentVM.vmid)`", "

}
catch
{
write-error -Message $_.Exception.message
}
<#        if ($VMAgentConfig.StatusCode -ne 0)
        {
            Write-Error -Message "Failed to add workspace to  $($VM.Name)"
            exit
        }
        else
        {
            write-output "Successfully added the workspace to  $($VM.Name)"
        }#>

}

write-output "VMList to use is: " $($VMList)
#Get the saved queries in LA
$SavedGroups = Get-AzOperationalInsightsSavedSearch -ResourceGroupName $LogAnalyticsSolutionWorkspaceRG `
                -WorkspaceName $LogAnalyticsSolutionWorkspaceName  -AzureRmContext $LASubscriptionContext -ErrorAction Continue -ErrorVariable oErr
#Find the Update Management saved query from the entire list and put it into a variable
$UpdatesGroup = $SavedGroups.Value | Where-Object {$_.Id -match "MicrosoftDefaultComputerGroup" -and $_.Properties.Category -eq "Updates"}

write-output "group is " $UpdatesGroup | out-string -Width 1000
#set the query/function
#remove trailing comma from list of VMs
$VMList = $($VMList).TrimEnd(', ')
#we use Resource as UUID is not useful when troubleshooting the query and computer gets truncated
$NewQuery="Heartbeat | where VMUUID in ( $($VMList) ) | distinct Computer"
write-output "Newquery is" $($NewQuery)

#just left in for info but no longer use Powershell to update LA query, using ARM as this has etag parameter, which is needed to avoid 409 conflict.
#New-AzOperationalInsightsSavedSearch -ResourceGroupName $LogAnalyticsSolutionWorkspaceRG -WorkspaceName $LogAnalyticsSolutionWorkspaceName `
#                                     -SavedSearchID "Updates|MicrosoftDefaultComputerGroup" -Category "Updates" -FunctionAlias "Updates__MicrosoftDefaultComputerGroup" `
#                                     -Query $NewQuery -DisplayName "MicrosoftDefaultComputerGroup" -Force


#write arm template to a file then make a new resource deployment to update the LA function

#configure arm template

        $ArmTemplate = @'
{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "location": {
            "type": "string",
            "defaultValue": ""
        },
        "id": {
            "type": "string",
            "defaultValue": ""
        },
        "resourceName": {
            "type": "string",
            "defaultValue": ""
        },
        "category": {
            "type": "string",
            "defaultValue": ""
        },
        "displayName": {
            "type": "string",
            "defaultValue": ""
        },
        "query": {
            "type": "string",
            "defaultValue": ""
        },
        "functionAlias": {
            "type": "string",
            "defaultValue": ""
        },
        "etag": {
            "type": "string",
            "defaultValue": ""
        },
        "apiVersion": {
            "defaultValue": "2017-04-26-preview",
            "type": "String"
        }
    },
    "resources": [
        {
            "apiVersion": "2017-04-26-preview",
            "type": "Microsoft.OperationalInsights/workspaces/savedSearches",
            "location": "[parameters('location')]",
            "name": "[parameters('resourceName')]",
            "id": "[parameters('id')]",
            "properties": {
                "displayname": "[parameters('displayName')]",
                "category": "[parameters('category')]",
                "query": "[parameters('query')]",
                "functionAlias": "[parameters('functionAlias')]",
                "etag": "[parameters('etag')]",
                "tags": [
                    {
                        "Name": "Group", "Value": "Computer"
                    }
                ]
            }
        }
    ]
}
'@
        #Endregion
        # Create temporary file to store ARM template in
        $TempFile = New-TemporaryFile -ErrorAction Continue -ErrorVariable oErr
        if ($oErr)
        {
            Write-Error -Message "Failed to create temporary file for solution ARM template" -ErrorAction Stop
        }
        Out-File -InputObject $ArmTemplate -FilePath $TempFile.FullName -ErrorAction Continue -ErrorVariable oErr
        if ($oErr)
        {
            Write-Error -Message "Failed to write ARM template for solution onboarding to temp file" -ErrorAction Stop
        }
        # Add all of the parameters
        $QueryDeploymentParams = @{}
        $QueryDeploymentParams.Add("location", $($LogAnalyticsSolutionWorkspace.Location))
        $QueryDeploymentParams.Add("id", $UpdatesGroup.Id)
        $QueryDeploymentParams.Add("resourceName", ($LogAnalyticsSolutionWorkspaceName+ "/Updates|MicrosoftDefaultComputerGroup").ToLower())
        $QueryDeploymentParams.Add("category", "Updates")
        $QueryDeploymentParams.Add("displayName", "MicrosoftDefaultComputerGroup")
        $QueryDeploymentParams.Add("query", $NewQuery)
        $QueryDeploymentParams.Add("functionAlias", $SolutionType + "__MicrosoftDefaultComputerGroup")
        $QueryDeploymentParams.Add("etag", "*")#$UpdatesGroup.ETag) etag is null for the query and referencing null property doesn't work so * instead
        #$QueryDeploymentParams.Add("apiVersion", $SolutionApiVersion)

        # Create deployment name
        $DeploymentName = "EnableMultipleAutomation" + (Get-Date).ToFileTimeUtc()

        $ObjectOutPut = New-AzResourceGroupDeployment -ResourceGroupName $LogAnalyticsSolutionWorkspaceRG -TemplateFile $TempFile.FullName `
            -Name $DeploymentName `
            -TemplateParameterObject $QueryDeploymentParams `
            -AzureRmContext $SubscriptionContext -ErrorAction Continue -ErrorVariable oErr
        if ($oErr)
        {
            Write-Error -Message "Failed to add VM: $VMName to solution: $SolutionType" -ErrorAction Stop
        }
        else
        {
            Write-Output -InputObject $ObjectOutPut
            Write-Output -InputObject "VM: $VMName successfully added to solution: $SolutionType"
        }

        # Remove temp file with arm template
        Remove-Item -Path $TempFile.FullName -Force

就像我说的,运行手册似乎已成功完成,但我想知道有人能告诉我没有执行什么任务吗? 谢谢, 尼尔。

【问题讨论】:

    标签: azure azure-runbook


    【解决方案1】:

    好的,我想我已经整理好了。 答案就在 LA 查询中。

    我的查询没有使用计算机作为搜索字段,因为它在 15 个字符处被截断,我只使用了 VMUUID。即使结果集相同,除非您的查询正确,否则 UM 也会失败。

    即使未使用,正确的查询也应该包含它。您还需要波浪号,因为显然更新管理需要非常精确的查询语法。

    这是一个有效查询的示例:

    Heartbeat | where Computer in~ ("") or VMUUID in~ ("xxxxx") | distinct Computer
    

    然后您必须在盒子上重新启动 MMA,然后等待控制台更新。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 2015-05-15
      相关资源
      最近更新 更多