Kif tibni rocket booster għall-iskripts PowerCLI 

Illum jew għada, kwalunkwe amministratur tas-sistema VMware jasal biex awtomat kompiti ta' rutina. Kollox jibda bil-linja tal-kmand, imbagħad jiġi PowerShell jew VMware PowerCLI.

Ejja ngħidu li ħakmu PowerShell ftit aktar milli tniedi ISE u tuża cmdlets standard minn moduli li jaħdmu minħabba "xi tip ta 'maġija". Meta tibda tgħodd il-magni virtwali fil-mijiet, issib li skripts li jgħinu fuq skala żgħira jimxu notevolment aktar bil-mod fuq skala kbira. 

F'din is-sitwazzjoni, 2 għodod se jgħinu:

  • PowerShell Runspaces – approċċ li jippermettilek li titqabbel l-eżekuzzjoni tal-proċessi f'ħjut separati; 
  • Get-View – funzjoni PowerCLI bażika, analoga ta' Get-WMIObject fil-Windows. Dan is-cmdlet ma jiġbedx oġġetti li jakkumpanjaw l-entitajiet, iżda jirċievi informazzjoni fil-forma ta 'oġġett sempliċi b'tipi ta' data sempliċi. F'ħafna każijiet toħroġ aktar malajr.

Sussegwentement, ser nitkellem fil-qosor dwar kull għodda u nuri eżempji ta 'użu. Ejja nanalizzaw skripts speċifiċi u naraw meta wieħed jaħdem aħjar mill-ieħor. Mur!

Kif tibni rocket booster għall-iskripts PowerCLI

L-ewwel stadju: Runspace

Allura, Runspace huwa ddisinjat għall-ipproċessar parallel ta 'kompiti barra l-modulu prinċipali. Naturalment, tista 'tniedi proċess ieħor li jiekol xi memorja, proċessur, eċċ. Jekk l-iskript tiegħek jibda fi ftit minuti u jikkonsma gigabyte ta' memorja, x'aktarx ma jkollokx bżonn Runspace. Iżda għal skripts għal għexieren ta 'eluf ta' oġġetti huwa meħtieġ.

Tista' tibda titgħallem hawn: 
Bidu ta' Użu ta' PowerShell Runspaces: Parti 1

X'jagħti l-użu ta' Runspace:

  • veloċità billi tillimita l-lista ta 'kmandi esegwiti,
  • eżekuzzjoni parallela tal-kompiti,
  • sigurtà.

Hawn eżempju mill-Internet meta Runspace jgħin:

“Il-kontenzjoni tal-ħażna hija waħda mill-aktar metriċi diffiċli biex tiġi segwita f’vSphere. Ġewwa vCenter, ma tistax sempliċement tmur tara liema VM qed tikkonsma aktar riżorsi tal-ħażna. Fortunatament, tista 'tiġbor din id-dejta fi ftit minuti grazzi għal PowerShell.
Se naqsam skript li se jippermetti lill-amministraturi tas-sistema VMware biex ifittxu malajr madwar vCenter u jirċievu lista ta 'VMs b'dejta dwar il-konsum medju tagħhom.  
L-iskript juża runspaces PowerShell biex jippermetti lil kull host ESXi jiġbor informazzjoni dwar il-konsum mill-VMs tiegħu stess fi Runspace separat u jirrapporta immedjatament it-tlestija. Dan jippermetti lil PowerShell jagħlaq l-impjiegi immedjatament, aktar milli jtenni permezz tal-hosts u jistenna li kull wieħed itemm it-talba tiegħu.

Sors: Kif Uri I/O tal-Magni Virtwali fuq Dashboard ESXi

Fil-każ hawn taħt, Runspace m'għadux utli:

“Qed nipprova nikteb script li jiġbor ħafna dejta minn VM u jikteb dejta ġdida meta jkun meħtieġ. Il-problema hija li hemm ħafna VMs, u 5-8 sekondi jintefqu fuq magna waħda." 

Sors: Multithreading PowerCLI ma RunspacePool

Hawnhekk ser ikollok bżonn Get-View, ejja nimxu fuqha. 

It-tieni stadju: Get-View

Biex tifhem għaliex Get-View huwa utli, ta 'min jiftakar kif jaħdmu s-cmdlets b'mod ġenerali. 

Cmdlets huma meħtieġa biex tinkiseb informazzjoni b'mod konvenjenti mingħajr il-ħtieġa li tistudja l-kotba ta 'referenza tal-API u tivvinta mill-ġdid ir-rota li jmiss. Dak li fl-antik ħa mija jew żewġ linji ta 'kodiċi, PowerShell jippermettilek li tagħmel bi kmand wieħed. Aħna nħallsu għal din il-konvenjenza b'ħeffa. M'hemm l-ebda maġija ġewwa ċ-cmdlets infushom: l-istess skript, iżda f'livell aktar baxx, miktub minn idejn skillful ta 'kaptan mill-Indja xemxija.

Issa, għal tqabbil ma 'Get-View, ejja nieħdu l-cmdlet Get-VM: jaċċessa l-magna virtwali u jirritorna oġġett kompost, jiġifieri, jehmeż oġġetti oħra relatati miegħu: VMHost, Datastore, eċċ.  

Get-View fil-post tagħha ma żżid xejn mhux meħtieġ għall-oġġett ritornat. Barra minn hekk, jippermettilna nispeċifikaw b'mod strett liema informazzjoni neħtieġu, li se tagħmel l-oġġett tal-ħruġ aktar faċli. Fil-Windows Server b'mod ġenerali u f'Hyper-V b'mod partikolari, is-cmdlet Get-WMIObject huwa analogu dirett - l-idea hija eżattament l-istess.

Get-View huwa inkonvenjenti għal operazzjonijiet ta 'rutina fuq oġġetti punt. Imma meta niġu għall-eluf u għexieren ta 'eluf ta' oġġetti, m'għandu l-ebda prezz.

Tista' taqra aktar fuq il-blog ta' VMware: Introduzzjoni għal Get-View

Issa ser nuruk kollox billi tuża każ reali. 

Kitba ta' skript biex tniżżel VM

Ġurnata waħda l-kollega tiegħi talabni nottimizza l-iskript tiegħu. Il-kompitu huwa rutina komuni: sib il-VMs kollha b'parametru cloud.uuid duplikat (iva, dan huwa possibbli meta tikklona VM f'vCloud Director). 

Is-soluzzjoni ovvja li tiġi f'moħħna hija:

  1. Ikseb lista tal-VMs kollha.
  2. Analiżi l-lista b'xi mod.

Il-verżjoni oriġinali kienet din l-iskrittura sempliċi:

function Get-CloudUUID1 {
   # Получаем список всех ВМ
   $vms = Get-VM
   $report = @()

   # Обрабатываем каждый объект, получая из него только 2 свойства: Имя ВМ и Cloud UUID.
   # Заносим данные в новый PS-объект с полями VM и UUID
   foreach ($vm in $vms)
   {
       $table = "" | select VM,UUID

       $table.VM = $vm.name
       $table.UUID = ($vm | Get-AdvancedSetting -Name cloud.uuid).Value
          
       $report += $table
   }
# Возвращаем все объекты
   $report
}
# Далее РУКАМИ парсим полученный результат

Kollox huwa estremament sempliċi u ċar. Jista 'jinkiteb fi ftit minuti b'waqfa għall-kafè. Invita l-filtrazzjoni u lest.

Imma ejja nkejlu l-ħin:

Kif tibni rocket booster għall-iskripts PowerCLI

Kif tibni rocket booster għall-iskripts PowerCLI

2 minuti 47 sekonda meta tipproċessa kważi 10k VMs. Bonus huwa n-nuqqas ta 'filtri u l-ħtieġa li manwalment issolvi r-riżultati. Ovvjament, l-iskrittura teħtieġ ottimizzazzjoni.

Runspaces huma l-ewwel li jiġu għas-salvataġġ meta jkollok bżonn simultanjament tikseb metriċi ospitanti minn vCenter jew ikollok bżonn tipproċessa għexieren ta 'eluf ta' oġġetti. Ejja naraw x'iġib dan l-approċċ.

Ixgħel l-ewwel veloċità: PowerShell Runspaces

L-ewwel ħaġa li tiġi f'moħħna għal din l-iskrittura hija li tesegwixxi l-linja mhux b'mod sekwenzjali, iżda f'ħjut paralleli, tiġbor id-dejta kollha f'oġġett wieħed u tiffiltraha. 

Iżda hemm problema: PowerCLI mhux se jippermettilna niftħu ħafna sessjonijiet indipendenti għal vCenter u se tarmi żball umoristiċi:

You have modified the global:DefaultVIServer and global:DefaultVIServers system variables. This is not allowed. Please reset them to $null and reconnect to the vSphere server.

Biex issolvi dan, l-ewwel trid tgħaddi l-informazzjoni tas-sessjoni ġewwa l-fluss. Ejja niftakru li PowerShell jaħdem ma 'oġġetti li jistgħu jiġu mgħoddija bħala parametru jew għal funzjoni jew għal ScriptBlock. Ejja ngħaddu s-sessjoni fil-forma ta' oġġett bħal dan, billi taqbeż $global:DefaultVIServers (Connect-VIServer biċ-ċavetta -NotDefault):

$ConnectionString = @()
foreach ($vCenter in $vCenters)
   {
       try {
           $ConnectionString += Connect-VIServer -Server $vCenter -Credential $Credential -NotDefault -AllLinked -Force -ErrorAction stop -WarningAction SilentlyContinue -ErrorVariable er
       }
       catch {
           if ($er.Message -like "*not part of a linked mode*")
           {
               try {
                   $ConnectionString += Connect-VIServer -Server $vCenter -Credential $Credential -NotDefault -Force -ErrorAction stop -WarningAction SilentlyContinue -ErrorVariable er
               }
               catch {
                   throw $_
               }
              
           }
           else {
               throw $_
           }
       }
   }

Issa ejja nimplimentaw multithreading permezz Runspace Pools.  

L-algoritmu huwa kif ġej:

  1. Ikollna lista tal-VMs kollha.
  2. Fi flussi paralleli nikbru cloud.uuid.
  3. Aħna niġbru data minn flussi f'oġġett wieħed.
  4. Aħna niffiltraw l-oġġett billi niġbruh bil-valur tal-qasam CloudUUID: dawk fejn in-numru ta 'valuri uniċi huwa akbar minn 1 huma l-VMs li qed infittxu.

Bħala riżultat, aħna nikseb l-iskrittura:


function Get-VMCloudUUID {
   param (
       [string[]]
       [ValidateNotNullOrEmpty()]
       $vCenters = @(),
       [int]$MaxThreads,
       [System.Management.Automation.PSCredential]
       [System.Management.Automation.Credential()]
       $Credential
   )

   $ConnectionString = @()

   # Создаем объект с сессионным ключом
   foreach ($vCenter in $vCenters)
   {
       try {
           $ConnectionString += Connect-VIServer -Server $vCenter -Credential $Credential -NotDefault -AllLinked -Force -ErrorAction stop -WarningAction SilentlyContinue -ErrorVariable er
       }
       catch {
           if ($er.Message -like "*not part of a linked mode*")
           {
               try {
                   $ConnectionString += Connect-VIServer -Server $vCenter -Credential $Credential -NotDefault -Force -ErrorAction stop -WarningAction SilentlyContinue -ErrorVariable er
               }
               catch {
                   throw $_
               }
              
           }
           else {
               throw $_
           }
       }
   }

   # Получаем список всех ВМ
   $Global:AllVMs = Get-VM -Server $ConnectionString

   # Поехали!
   $ISS = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
   $RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads, $ISS, $Host)
   $RunspacePool.ApartmentState = "MTA"
   $RunspacePool.Open()
   $Jobs = @()

# ScriptBlock с магией!)))
# Именно он будет выполняться в потоке
   $scriptblock = {
       Param (
       $ConnectionString,
       $VM
       )

       $Data = $VM | Get-AdvancedSetting -Name Cloud.uuid -Server $ConnectionString | Select-Object @{N="VMName";E={$_.Entity.Name}},@{N="CloudUUID";E={$_.Value}},@{N="PowerState";E={$_.Entity.PowerState}}

       return $Data
   }
# Генерируем потоки

   foreach($VM in $AllVMs)
   {
       $PowershellThread = [PowerShell]::Create()
# Добавляем скрипт
       $null = $PowershellThread.AddScript($scriptblock)
# И объекты, которые передадим в качестве параметров скрипту
       $null = $PowershellThread.AddArgument($ConnectionString)
       $null = $PowershellThread.AddArgument($VM)
       $PowershellThread.RunspacePool = $RunspacePool
       $Handle = $PowershellThread.BeginInvoke()
       $Job = "" | Select-Object Handle, Thread, object
       $Job.Handle = $Handle
       $Job.Thread = $PowershellThread
       $Job.Object = $VM.ToString()
       $Jobs += $Job
   }

# Ставим градусник, чтобы наглядно отслеживать выполнение заданий
# И здесь же прибиваем отработавшие задания
   While (@($Jobs | Where-Object {$_.Handle -ne $Null}).count -gt 0)
   {
       $Remaining = "$($($Jobs | Where-Object {$_.Handle.IsCompleted -eq $False}).object)"

       If ($Remaining.Length -gt 60) {
           $Remaining = $Remaining.Substring(0,60) + "..."
       }

       Write-Progress -Activity "Waiting for Jobs - $($MaxThreads - $($RunspacePool.GetAvailableRunspaces())) of $MaxThreads threads running" -PercentComplete (($Jobs.count - $($($Jobs | Where-Object {$_.Handle.IsCompleted -eq $False}).count)) / $Jobs.Count * 100) -Status "$(@($($Jobs | Where-Object {$_.Handle.IsCompleted -eq $False})).count) remaining - $remaining"

       ForEach ($Job in $($Jobs | Where-Object {$_.Handle.IsCompleted -eq $True})){
           $Job.Thread.EndInvoke($Job.Handle)     
           $Job.Thread.Dispose()
           $Job.Thread = $Null
           $Job.Handle = $Null
       }
   }

   $RunspacePool.Close() | Out-Null
   $RunspacePool.Dispose() | Out-Null
}


function Get-CloudUUID2
{
   [CmdletBinding()]
   param(
   [string[]]
   [ValidateNotNullOrEmpty()]
   $vCenters = @(),
   [int]$MaxThreads = 50,
   [System.Management.Automation.PSCredential]
   [System.Management.Automation.Credential()]
   $Credential)

   if(!$Credential)
   {
       $Credential = Get-Credential -Message "Please enter vCenter credentials."
   }

   # Вызов функции Get-VMCloudUUID, где мы распараллеливаем операцию
   $AllCloudVMs = Get-VMCloudUUID -vCenters $vCenters -MaxThreads $MaxThreads -Credential $Credential
   $Result = $AllCloudVMs | Sort-Object Value | Group-Object -Property CloudUUID | Where-Object -FilterScript {$_.Count -gt 1} | Select-Object -ExpandProperty Group
   $Result
}

Is-sbuħija ta 'din l-iskrittura hija li tista' tintuża f'każijiet simili oħra billi sempliċement tissostitwixxi l-ScriptBlock u l-parametri li se jiġu mgħoddija lill-fluss. Sfruttaha!

Aħna nkejlu l-ħin:

Kif tibni rocket booster għall-iskripts PowerCLI

55 sekondi. Huwa aħjar, iżda xorta jista 'jkun aktar mgħaġġel. 

Ejja nimxu għat-tieni veloċità: GetView

Ejja nsiru nafu x'inhu ħażin.
L-ewwel u qabel kollox, is-cmdlet Get-VM jieħu ħafna żmien biex jiġi eżegwit.
It-tieni, is-cmdlet Get-AdvancedOptions jieħu saħansitra aktar żmien biex jitlesta.
Ejja nittrattaw it-tieni l-ewwel. 

Get-AdvancedOptions huwa konvenjenti għal oġġetti VM individwali, iżda goff ħafna meta taħdem ma 'ħafna oġġetti. Nistgħu niksbu l-istess informazzjoni mill-oġġett tal-magna virtwali innifsu (Get-VM). Huwa biss midfun sew fl-oġġett ExtensionData. Armati b'filtrazzjoni, aħna nħaffu l-proċess biex niksbu d-dejta meħtieġa.

B'ċaqliq żgħir ta 'l-idejn dan huwa:


VM | Get-AdvancedSetting -Name Cloud.uuid -Server $ConnectionString | Select-Object @{N="VMName";E={$_.Entity.Name}},@{N="CloudUUID";E={$_.Value}},@{N="PowerState";E={$_.Entity.PowerState}}

Jidawwar f'dan:


$VM | Where-Object {($_.ExtensionData.Config.ExtraConfig | Where-Object {$_.key -eq "cloud.uuid"}).Value -ne $null} | Select-Object @{N="VMName";E={$_.Name}},@{N="CloudUUID";E={($_.ExtensionData.Config.ExtraConfig | Where-Object {$_.key -eq "cloud.uuid"}).Value}},@{N="PowerState";E={$_.summary.runtime.powerstate}}

L-output huwa l-istess bħal Get-AdvancedOptions, iżda jaħdem ħafna drabi aktar malajr. 

Issa biex Get-VM. Mhuwiex mgħaġġel għax jittratta oġġetti kumplessi. Tqum mistoqsija loġika: għaliex għandna bżonn informazzjoni żejda u PSObject mostruż f'dan il-każ, meta għandna bżonn biss l-isem tal-VM, l-istat tagħha u l-valur ta 'attribut delikat?  

Barra minn hekk, l-ostaklu fil-forma ta 'Get-AdvancedOptions tneħħa mill-iskript. L-użu ta 'Runspace Pools issa jidher qisu żejjed peress li m'għadx hemm bżonn li jiġi parallelizzat kompitu bil-mod fuq ħjut squat meta tgħaddi sessjoni. L-għodda hija tajba, iżda mhux għal dan il-każ. 

Ejja nħarsu lejn l-output ta 'ExtensionData: huwa xejn aktar minn oġġett Get-View. 

Ejja nsejħu fuq it-teknika antika tal-kaptani tal-PowerShell: linja waħda li tuża filtri, issortjar u raggruppament. L-orrur ta 'qabel kollu huwa kkollassat b'mod eleganti f'linja waħda u eżegwit f'sessjoni waħda:


$AllVMs = Get-View -viewtype VirtualMachine -Property Name,Config.ExtraConfig,summary.runtime.powerstate | Where-Object {($_.Config.ExtraConfig | Where-Object {$_.key -eq "cloud.uuid"}).Value -ne $null} | Select-Object @{N="VMName";E={$_.Name}},@{N="CloudUUID";E={($_.Config.ExtraConfig | Where-Object {$_.key -eq "cloud.uuid"}).Value}},@{N="PowerState";E={$_.summary.runtime.powerstate}} | Sort-Object CloudUUID | Group-Object -Property CloudUUID | Where-Object -FilterScript {$_.Count -gt 1} | Select-Object -ExpandProperty Group

Aħna nkejlu l-ħin:

Kif tibni rocket booster għall-iskripts PowerCLI

9 sekondi għal kważi 10k oġġetti b'filtrazzjoni mill-kundizzjoni mixtieqa. Kbir!

Minflok ma tikkonkludi

Riżultat aċċettabbli jiddependi direttament fuq l-għażla tal-għodda. Ħafna drabi huwa diffiċli li wieħed jgħid ċert x'għandu jintgħażel eżatt biex dan jintlaħaq. Kull wieħed mill-metodi elenkati biex jitħaffu l-iskripts huwa tajjeb fil-limiti tal-applikabbiltà tiegħu. Nittama li dan l-artikolu jgħinek fil-kompitu diffiċli li tifhem il-baŜi tal-awtomazzjoni u l-ottimizzazzjoni tal-proċess fl-infrastruttura tiegħek.

PS: L-awtur jirringrazzja lill-membri kollha tal-komunità għall-għajnuna u l-appoġġ tagħhom fit-tħejjija tal-artiklu. Anke dawk bis-saqajn. U anke dawk li m'għandhomx saqajn, bħal boa constrictor.

Sors: www.habr.com

Żid kumment