A Windowshoz készült Log Analytics-ügynökkel kapcsolatos hibák elhárítása

Ez a cikk segítséget nyújt a Windows Log Analytics-ügynökével az Azure Monitorban tapasztalt hibák elhárításához, és lehetséges megoldásokat javasol azok megoldására.

Log Analytics hibaelhárító eszköz

A Windows hibaelhárító eszközhöz készült Log Analytics-ügynök PowerShell-szkriptek gyűjteménye, amelyek a Log Analytics-ügynökkel kapcsolatos problémák felderítésére és diagnosztizálására szolgálnak. A telepítéskor automatikusan bekerül az ügynökbe. Az eszköz futtatásának kell lennie a probléma diagnosztizálása első lépésének.

A hibaelhárítási eszköz használata

  1. Nyissa meg a PowerShell-parancssort rendszergazdaként azon a gépen, amelyen a Log Analytics-ügynök telepítve van.

  2. Lépjen arra a könyvtárra, ahol az eszköz található:

    cd "C:\Program Files\Microsoft Monitoring Agent\Agent\Troubleshooter"

  3. Hajtsa végre a fő szkriptet a következő paranccsal:

    .\GetAgentInfo.ps1

  4. Válasszon ki egy hibaelhárítási forgatókönyvet.

  5. Kövesse a konzol utasításait. Vegye figyelembe, hogy a nyomkövetési naplók lépései manuális beavatkozást igényelnek a naplógyűjtés leállításához. A probléma reprodukálhatósága alapján várja meg az időtartamot, és válassza az "s" lehetőséget a naplógyűjtés leállításához, és folytassa a következő lépésre.

    Az eredményfájl helyét a rendszer a befejezéskor naplózza, és megnyílik egy új kezelőablak, amely kiemeli azt.

Installation

A Hibaelhárító eszköz automatikusan megjelenik a Log Analytics-ügynök 10.20.18053.0-s buildjének telepítésekor és tovább.

Érintett forgatókönyvek

A hibaelhárító eszköz a következő forgatókönyveket ellenőrzi:

  • Az ügynök nem jelent adatokat, vagy a szívverés adatai hiányoznak.
  • Az ügynökbővítmény üzembe helyezése sikertelen.
  • Az ügynök összeomlik.
  • Az ügynök nagy processzort vagy memóriát használ.
  • Telepítési és eltávolítási hibák.
  • Az egyéni naplók problémái vannak.
  • Az OMS Gateway problémái vannak.
  • A teljesítményszámlálók problémái vannak.
  • Az ügynöknaplók nem gyűjthetők.

Megjegyzés:

Ha problémát tapasztal, futtassa a hibaelhárítási eszközt. A naplók kezdeti használata segít a támogatási csapatnak a probléma gyorsabb elhárításában.

Fontos hibaelhárítási források

A Windows Log Analytics-ügynökével kapcsolatos problémák elhárításához az ügynök naplózza az eseményeket a Windows eseménynaplójában, különösen az Application and Services\Operations Manager alatt.

Connectivity issues

Ha az ügynök proxykiszolgálón vagy tűzfalon keresztül kommunikál, előfordulhat, hogy olyan korlátozások lépnek életbe, amelyek megakadályozzák a forrásszámítógép és az Azure Monitor szolgáltatás közötti kommunikációt. Ha a kommunikáció helytelen konfiguráció miatt le van tiltva, előfordulhat, hogy egy munkaterület regisztrációja meghiúsul az ügynök telepítésének vagy az ügynök beállítás utáni konfigurálásának megkísérlése során, hogy egy másik munkaterületen jelentsen. Az ügynök kommunikációja sikertelen lehet a sikeres regisztráció után. Ez a szakasz a Windows-ügynökkel kapcsolatos ilyen típusú problémák elhárításának módszereit ismerteti.

Ellenőrizze, hogy a tűzfal vagy a proxy úgy van-e konfigurálva, hogy engedélyezze az alábbi táblázatban ismertetett portokat és URL-címeket. Győződjön meg arról is, hogy a HTTP-ellenőrzés nincs engedélyezve a webes forgalom számára. Megakadályozhatja, hogy biztonságos TLS-csatorna legyen az ügynök és az Azure Monitor között.

Ügynök erőforrása Ports Direction HTTPS-ellenőrzés kihagyása
*.ods.opinsights.azure.com 443-as port Outbound Igen
*.oms.opinsights.azure.com 443-as port Outbound Igen
*.blob.core.windows.net 443-as port Outbound Igen
*.agentsvc.azure-automation.net 443-as port Outbound Igen

Az Azure Government-hez szükséges tűzfalinformációkért tekintse meg az Azure Government felügyeletét. Ha azt tervezi, hogy az Azure Automation hibrid runbook-feldolgozójával csatlakozik és regisztrál az Automation szolgáltatással runbookokat vagy felügyeleti megoldásokat használ a környezetben, hozzáféréssel kell rendelkeznie a hibrid runbook-feldolgozó hálózatának konfigurálása című cikkben leírt portszámhoz és URL-címekhez.

Többféleképpen ellenőrizheti, hogy az ügynök sikeresen kommunikál-e az Azure Monitorral:

  • Engedélyezze az Azure Log Analytics-ügynök állapotfelmérését a munkaterületen. Az Ügynök állapota irányítópulton tekintse meg a nem válaszoló ügynökök száma oszlopot, hogy gyorsan kiderüljön, hogy az ügynök szerepel-e a listában.

  • Futtassa a következő lekérdezést annak ellenőrzéséhez, hogy az ügynök szívverést küld-e arra a munkaterületre, amelyen a jelentéskészítésre van konfigurálva. Cserélje le <ComputerName> a gép tényleges nevére.

    Heartbeat 
    | where Computer like "<ComputerName>"
    | summarize arg_max(TimeGenerated, * ) by Computer 
    

    Ha a számítógép sikeresen kommunikál a szolgáltatással, a lekérdezésnek eredményt kell adnia. Ha a lekérdezés nem ad vissza eredményt, először ellenőrizze, hogy az ügynök a megfelelő munkaterületen való jelentéskészítésre van-e konfigurálva. Ha megfelelően van konfigurálva, folytassa a 3. lépéssel, és keressen rá a Windows eseménynaplójában annak megállapításához, hogy az ügynök naplózza-e azt a problémát, amely megakadályozhatja az Azure Monitorral való kommunikációt.

  • A csatlakozási problémák azonosításának másik módja a TestCloud Csatlakozás ivity eszköz futtatása. Az eszköz alapértelmezés szerint telepítve van az ügynökkel a(z) %SystemRoot%\Program Files\Microsoft Monitoring Agent\Agent mappában. Egy rendszergazda jogú parancssorból lépjen a mappába, és futtassa az eszközt. The tool returns the results and highlights where the test failed. Lehet például, hogy egy letiltott porthoz vagy URL-címhez kapcsolódik.

    Screenshot that shows TestCloudConnection tool execution results.

  • Szűrje az Operations Manager eseménynaplóját eseményforrások Állapotfigyelő szolgáltatás modulok, HealthService és Szolgáltatás Csatlakozás or szerint, és szűrjön eseményszintűfigyelmeztetés és hiba alapján annak ellenőrzéséhez, hogy az alábbi táblázatból írt-e eseményeket. Ha vannak, tekintse át az egyes lehetséges események megoldási lépéseit.

    Eseményazonosító Source Leírás Resolution (Osztás)
    2133 & 2129 Állapotfigyelő szolgáltatás Csatlakozás szolgáltatásba való átirányítás az ügynöktől sikertelen volt. Ez a hiba akkor fordulhat elő, ha az ügynök nem tud közvetlenül vagy tűzfalon vagy proxykiszolgálón keresztül kommunikálni az Azure Monitor szolgáltatással. Ellenőrizze az ügynökproxy beállításait, vagy hogy a hálózati tűzfal vagy proxy engedélyezi-e a TCP-forgalmat a számítógépről a szolgáltatásba.
    2138 Állapotfigyelő szolgáltatás modulok A proxy hitelesítést igényel. Konfigurálja az ügynökproxy beállításait, és adja meg a proxykiszolgálóval való hitelesítéshez szükséges felhasználónevet/jelszót.
    2129 Állapotfigyelő szolgáltatás modulok Sikertelen kapcsolat. Sikertelen TLS-egyeztetés. Ellenőrizze a hálózati adapter TCP/IP-beállításait és az ügynökproxy beállításait.
    2127 Állapotfigyelő szolgáltatás modulok Hibakód érkezett az adatok küldésének sikertelenségéről. Ha csak időszakosan történik a nap folyamán, akkor véletlenszerű anomália lehet, amelyet figyelmen kívül lehet hagyni. Monitorozás, amelyből megtudhatja, milyen gyakran fordul elő. Ha a nap folyamán gyakran előfordul, először ellenőrizze a hálózati konfigurációt és a proxybeállításokat. Ha a leírás tartalmazza a 404-ös HTTP-hibakódot, és ez az első alkalom, hogy az ügynök adatokat próbál küldeni a szolgáltatásnak, akkor egy 500-ás hibát fog tartalmazni egy belső 404 hibakóddal. A 404-es hibakód azt jelenti, hogy "nem található", ami azt jelzi, hogy az új munkaterület tárterülete még ki van építve. A következő újrapróbálkozáskor az adatok a várt módon sikeresen írásra kerülnek a munkaterületre. A 403-at jelző HTTP-hiba engedély- vagy hitelesítő adatokkal kapcsolatos problémát jelezhet. A 403-at tartalmazó hiba további információkat tartalmaz a probléma elhárításához.
    4000 Szolgáltatás-összekötő A DNS-névfeloldás nem sikerült. A gép nem tudta feloldani az adatokat a szolgáltatásnak küldött internetcímet. Ez a probléma lehet a dns-feloldó beállításai a számítógépen, helytelen proxybeállítások vagy a szolgáltató ideiglenes DNS-problémája. Ha rendszeresen előfordul, azt egy átmeneti, hálózattal kapcsolatos probléma okozhatja.
    4001 Szolgáltatás-összekötő Csatlakozás szolgáltatásra való átirányítás nem sikerült. Ez a hiba akkor fordulhat elő, ha az ügynök nem tud közvetlenül vagy tűzfalon vagy proxykiszolgálón keresztül kommunikálni az Azure Monitor szolgáltatással. Ellenőrizze az ügynökproxy beállításait, vagy hogy a hálózati tűzfal vagy proxy engedélyezi-e a TCP-forgalmat a számítógépről a szolgáltatásba.
    4002 Szolgáltatás-összekötő A szolgáltatás egy lekérdezésre válaszul visszaadta a 403-at a HTTP-állapotkódnak. Kérdezze meg a szolgáltatás rendszergazdáját a szolgáltatás állapotáról. A lekérdezés később újrapróbálkozott. Ez a hiba az ügynök kezdeti regisztrációs fázisában van megírva. A https://< workspaceID.oms.opinsights.azure.com/AgentService.svc/AgentTopologyRequest> url-címhez hasonló URL-cím jelenik meg. A 403-at tartalmazó hibakód "tiltott", és egy hibásan beírt munkaterület-azonosító vagy -kulcs okozhatja. Előfordulhat, hogy a dátum és az idő helytelen a számítógépen. Ha az idő az aktuális időponttól +/- 15 perc, az előkészítés meghiúsul. A probléma megoldásához frissítse a Windows rendszerű számítógép dátumát és/vagy időpontját.

Adatgyűjtési problémák

Az ügynök telepítése és a konfigurált munkaterületre vagy munkaterületekre való jelentéskészítés után leállhat a konfiguráció fogadása, valamint a teljesítmény, naplók vagy egyéb adatok gyűjtése vagy továbbítása a szolgáltatásnak attól függően, hogy mi engedélyezve van, és mi a cél a számítógép számára. Meg kell határoznia:

  • Ez egy adott adattípus, vagy az összes olyan adat, amely nem érhető el a munkaterületen?
  • Az adattípust egy megoldás adja meg, vagy a munkaterület adatgyűjtési konfigurációjának részeként van megadva?
  • Hány számítógép érintett? Egyetlen számítógép vagy több számítógép jelent a munkaterületnek?
  • Működött és leállt egy adott napkor, vagy soha nem gyűjtötték be?
  • A használt naplókeresési lekérdezés szintaktikailag helyes?
  • Megkapta már az ügynök a konfigurációját az Azure Monitortól?

A hibaelhárítás első lépése annak megállapítása, hogy a számítógép szívverési eseményt küld-e.

Heartbeat 
    | where Computer like "<ComputerName>"
    | summarize arg_max(TimeGenerated, * ) by Computer

Ha a lekérdezés eredményeket ad vissza, meg kell állapítania, hogy egy adott adattípust nem gyűjtenek-e össze és továbbítanak-e a szolgáltatásnak. Ezt a problémát az okozhatja, hogy az ügynök nem kapott frissített konfigurációt a szolgáltatástól, vagy más olyan tünetet, amely megakadályozza az ügynök normál működését. A további hibaelhárításhoz hajtsa végre az alábbi lépéseket.

  1. Nyisson meg egy rendszergazda jogú parancssort a számítógépen, és indítsa újra az ügynökszolgáltatást a beírással net stop healthservice && net start healthservice.

  2. Nyissa meg az Operations Manager eseménynaplóját, és keresse meg a 7023-at, a 7024-et, a 7025-öt, a 7028-at és az 1210-et az EseményforrásHealthService szolgáltatásból. Ezek az események azt jelzik, hogy az ügynök sikeresen megkapta a konfigurációt az Azure Monitortól, és aktívan figyelik a számítógépet. Az 1210-es eseményazonosító eseményleírása az utolsó sorban megadja az ügynök figyelési hatókörében szereplő összes megoldást és Elemzések.

    Screenshot that shows an Event ID 1210 description.

  3. Várjon néhány percet. Ha nem látja a várt adatokat a lekérdezés eredményeiben vagy vizualizációjában, attól függően, hogy egy megoldásból vagy az Insightból tekinti-e meg az adatokat az Operations Manager eseménynaplójából, keressen eseményforrásokatHealthService és Állapotfigyelő szolgáltatás modulokra. Szűrjön eseményszintűfigyelmeztetés és hiba szerint annak ellenőrzéséhez, hogy az alábbi táblázatból írt-e eseményeket.

    Eseményazonosító Source Leírás Resolution (Osztás)
    8000 HealthService Ez az esemény azt határozza meg, hogy egy teljesítményhez, eseményhez vagy más összegyűjtött adattípushoz kapcsolódó munkafolyamat nem tud-e továbbítani a szolgáltatásnak a munkaterületre való betöltés céljából. A healthService forrásból származó 2136-os eseményazonosító együtt van megírva ezzel az eseménysel, és jelezheti, hogy az ügynök nem tud kommunikálni a szolgáltatással. Lehetséges okok lehetnek a proxy- és hitelesítési beállítások helytelen konfigurálása, a hálózatkimaradás, vagy a hálózati tűzfal vagy proxy nem engedélyezi a TCP-forgalmat a számítógépről a szolgáltatásba.
    10102 és 10103 Állapotfigyelő szolgáltatás modulok A munkafolyamat nem tudta feloldani az adatforrást. Ez a probléma akkor fordulhat elő, ha a megadott teljesítményszámláló vagy -példány nem létezik a számítógépen, vagy helytelenül van definiálva a munkaterület adatbeállításaiban. Ha ez egy felhasználó által megadott teljesítményszámláló, ellenőrizze, hogy a megadott adatok a megfelelő formátumot követik-e, és léteznek-e a célszámítógépeken.
    26002 Állapotfigyelő szolgáltatás modulok A munkafolyamat nem tudta feloldani az adatforrást. Ez a probléma akkor fordulhat elő, ha a megadott Windows-eseménynapló nem létezik a számítógépen. Ez a hiba nyugodtan figyelmen kívül hagyható, ha a számítógépnek nem kell regisztrálnia ezt az eseménynaplót. Ellenkező esetben, ha ez egy felhasználó által megadott eseménynapló, ellenőrizze, hogy a megadott adatok helyesek-e.

Rögzített tanúsítványokkal kapcsolatos problémák a Microsoft régebbi figyelési ügynökeivel – Kompatibilitástörő változás

A legfelső szintű hitelesítésszolgáltató módosítása – áttekintés

2023. június 30-tól a Log Analytics háttérrendszere már nem fogadja el az MMA-ból az elavult főtanúsítványra hivatkozó kapcsolatokat. Ezek az MMA-k régebbi verziók a 2020. téli kiadás (Log Analytics Agent) és az SCOM 2019 UR3 (SCOM) előtt. Bármely verzió, csomag: 10.20.18053 / Bővítmény: 1.0.18053.0 vagy újabb nem lesz semmilyen probléma, valamint az SCOM 2019 UR3 feletti verzió. Minden ennél régebbi ügynök leáll, és a továbbiakban nem dolgozik és nem tölt fel a Log Analyticsbe.

Pontosan mi változik?

A különböző Azure-szolgáltatásokra irányuló folyamatos biztonsági erőfeszítések részeként az Azure Log Analytics hivatalosan is átvált a Baltimore CyberTrust CA-gyökérről a DigiCert Global G2 CA-gyökérre. Ez a változás hatással lesz a Log Analyticstel folytatott TLS-kommunikációra, ha az új DigiCert Global G2 hitelesítésszolgáltató főtanúsítványa hiányzik az operációs rendszerből, vagy az alkalmazás a régi Baltimore Root hitelesítésszolgáltatóra hivatkozik. Ez azt jelenti, hogy a Log Analytics többé nem fogadja el a régi legfelső szintű hitelesítésszolgáltatót használó MMA-kapcsolatokat a kivonása után.

Megoldástermékek

Előfordulhat, hogy akkor is megkapta a kompatibilitástörő változásról szóló értesítést, ha még nem telepítette személyesen a Microsoft Monitoring Agentet. Ennek az az oka, hogy a különböző Azure-termékek a Microsoft Monitoring Agentet használják. Ha ezen termékek egyikét használja, akkor a Windows Log Analytics-ügynök használata hatással lehet rájuk. Az alábbi hivatkozásokat tartalmazó termékek esetében előfordulhatnak olyan konkrét utasítások, amelyek megkövetelik, hogy frissítsen a legújabb ügynökre.

Feltörő ügynökök azonosítása és elkülönítése

A korlátozott számú ügynökkel rendelkező üzemelő példányok esetében erősen javasoljuk, hogy az ügynököt csomópontonként frissítse az alábbi felügyeleti utasítások segítségével.

A több csomóponttal rendelkező üzemelő példányok esetében írtunk egy szkriptet, amely észleli az esetlegesen feltört MMA-kat előfizetésenként, majd később frissítjük őket a legújabb verzióra. Ezeket a szkripteket egymás után kell futtatni, kezdve az UpdateMMA.ps1 és az UpgradeMMA.ps1 fájllal. A géptől függően a szkript eltarthat egy ideig. Az időtúllépés elkerülése érdekében a PowerShell 7 vagy újabb verziójára van szükség.

UpdateMMA.ps1 Ez a szkript végighalad az előfizetésekben lévő virtuális gépeken, ellenőrzi, hogy telepítve vannak-e a meglévő MMA-k, majd létrehoz egy .csv-fájlt az ügynökökről, amelyeket frissíteni kell.

UpgradeMMA.ps1 Ez a szkript a . Az UpdateMMA.ps1-ben létrehozott CSV-fájl az összes kompatibilitástörő MMA frissítéséhez.

Mindkét szkript végrehajtása eltarthat egy ideig.

# UpdateMMA.ps1
# This script is to be run per subscription, the customer has to set the az subscription before running this within the terminal scope.
# This script uses parallel processing, modify the $parallelThrottleLimit parameter to either increase or decrease the number of parallel processes
# PS> .\UpdateMMA.ps1 GetInventory
# The above command will generate a csv file with the details of VM's and VMSS that require MMA upgrade. 
# The customer can modify the csv by adding/removing rows if needed
# Update the MMA by running the script again and passing the csv file as parameter as shown below:
# PS> .\UpdateMMA.ps1 Upgrade
# If you don't want to check the inventory, then run the script wiht an additional -no-inventory-check
# PS> .\UpdateMMA.ps1 GetInventory & .\UpdateMMA.ps1 Upgrade


# This version of the script requires Powershell version >= 7 in order to improve performance via ForEach-Object -Parallel
# https://docs.microsoft.com/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/powershell/scripting/whats-new/migrating-from-windows-powershell-51-to-powershell-7?view=powershell-7.1."
    exit 1
}

$parallelThrottleLimit = 16
$mmaFixVersion = [version]"10.20.18053.0"

function GetVmsWithMMAInstalled
{
    param(
        $fileName
    )

    $vmList = az vm list --show-details --query "[?powerState=='VM running'].{ResourceGroup:resourceGroup, VmName:name}" | ConvertFrom-Json
    
    if(!$vmList)
    {
        Write-Host "Cannot get the VM list, this script can only detect the running VM's"
        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 running 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 Inventory" -PercentComplete $percent
            $vmName = $_.VmName
            $resourceGroup = $_.ResourceGroup
            $responseJson = az vm run-command invoke --command-id RunPowerShellScript --name $vmName -g $resourceGroup --scripts '@UpgradeMMA.ps1' --parameters "functionName=GetMMAVersion" --output json | ConvertFrom-Json
            if($responseJson)
            {
                $mmaVersion = $responseJson.Value[0].message
                if ($mmaVersion) 
                {
                    $extensionName = az vm extension list -g $resourceGroup --vm-name $vmName --query "[?name == 'MicrosoftMonitoringAgent'].name" | ConvertFrom-Json
                    if ($extensionName) 
                    {
                        $installType = "Extension"
                    }
                    else 
                    {
                        $installType = "Installer"
                    }
                    $csvObj = New-Object -TypeName PSObject -Property @{
                        'Name'           = $vmName
                        'Resource_Group' = $resourceGroup
                        'Resource_Type'  = "VM"
                        'Install_Type'   = $installType
                        'Version'        = $mmaVersion
                        "Instance_Id"    = ""
                    }
                    $csvObj | Export-Csv $using:fileName -Append -Force
                } 
            } 
        }
    }
}

function GetVmssWithMMAInstalled
{
    param(
        $fileName
    )

    # get the vmss list which are successfully provisioned
    $vmssList = az vmss list --query "[?provisioningState=='Succeeded'].{ResourceGroup:resourceGroup, VmssName:name}" | ConvertFrom-Json   

    $vmssCount = $vmssList.Length
    Write-Host "Detected $vmssCount Vmss running 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 Inventory" -PercentComplete $percent
        $vmssName = $_.VmssName
        $resourceGroup = $_.ResourceGroup

        # get running vmss instance ids
        $vmssInstanceIds = az vmss list-instances --resource-group $resourceGroup --name $vmssName --expand instanceView --query "[?instanceView.statuses[1].displayStatus=='VM running'].instanceId" | ConvertFrom-Json
        if ($vmssInstanceIds.Length -gt 0) 
        {
            $isMMAExtensionInstalled = az vmss extension list -g $resourceGroup --vmss-name $vmssName --query "[?name == 'MicrosoftMonitoringAgent'].name" | ConvertFrom-Json
            if ($isMMAExtensionInstalled ) 
            {
                # check an instance in vmss, if it needs an MMA upgrade. Since the extension is installed at VMSS level, checking for bad version in 1 instance should be fine.
                $responseJson = az vmss run-command invoke --command-id RunPowerShellScript --name $vmssName -g $resourceGroup --instance-id $vmssInstanceIds[0] --scripts '@UpgradeMMA.ps1' --parameters "functionName=GetMMAVersion" --output json | ConvertFrom-Json
                $mmaVersion = $responseJson.Value[0].message
                if ($mmaVersion) 
                {
                    $csvObj = New-Object -TypeName PSObject -Property @{
                        'Name'           = $vmssName
                        'Resource_Group' = $resourceGroup
                        'Resource_Type'  = "VMSS"
                        'Install_Type'   = "Extension"
                        'Version'        = $mmaVersion
                        "Instance_Id"    = ""
                    }
                    $csvObj | Export-Csv $using:fileName -Append -Force
                }
            }
            else 
            {
                foreach ($instanceId in $vmssInstanceIds) 
                {
                    $responseJson = az vmss run-command invoke --command-id RunPowerShellScript --name $vmssName -g $resourceGroup --instance-id $instanceId --scripts '@UpgradeMMA.ps1' --parameters "functionName=GetMMAVersion" --output json | ConvertFrom-Json
                    $mmaVersion = $responseJson.Value[0].message
                    if ($mmaVersion) 
                    {
                        $csvObj = New-Object -TypeName PSObject -Property @{
                            'Name'           = $vmssName
                            'Resource_Group' = $resourceGroup
                            'Resource_Type'  = "VMSS"
                            'Install_Type'   = "Installer"
                            'Version'        = $mmaVersion
                            "Instance_Id"    = $instanceId
                        }
                        $csvObj | Export-Csv $using:fileName -Append -Force
                    }
                }
            }
        }      
    }
}

function Upgrade
{
    param(
        $fileName = "MMAInventory.csv"
    )
    Import-Csv $fileName | ForEach-Object -ThrottleLimit $parallelThrottleLimit -Parallel {
        $mmaVersion = [version]$_.Version
        if($mmaVersion -lt $using:mmaFixVersion)
        {
            if ($_.Install_Type -eq "Extension") 
            {
                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 set --name MicrosoftMonitoringAgent --publisher Microsoft.EnterpriseCloud.Monitoring --force-update --vmss-name $_.Name --resource-group $_.Resource_Group --no-wait --output none
                }
                else 
                {
                    # if the extension is installed with a custom name, provide the name using the flag: --extension-instance-name <extension name>
                    az vm extension set --name MicrosoftMonitoringAgent --publisher Microsoft.EnterpriseCloud.Monitoring --force-update --vm-name $_.Name --resource-group $_.Resource_Group --no-wait --output none
                }
            }
            else {
                if ($_.Resource_Type -eq "VMSS") 
                {
                    az vmss run-command invoke --command-id RunPowerShellScript --name $_.Name -g $_.Resource_Group --instance-id $_.Instance_Id --scripts '@UpgradeMMA.ps1' --parameters "functionName=UpgradeMMA" --output none
                }
                else 
                {
                    az vm run-command invoke --command-id RunPowerShellScript --name $_.Name -g $_.Resource_Group --scripts '@UpgradeMMA.ps1' --parameters "functionName=UpgradeMMA" --output none
                }
            }
        }
    }
}

function GetInventory
{
    param(
        $fileName = "MMAInventory.csv"
    )

    # create a new file 
    New-Item -Name $fileName -ItemType File -Force
    GetVmsWithMMAInstalled $fileName
    GetVmssWithMMAInstalled $fileName
}

switch ($args.Count)
{
    0 {
        Write-Host "The arguments provided are incorrect."
        Write-Host "To get the Inventory: Run the script as: PS> .\UpdateMMA.ps1 GetInventory"
        Write-Host "To update MMA from Inventory: Run the script as: PS> .\UpdateMMA.ps1 Upgrade"
        Write-Host "To do the both steps together: PS> .\UpdateMMA.ps1 GetInventory & .\UpdateMMA.ps1 Upgrade"
    }
    1 {
        $funcname = $args[0]
        Invoke-Expression "& $funcname"
    }
    2 {
        $funcname = $args[0]
        $funcargs = $args[1]
        Invoke-Expression "& $funcname $funcargs"
    }
}