Sut i adeiladu atgyfnerthu roced ar gyfer sgriptiau PowerCLI 

Yn hwyr neu'n hwyrach, daw unrhyw weinyddwr system VMware i awtomeiddio tasgau arferol. Mae'r cyfan yn dechrau gyda'r llinell orchymyn, yna daw PowerShell neu VMware PowerCLI.

Gadewch i ni ddweud eich bod wedi meistroli PowerShell ychydig ymhellach na lansio ISE a defnyddio cmdlets safonol o fodiwlau sy'n gweithio oherwydd “rhyw fath o hud”. Pan ddechreuwch gyfrif peiriannau rhithwir yn y cannoedd, fe welwch fod sgriptiau sy'n helpu ar raddfa fach yn rhedeg yn sylweddol arafach ar raddfa fawr. 

Yn y sefyllfa hon, bydd 2 offeryn yn helpu:

  • Mannau Rhedeg PowerShell - dull sy'n eich galluogi i gyfochrog â gweithredu prosesau mewn edafedd ar wahân; 
  • Cael-Gweld – swyddogaeth PowerCLI sylfaenol, analog o Get-WMIObject yn Windows. Nid yw'r cmdlet hwn yn tynnu gwrthrychau sy'n cyd-fynd ag endidau, ond mae'n derbyn gwybodaeth ar ffurf gwrthrych syml gyda mathau syml o ddata. Mewn llawer o achosion mae'n dod allan yn gyflymach.

Nesaf, byddaf yn siarad yn fyr am bob offeryn ac yn dangos enghreifftiau o ddefnydd. Gadewch i ni ddadansoddi sgriptiau penodol a gweld pan fydd un yn gweithio'n well na'r llall. Ewch!

Sut i adeiladu atgyfnerthu roced ar gyfer sgriptiau PowerCLI

Cam cyntaf: Runspace

Felly, mae Runspace wedi'i gynllunio ar gyfer prosesu tasgau yn gyfochrog y tu allan i'r prif fodiwl. Wrth gwrs, gallwch chi lansio proses arall a fydd yn bwyta rhywfaint o gof, prosesydd, ac ati Os yw'ch sgript yn rhedeg mewn ychydig funudau ac yn defnyddio gigabeit o gof, yn fwyaf tebygol ni fydd angen Runspace arnoch chi. Ond ar gyfer sgriptiau ar gyfer degau o filoedd o wrthrychau mae ei angen.

Gallwch chi ddechrau dysgu yma: 
Dechrau Defnyddio Mannau Rhedeg PowerShell: Rhan 1

Beth mae defnyddio Runspace yn ei roi:

  • cyflymder trwy gyfyngu ar y rhestr o orchmynion a weithredir,
  • cyflawni tasgau yn gyfochrog,
  • diogelwch.

Dyma enghraifft o'r Rhyngrwyd pan fydd Runspace yn helpu:

“Mae cynnen storio yn un o’r metrigau anoddaf i’w olrhain yn vSphere. Y tu mewn i vCenter, ni allwch fynd i weld pa VM sy'n defnyddio mwy o adnoddau storio. Yn ffodus, gallwch chi gasglu'r data hwn mewn munudau diolch i PowerShell.
Byddaf yn rhannu sgript a fydd yn caniatáu i weinyddwyr system VMware chwilio'n gyflym trwy vCenter a derbyn rhestr o VMs gyda data ar eu defnydd cyfartalog.  
Mae'r sgript yn defnyddio mannau rhedeg PowerShell i ganiatáu i bob gwesteiwr ESXi gasglu gwybodaeth am ddefnydd o'i VMs ei hun mewn Runspace ar wahân ac adrodd ar gwblhau ar unwaith. Mae hyn yn caniatáu i PowerShell gau swyddi ar unwaith, yn hytrach nag ailadrodd trwy westeion ac aros i bob un gwblhau ei gais. ”

Ffynhonnell: Sut i Ddangos Peiriant Rhithwir I/O ar Ddangosfwrdd ESXi

Yn yr achos isod, nid yw Runspace bellach yn ddefnyddiol:

“Rwy’n ceisio ysgrifennu sgript sy’n casglu llawer o ddata o VM ac yn ysgrifennu data newydd pan fo angen. Y broblem yw bod yna gryn dipyn o VMs, ac mae 5-8 eiliad yn cael eu gwario ar un peiriant.” 

Ffynhonnell: PowerCLI Multithreading gyda RunspacePool

Yma bydd angen Get-View arnoch chi, gadewch i ni symud ymlaen ato. 

Ail gam: Get-View

Er mwyn deall pam mae Get-View yn ddefnyddiol, mae'n werth cofio sut mae cmdlets yn gweithio'n gyffredinol. 

Mae angen Cmdlets i gael gwybodaeth yn gyfleus heb fod angen astudio cyfeirlyfrau API ac ailddyfeisio'r olwyn nesaf. Beth yn yr hen ddyddiau a gymerodd gant neu ddau o linellau o god, mae PowerShell yn caniatáu ichi wneud gydag un gorchymyn. Rydym yn talu am y cyfleustra hwn gyda chyflymder. Nid oes unrhyw hud y tu mewn i'r cmdlets eu hunain: yr un sgript, ond ar lefel is, wedi'i hysgrifennu gan ddwylo medrus meistr o India heulog.

Nawr, er mwyn cymharu â Get-View, gadewch i ni gymryd y cmdlet Get-VM: mae'n cyrchu'r peiriant rhithwir ac yn dychwelyd gwrthrych cyfansawdd, hynny yw, mae'n cysylltu gwrthrychau cysylltiedig eraill ag ef: VMHost, Datastore, ac ati.  

Nid yw Get-View yn ei le yn ychwanegu unrhyw beth diangen at y gwrthrych a ddychwelwyd. Ar ben hynny, mae'n caniatáu inni nodi'n fanwl pa wybodaeth sydd ei hangen arnom, a fydd yn gwneud y gwrthrych allbwn yn haws. Yn Windows Server yn gyffredinol ac yn Hyper-V yn arbennig, mae cmdlet Get-WMIObject yn analog uniongyrchol - mae'r syniad yn union yr un fath.

Mae Get-View yn anghyfleus ar gyfer gweithrediadau arferol ar wrthrychau pwynt. Ond pan ddaw i filoedd a degau o filoedd o wrthrychau, nid oes ganddo unrhyw bris.

Gallwch ddarllen mwy ar y blog VMware: Cyflwyniad i Get-View

Nawr byddaf yn dangos popeth i chi gan ddefnyddio cas go iawn. 

Ysgrifennu sgript i ddadlwytho VM

Un diwrnod gofynnodd fy nghydweithiwr imi wneud y gorau o'i sgript. Mae'r dasg yn drefn gyffredin: dewch o hyd i bob VM gyda pharamedr cloud.uuid dyblyg (ie, mae hyn yn bosibl wrth glonio VM yn vCloud Director). 

Yr ateb amlwg sy'n dod i'r meddwl yw:

  1. Cael rhestr o'r holl VMs.
  2. Dosrannu'r rhestr rywsut.

Y fersiwn wreiddiol oedd y sgript syml hon:

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
}
# Далее РУКАМИ парсим полученный результат

Mae popeth yn hynod o syml a chlir. Gellir ei ysgrifennu mewn cwpl o funudau gydag egwyl goffi. Sgriwiwch ar y hidlydd ac mae wedi'i wneud.

Ond gadewch i ni fesur yr amser:

Sut i adeiladu atgyfnerthu roced ar gyfer sgriptiau PowerCLI

Sut i adeiladu atgyfnerthu roced ar gyfer sgriptiau PowerCLI

2 munud 47 eiliad wrth brosesu bron i 10k VMs. Bonws yw absenoldeb hidlwyr a'r angen i ddidoli'r canlyniadau â llaw. Yn amlwg, mae angen optimeiddio ar y sgript.

Mannau rhedeg yw'r rhai cyntaf i ddod i'r adwy pan fydd angen i chi gael metrigau gwesteiwr o vCenter ar yr un pryd neu pan fydd angen i chi brosesu degau o filoedd o wrthrychau. Gawn ni weld beth ddaw yn sgil y dull hwn.

Trowch y cyflymder cyntaf ymlaen: PowerShell Runspaces

Y peth cyntaf sy'n dod i'r meddwl ar gyfer y sgript hon yw gweithredu'r ddolen nid yn ddilyniannol, ond mewn edafedd cyfochrog, casglwch yr holl ddata yn un gwrthrych a'i hidlo. 

Ond mae yna broblem: ni fydd PowerCLI yn caniatáu inni agor llawer o sesiynau annibynnol i vCenter a bydd yn taflu gwall doniol:

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.

I ddatrys hyn, yn gyntaf rhaid i chi basio gwybodaeth sesiwn y tu mewn i'r ffrwd. Gadewch inni gofio bod PowerShell yn gweithio gyda gwrthrychau y gellir eu trosglwyddo fel paramedr naill ai i swyddogaeth neu i ScriptBlock. Gadewch i ni basio'r sesiwn ar ffurf gwrthrych o'r fath, gan osgoi $global:DefaultVIServers (Connect-VIServer gyda'r allwedd -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 $_
           }
       }
   }

Nawr, gadewch i ni weithredu multithreading trwy Runspace Pools.  

Mae'r algorithm fel a ganlyn:

  1. Rydym yn cael rhestr o'r holl VMs.
  2. Mewn ffrydiau cyfochrog cawn cloud.uuid.
  3. Rydym yn casglu data o ffrydiau i un gwrthrych.
  4. Rydyn ni'n hidlo'r gwrthrych trwy ei grwpio yn ôl gwerth y maes CloudUUID: y rhai lle mae nifer y gwerthoedd unigryw yn fwy nag 1 yw'r VMs rydyn ni'n edrych amdanyn nhw.

O ganlyniad, rydym yn cael y sgript:


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
}

Harddwch y sgript hon yw y gellir ei ddefnyddio mewn achosion tebyg eraill trwy ddisodli'r ScriptBlock a'r paramedrau a fydd yn cael eu trosglwyddo i'r nant. Manteisiwch arno!

Rydym yn mesur amser:

Sut i adeiladu atgyfnerthu roced ar gyfer sgriptiau PowerCLI

55 eiliad. Mae'n well, ond gall fod yn gyflymach o hyd. 

Gadewch i ni symud i'r ail gyflymder: GetView

Gadewch i ni ddarganfod beth sy'n bod.
Yn gyntaf ac yn bennaf, mae cmdlet Get-VM yn cymryd amser hir i'w weithredu.
Yn ail, mae cmdlet Get-AdvancedOptions yn cymryd hyd yn oed yn hirach i'w gwblhau.
Gadewch i ni ddelio â'r ail un yn gyntaf. 

Mae Get-AdvancedOptions yn gyfleus ar gyfer gwrthrychau VM unigol, ond yn drwsgl iawn wrth weithio gyda llawer o wrthrychau. Gallwn gael yr un wybodaeth o'r gwrthrych peiriant rhithwir ei hun (Get-VM). Mae newydd ei gladdu'n dda yn y gwrthrych ExtensionData. Gyda hidlo, rydym yn cyflymu'r broses o gael y data angenrheidiol.

Gyda symudiad bach yn y llaw dyma:


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

Yn troi i mewn i hyn:


$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}}

Mae'r allbwn yr un peth â Get-AdvancedOptions, ond mae'n gweithio lawer gwaith yn gyflymach. 

Nawr i Get-VM. Nid yw'n gyflym oherwydd ei fod yn delio â gwrthrychau cymhleth. Mae cwestiwn rhesymegol yn codi: pam mae angen gwybodaeth ychwanegol a PSO gwrthun gwrthun yn yr achos hwn, pan mai dim ond enw'r VM sydd ei angen arnom, ei gyflwr a gwerth priodoledd anodd?  

Yn ogystal, mae'r rhwystr ar ffurf Get-AdvancedOptions wedi'i dynnu o'r sgript. Mae defnyddio Runspace Pools bellach yn ymddangos yn ormod gan nad oes angen mwyach i gyfochrog â thasg araf ar draws edafedd sgwat wrth drosglwyddo sesiwn. Mae'r offeryn yn dda, ond nid ar gyfer yr achos hwn. 

Gadewch i ni edrych ar allbwn ExtensionData: nid yw'n ddim mwy na gwrthrych Get-View. 

Gadewch i ni alw ar dechneg hynafol y meistri PowerShell: un llinell gan ddefnyddio hidlwyr, didoli a grwpio. Mae'r holl arswyd blaenorol yn cael ei chwalu'n gain i un llinell a'i weithredu mewn un sesiwn:


$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

Rydym yn mesur amser:

Sut i adeiladu atgyfnerthu roced ar gyfer sgriptiau PowerCLI

Eiliadau 9 ar gyfer bron i 10k o wrthrychau gyda hidlo yn ôl y cyflwr dymunol. Gwych!

Yn hytrach na i gasgliad

Mae canlyniad derbyniol yn dibynnu'n uniongyrchol ar y dewis o offeryn. Yn aml mae'n anodd dweud yn sicr beth yn union y dylid ei ddewis i'w gyflawni. Mae pob un o'r dulliau a restrir ar gyfer cyflymu sgriptiau yn dda o fewn terfynau ei gymhwysedd. Rwy'n gobeithio y bydd yr erthygl hon yn eich helpu yn y dasg anodd o ddeall hanfodion awtomeiddio prosesau ac optimeiddio yn eich seilwaith.

PS: Mae'r awdur yn diolch i holl aelodau'r gymuned am eu cymorth a'u cefnogaeth wrth baratoi'r erthygl. Hyd yn oed y rhai sydd â phawennau. A hyd yn oed y rhai nad oes ganddyn nhw goesau, fel boa constrictor.

Ffynhonnell: hab.com

Ychwanegu sylw