MMA/OMS 검색 및 제거 유틸리티
컴퓨터를 AMA(Azure Monitor 에이전트)로 마이그레이션한 후 운영 체제에 따라 레거시 Log Analytics 에이전트를 제거하여 로그가 중복되지 않도록 합니다. 레거시 검색 및 제거 유틸리티는 단일 구독에서 Azure VM(Virtual Machines), Azure VMSS(Virtual Machine Scale Sets) 및 Azure Arc 서버에서 확장을 제거할 수 있습니다.
이 유틸리티는 다음 두 단계로 작동합니다.
검색: 이 유틸리티는 레거시 에이전트가 간단한 CSV 파일에 설치된 모든 컴퓨터의 인벤토리를 만듭니다. 유틸리티가 실행되는 동안에는 새 VM을 만들지 않는 것이 좋습니다.
제거: 유틸리티는 CSV 파일에 나열된 컴퓨터에서 레거시 에이전트를 제거합니다. 에이전트를 제거하려는 컴퓨터만 존재하도록 CSV 파일의 컴퓨터 목록을 편집해야 합니다.
!참고: MSI 설치 프로그램을 사용하여 설치된 MMA 에이전트에서는 제거가 작동하지 않습니다. VM 확장에서만 작동합니다.
필수 조건
인터넷에 연결된 컴퓨터에서 모든 설정 단계를 수행합니다. 필요 항목:
- Windows 10 이상 또는 Windows Server 2019 이상
- PowerShell 7.0 이상. 이 기능을 사용하면 프로세스 속도를 높일 수 있는 병렬 실행이 가능합니다.
- Azure Graph API와 통신하려면 Azcli를 설치해야 합니다.
- PowerShell을 관리자 권한으로 엽니다.
Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile AzureCLI.msi
명령을 실행합니다.Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'
명령을 실행합니다.- 최신 버전의 Azure CLI가 다운로드 및 설치됩니다.
1단계 로그인 및 구독 설정
이 도구는 한 번에 하나의 구독을 작동합니다. 제거를 수행하려면 로그인하고 구독을 설정해야 합니다. 관리자 권한으로 PowerShell 명령 프롬프트를 열고 로그인합니다.
az login
다음으로 구독을 설정해야 합니다.
Az account set --subscription {subscription_id or “subscription_name”}
2단계 스크립트 복사
에이전트를 제거하려면 다음 스크립트를 사용합니다. 로컬 디렉터리에서 LogAnalyticsAgentUninstallUtilityScript.ps1이라는 파일을 열고 해당 파일에 스크립트를 복사합니다.
# This is per subscription, the customer has to set the az subscription before running this.
# az login
# az account set --subscription <subscription_id/subscription_name>
# This script uses parallel processing, modify the $parallelThrottleLimit parameter to either increase or decrease the number of parallel processes
# PS> .\LogAnalyticsAgentUninstallUtilityScript.ps1 GetInventory
# The above command will generate a csv file with the details of Vm's and Vmss and Arc servers that has log analyice Agent extension installed.
# The customer can modify the the csv by adding/removing rows if needed
# Remove the log analytics agent by running the script again as shown below:
# PS> .\LogAnalyticsAgentUninstallUtilityScript.ps1 UninstallExtension
# This version of the script requires Powershell version >= 7 in order to improve performance via ForEach-Object -Parallel
# https://docs.microsoft.com/en-us/powershell/scripting/whats-new/migrating-from-windows-powershell-51-to-powershell-7?view=powershell-7.1
if ($PSVersionTable.PSVersion.Major -lt 7)
{
Write-Host "This script requires Powershell version 7 or newer to run. Please see https://docs.microsoft.com/en-us/powershell/scripting/whats-new/migrating-from-windows-powershell-51-to-powershell-7?view=powershell-7.1."
exit 1
}
$parallelThrottleLimit = 16
function GetArcServersWithLogAnalyticsAgentExtensionInstalled {
param (
$fileName
)
$serverList = az connectedmachine list --query "[].{ResourceId:id, ResourceGroup:resourceGroup, ServerName:name}" | ConvertFrom-Json
if(!$serverList)
{
Write-Host "Cannot get the Arc server list"
return
}
$serversCount = $serverList.Length
$vmParallelThrottleLimit = $parallelThrottleLimit
if ($serversCount -lt $vmParallelThrottleLimit)
{
$serverParallelThrottleLimit = $serversCount
}
$serverGroups = @()
if($serversCount -eq 1)
{
$serverGroups += ,($serverList[0])
}
else
{
# split the list into batches to do parallel processing
for ($i = 0; $i -lt $serversCount; $i += $vmParallelThrottleLimit)
{
$serverGroups += , ($serverList[$i..($i + $serverParallelThrottleLimit - 1)])
}
}
Write-Host "Detected $serversCount Arc servers in this subscription."
$hash = [hashtable]::Synchronized(@{})
$hash.One = 1
$serverGroups | Foreach-Object -ThrottleLimit $parallelThrottleLimit -Parallel {
$len = $using:serversCount
$hash = $using:hash
$_ | ForEach-Object {
$percent = 100 * $hash.One++ / $len
Write-Progress -Activity "Getting Arc server extensions Inventory" -PercentComplete $percent
$serverName = $_.ServerName
$resourceGroup = $_.ResourceGroup
$resourceId = $_.ResourceId
Write-Debug "Getting extensions for Arc server: $serverName"
$extensions = az connectedmachine extension list -g $resourceGroup --machine-name $serverName --query "[?contains(['MicrosoftMonitoringAgent', 'OmsAgentForLinux', 'AzureMonitorLinuxAgent', 'AzureMonitorWindowsAgent'], properties.type)].{type: properties.type, name: name}" | ConvertFrom-Json
if (!$extensions) {
return
}
$extensionMap = @{}
foreach ($ext in $extensions) {
$extensionMap[$ext.type] = $ext.name
}
$extensionName = ""
if ($extensionMap.ContainsKey("MicrosoftMonitoringAgent")) {
$extensionName = $extensionMap["MicrosoftMonitoringAgent"]
}
elseif ($extensionMap.ContainsKey("OmsAgentForLinux")) {
$extensionName = $extensionMap["OmsAgentForLinux"]
}
if ($extensionName) {
$amaExtensionInstalled = "False"
if ($extensionMap.ContainsKey("AzureMonitorWindowsAgent") -or $extensionMap.ContainsKey("AzureMonitorLinuxAgent")) {
$amaExtensionInstalled = "True"
}
$csvObj = New-Object -TypeName PSObject -Property @{
'ResourceId' = $resourceId
'Name' = $serverName
'Resource_Group' = $resourceGroup
'Resource_Type' = "ArcServer"
'Install_Type' = "Extension"
'Extension_Name' = $extensionName
'AMA_Extension_Installed' = $amaExtensionInstalled
}
$csvObj | Export-Csv $using:fileName -Append -Force | Out-Null
}
# az cli sometime cannot handle many requests at same time, so delaying next request by 2 milliseconds
Start-Sleep -Milliseconds 2
}
}
}
function GetVmsWithLogAnalyticsAgentExtensionInstalled
{
param(
$fileName
)
$vmList = az vm list --query "[].{ResourceId:id, ResourceGroup:resourceGroup, VmName:name}" | ConvertFrom-Json
if(!$vmList)
{
Write-Host "Cannot get the VM list"
return
}
$vmsCount = $vmList.Length
$vmParallelThrottleLimit = $parallelThrottleLimit
if ($vmsCount -lt $vmParallelThrottleLimit)
{
$vmParallelThrottleLimit = $vmsCount
}
if($vmsCount -eq 1)
{
$vmGroups += ,($vmList[0])
}
else
{
# split the vm's into batches to do parallel processing
for ($i = 0; $i -lt $vmsCount; $i += $vmParallelThrottleLimit)
{
$vmGroups += , ($vmList[$i..($i + $vmParallelThrottleLimit - 1)])
}
}
Write-Host "Detected $vmsCount Vm's in this subscription."
$hash = [hashtable]::Synchronized(@{})
$hash.One = 1
$vmGroups | Foreach-Object -ThrottleLimit $parallelThrottleLimit -Parallel {
$len = $using:vmsCount
$hash = $using:hash
$_ | ForEach-Object {
$percent = 100 * $hash.One++ / $len
Write-Progress -Activity "Getting VM extensions Inventory" -PercentComplete $percent
$resourceId = $_.ResourceId
$vmName = $_.VmName
$resourceGroup = $_.ResourceGroup
Write-Debug "Getting extensions for VM: $vmName"
$extensions = az vm extension list -g $resourceGroup --vm-name $vmName --query "[?contains(['MicrosoftMonitoringAgent', 'OmsAgentForLinux', 'AzureMonitorLinuxAgent', 'AzureMonitorWindowsAgent'], typePropertiesType)].{type: typePropertiesType, name: name}" | ConvertFrom-Json
if (!$extensions) {
return
}
$extensionMap = @{}
foreach ($ext in $extensions) {
$extensionMap[$ext.type] = $ext.name
}
$extensionName = ""
if ($extensionMap.ContainsKey("MicrosoftMonitoringAgent")) {
$extensionName = $extensionMap["MicrosoftMonitoringAgent"]
}
elseif ($extensionMap.ContainsKey("OmsAgentForLinux")) {
$extensionName = $extensionMap["OmsAgentForLinux"]
}
if ($extensionName) {
$amaExtensionInstalled = "False"
if ($extensionMap.ContainsKey("AzureMonitorWindowsAgent") -or $extensionMap.ContainsKey("AzureMonitorLinuxAgent")) {
$amaExtensionInstalled = "True"
}
$csvObj = New-Object -TypeName PSObject -Property @{
'ResourceId' = $resourceId
'Name' = $vmName
'Resource_Group' = $resourceGroup
'Resource_Type' = "VM"
'Install_Type' = "Extension"
'Extension_Name' = $extensionName
'AMA_Extension_Installed' = $amaExtensionInstalled
}
$csvObj | Export-Csv $using:fileName -Append -Force | Out-Null
}
# az cli sometime cannot handle many requests at same time, so delaying next request by 2 milliseconds
Start-Sleep -Milliseconds 2
}
}
}
function GetVmssWithLogAnalyticsAgentExtensionInstalled
{
param(
$fileName
)
# get the vmss list which are successfully provisioned
$vmssList = az vmss list --query "[?provisioningState=='Succeeded'].{ResourceId:id, ResourceGroup:resourceGroup, VmssName:name}" | ConvertFrom-Json
$vmssCount = $vmssList.Length
Write-Host "Detected $vmssCount Vmss in this subscription."
$hash = [hashtable]::Synchronized(@{})
$hash.One = 1
$vmssList | Foreach-Object -ThrottleLimit $parallelThrottleLimit -Parallel {
$len = $using:vmssCount
$hash = $using:hash
$percent = 100 * $hash.One++ / $len
Write-Progress -Activity "Getting VMSS extensions Inventory" -PercentComplete $percent
$resourceId = $_.ResourceId
$vmssName = $_.VmssName
$resourceGroup = $_.ResourceGroup
Write-Debug "Getting extensions for VMSS: $vmssName"
$extensions = az vmss extension list -g $resourceGroup --vmss-name $vmssName --query "[?contains(['MicrosoftMonitoringAgent', 'OmsAgentForLinux', 'AzureMonitorLinuxAgent', 'AzureMonitorWindowsAgent'], typePropertiesType)].{type: typePropertiesType, name: name}" | ConvertFrom-Json
if (!$extensions) {
return
}
$extensionMap = @{}
foreach ($ext in $extensions) {
$extensionMap[$ext.type] = $ext.name
}
$extensionName = ""
if ($extensionMap.ContainsKey("MicrosoftMonitoringAgent")) {
$extensionName = $extensionMap["MicrosoftMonitoringAgent"]
}
elseif ($extensionMap.ContainsKey("OmsAgentForLinux")) {
$extensionName = $extensionMap["OmsAgentForLinux"]
}
if ($extensionName) {
$amaExtensionInstalled = "False"
if ($extensionMap.ContainsKey("AzureMonitorWindowsAgent") -or $extensionMap.ContainsKey("AzureMonitorLinuxAgent")) {
$amaExtensionInstalled = "True"
}
$csvObj = New-Object -TypeName PSObject -Property @{
'ResourceId' = $resourceId
'Name' = $vmssName
'Resource_Group' = $resourceGroup
'Resource_Type' = "VMSS"
'Install_Type' = "Extension"
'Extension_Name' = $extensionName
'AMA_Extension_Installed' = $amaExtensionInstalled
}
$csvObj | Export-Csv $using:fileName -Append -Force | Out-Null
}
# az cli sometime cannot handle many requests at same time, so delaying next request by 2 milliseconds
Start-Sleep -Milliseconds 2
}
}
function GetInventory
{
param(
$fileName = "LogAnalyticsAgentExtensionInventory.csv"
)
# create a new file
New-Item -Name $fileName -ItemType File -Force
Start-Transcript -Path $logFileName -Append
GetVmsWithLogAnalyticsAgentExtensionInstalled $fileName
GetVmssWithLogAnalyticsAgentExtensionInstalled $fileName
GetArcServersWithLogAnalyticsAgentExtensionInstalled $fileName
Stop-Transcript
}
function UninstallExtension
{
param(
$fileName = "LogAnalyticsAgentExtensionInventory.csv"
)
Start-Transcript -Path $logFileName -Append
Import-Csv $fileName | ForEach-Object -ThrottleLimit $parallelThrottleLimit -Parallel {
if ($_.Install_Type -eq "Extension")
{
$extensionName = $_.Extension_Name
$resourceName = $_.Name
Write-Debug "Uninstalling extension: $extensionName from $resourceName"
if ($_.Resource_Type -eq "VMSS")
{
# if the extension is installed with a custom name, provide the name using the flag: --extension-instance-name <extension name>
az vmss extension delete --name $extensionName --vmss-name $resourceName --resource-group $_.Resource_Group --output none --no-wait
}
elseif($_.Resource_Type -eq "VM")
{
# if the extension is installed with a custom name, provide the name using the flag: --extension-instance-name <extension name>
az vm extension delete --name $extensionName --vm-name $resourceName --resource-group $_.Resource_Group --output none --no-wait
}
elseif($_.Resource_Type -eq "ArcServer")
{
az connectedmachine extension delete --name $extensionName --machine-name $resourceName --resource-group $_.Resource_Group --no-wait --output none --yes -y
}
# az cli sometime cannot handle many requests at same time, so delaying next delete request by 2 milliseconds
Start-Sleep -Milliseconds 2
}
}
Stop-Transcript
}
$logFileName = "LogAnalyticsAgentUninstallUtilityScriptLog.log"
switch ($args.Count)
{
0 {
Write-Host "The arguments provided are incorrect."
Write-Host "To get the Inventory: Run the script as: PS> .\LogAnalyticsAgentUninstallUtilityScript.ps1 GetInventory"
Write-Host "To uninstall Log Analytics Agent from Inventory: Run the script as: PS> .\LogAnalyticsAgentUninstallUtilityScript.ps1 UninstallExtension"
}
1 {
if (-Not (Test-Path $logFileName)) {
New-Item -Path $logFileName -ItemType File
}
$funcname = $args[0]
Invoke-Expression "& $funcname"
}
2 {
if (-Not (Test-Path $logFileName)) {
New-Item -Path $logFileName -ItemType File
}
$funcname = $args[0]
$funcargs = $args[1]
Invoke-Expression "& $funcname $funcargs"
}
}
3단계 인벤토리를 가져옵니다.
구독에 있는 모든 VM, VMSS 및 Arc 지원 서버의 모든 레거시 에이전트 목록을 수집합니다. 구독에서 레거시 에이전트의 인벤토리를 다운로드한 스크립트를 실행합니다.
.\LogAnalyticsAgentUninstallUtilityScript.ps1 GetInventory
스크립트는 구독에서 볼 수 있는 전체 VM, VMSS 또는 Arc 사용 서버를 보고합니다. 스크립트를 실행하는 데 몇 분이 걸립니다. 콘솔 창에 진행률 표시줄이 표시됩니다. 완료되면 로컬 디렉터리에서 다음 형식의 "LogAnalyticsAgentExtensionInventory.csv"라는 CSV 파일을 볼 수 있습니다.
Resource_ID | 속성 | Resource_Group | Resource_Type | Install_Type | Extension_Name | AMA_Extension_Installed |
---|---|---|---|---|---|---|
012cb5cf-e1a8-49ee-a484-d40673167c9c | Linux-ama-e2e-debian9 | Linux-AMA-E2E | VM | 내선 번호 | OmsAgentForLinux | True |
8acae35a-454f-4869-bf4f-658189d98516 | test2012-r2-da | test2012-r2-daAMA-ADMIN | VM | 내선 번호 | MicrosoftMonitorAgent | False |
4단계 인벤토리 제거
이 스크립트는 VM, Virtual Machine Scale Sets 및 Arc 지원 서버 목록을 반복하고 레거시 에이전트를 제거합니다. 에이전트가 실행 중이 아니면 제거할 수 없습니다.
.\LogAnalyticsAgentUninstallUtilityScript.ps1 UninstallExtension
스크립트가 완료되면 "LogAnalyticsAgentExtensionInventory.csv" 파일에서 VM, Virtual Machine Scale Sets 및 Arc 지원 서버의 제거 상태를 확인할 수 있습니다.