微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 Runbook 将 Azure VM 载入更新管理

如何解决使用 Runbook 将 Azure VM 载入更新管理

我创建了一个 Runbook,用于将 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 工作区‘workspacename’报告,但它们确实如此没有启用“更新管理”。”

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

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.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","resourceName": {
            "type": "string","category": {
            "type": "string","displayName": {
            "type": "string","query": {
            "type": "string","functionAlias": {
            "type": "string","etag": {
            "type": "string","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

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

解决方法

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

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

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

这是一个工作查询的例子:

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。