Kumaha carana ngawangun booster rokét pikeun skrip PowerCLI 

Moal lami deui atanapi engké, sagala administrator sistem VMware datang ka ngajadikeun otomatis tugas rutin. Éta sadayana dimimitian ku garis paréntah, teras sumping PowerShell atanapi VMware PowerCLI.

Anggap anjeun parantos ngawasa PowerShell sakedik langkung jauh ti ngaluncurkeun ISE sareng nganggo cmdlet standar tina modul anu tiasa dianggo kusabab "sababaraha jinis sihir". Lamun anjeun ngawitan cacah mesin virtual dina ratusan, anjeun bakal manggihan yén Aksara nu mantuan kaluar dina skala leutik ngajalankeun noticeably laun dina skala badag. 

Dina kaayaan ieu, 2 alat bakal ngabantosan:

  • PowerShell Runspaces - pendekatan anu ngamungkinkeun anjeun parallelize palaksanaan prosés dina threads misah; 
  • Meunang-Témbongkeun - fungsi dasar PowerCLI, analog tina Get-WMIObject dina Windows. Cmdlet ieu henteu narik obyék anu ngiringan éntitas, tapi nampi inpormasi dina bentuk obyék anu sederhana sareng jinis data anu sederhana. Dina loba kasus eta kaluar gancang.

Salajengna, kuring bakal ngobrol sakeudeung ngeunaan unggal alat sareng nunjukkeun conto pamakean. Hayu urang analisa skrip khusus sareng tingali nalika hiji damel langkung saé tibatan anu sanés. indit!

Kumaha carana ngawangun booster rokét pikeun skrip PowerCLI

Tahap kahiji: Runspace

Janten, Runspace dirancang pikeun ngolah paralel tugas di luar modul utama. Tangtosna, anjeun tiasa ngaluncurkeun prosés sanés anu bakal ngahakan mémori, prosésor, jsb. Upami skrip anjeun dijalankeun dina sababaraha menit sareng nganggo mémori gigabyte, kamungkinan anjeun henteu peryogi Runspace. Tapi pikeun naskah pikeun puluhan rébu objék diperlukeun.

Anjeun tiasa ngamimitian diajar di dieu: 
Mimiti Pamakéan PowerShell Runspaces: Bagian 1

Naon anu nganggo Runspace masihan:

  • gancang ku ngawatesan daptar paréntah anu dieksekusi,
  • palaksanaan tugas paralel,
  • kaamanan.

Ieu conto tina Internét nalika Runspace ngabantosan:

"Pertentangan Panyimpen mangrupikeun salah sahiji métrik anu paling hese pikeun dilacak dina vSphere. Di jero vCenter, anjeun moal tiasa ngan ukur ningali VM mana anu nganggo sumber panyimpen langkung seueur. Kabeneran, anjeun tiasa ngumpulkeun data ieu dina sababaraha menit berkat PowerShell.
Kuring baris babagi hiji naskah anu bakal ngidinan pangurus sistem VMware gancang neangan sakuliah vCenter sarta tampa petunjuk daptar VMs kalawan data dina konsumsi rata maranéhna.  
Skrip ngagunakeun PowerShell runspaces pikeun ngidinan unggal host ESXi ngumpulkeun informasi konsumsi ti VMs sorangan dina Runspace misah tur geuwat ngalaporkeun parantosan. Hal ieu ngamungkinkeun PowerShell pikeun nutup padamelan langsung, tinimbang ngaliwat host sareng ngantosan masing-masing ngalengkepan pamundutna.

sumber: Kumaha Témbongkeun Mesin Virtual I / O dina Dashboard ESXi

Dina kasus di handap ieu, Runspace henteu kapaké deui:

"Kuring nyobian nyerat naskah anu ngumpulkeun seueur data tina VM sareng nyerat data énggal upami diperyogikeun. Masalahna nyaeta aya cukup loba VMs, sarta 5-8 detik spent dina hiji mesin. 

sumber: Multithreading PowerCLI kalawan RunspacePool

Di dieu anjeun peryogi Get-View, hayu urang teraskeun. 

Tahap kadua: Get-View

Pikeun ngartos naha Get-View mangpaat, éta patut émut kumaha cmdlet sacara umum dianggo. 

Cmdlet diperlukeun pikeun merenah meunangkeun informasi tanpa kudu diajar buku rujukan API tur reinvent kabayang salajengna. Naon dina jaman baheula nyandak saratus atanapi dua baris kode, PowerShell ngamungkinkeun anjeun ngalakukeun sareng hiji paréntah. Urang mayar genah ieu kalawan speed. Henteu aya sihir dina jero cmdlet sorangan: naskah anu sami, tapi dina tingkat anu langkung handap, ditulis ku panangan terampil master ti India anu cerah.

Ayeuna, pikeun ngabandingkeun sareng Get-View, hayu urang nyandak cmdlet Get-VM: éta ngaksés mesin virtual sareng mulangkeun obyék komposit, nyaéta, ngagantelkeun objék anu aya hubunganana: VMHost, Datastore, jsb.  

Meunang-Témbongkeun dina tempatna henteu nambihan nanaon anu teu dipikabutuh pikeun objék anu dipulangkeun. Leuwih ti éta, éta ngamungkinkeun urang pikeun mastikeun nangtukeun informasi naon urang kudu, nu bakal nyieun objék kaluaran gampang. Dina Windows Server sacara umum sareng dina Hyper-V khususna, Get-WMIObject cmdlet mangrupikeun analog langsung - idena sami.

Meunang-Témbongkeun teu merenah pikeun operasi rutin dina objék titik. Tapi lamun datang ka rébuan sarta puluhan rébu objék, teu boga harga.

Anjeun tiasa maca langkung seueur dina blog VMware: Bubuka pikeun Meunangkeun-Témbongkeun

Ayeuna kuring bakal nunjukkeun anjeun sadayana nganggo kasus nyata. 

Nulis naskah pikeun ngabongkar momotanana VM

Hiji poé batur sapagawean kuring nanya ka kuring pikeun ngaoptimalkeun naskah na. tugas téh rutin umum: manggihan sakabeh VMs kalawan duplikat cloud.uuid parameter (enya, ieu mungkin lamun kloning a VM di vCloud Diréktur). 

Solusi anu jelas anu aya dina pikiran nyaéta:

  1. Meunang daptar sadaya VMs.
  2. Parse daptar kumaha bae.

Versi aslina nyaéta naskah basajan ieu:

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

Sagalana pisan basajan tur jelas. Éta tiasa ditulis dina sababaraha menit sareng istirahat kopi. Screw on filtration jeung geus rengse.

Tapi hayu urang ngukur waktos:

Kumaha carana ngawangun booster rokét pikeun skrip PowerCLI

Kumaha carana ngawangun booster rokét pikeun skrip PowerCLI

2 menit 47 detik nalika ngolah ampir 10k VMs. Bonus nyaéta henteuna saringan sareng kabutuhan sacara manual nyortir hasil. Jelas, naskah merlukeun optimasi.

Runspaces anu pangheulana datang ka nyalametkeun mun anjeun kudu sakaligus ménta metrics host ti vCenter atawa kudu ngolah puluhan rébu objék. Hayu urang tingali naon pendekatan ieu brings.

Hurungkeun laju kahiji: PowerShell Runspaces

Hal kahiji anu datang ka pikiran pikeun naskah ieu ngajalankeun loop teu sequentially, tapi dina threads paralel, ngumpulkeun sakabeh data kana hiji obyék sarta nyaring eta. 

Tapi aya masalah: PowerCLI moal ngidinan urang pikeun muka loba sesi bebas ka vCenter sarta bakal maledog kasalahan lucu:

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.

Pikeun ngabéréskeun ieu, anjeun kedah ngirimkeun inpormasi sési di jero aliran. Hayu urang émut yén PowerShell tiasa dianggo sareng obyék anu tiasa disalurkeun salaku parameter pikeun fungsi atanapi ka ScriptBlock. Hayu urang lulus sési dina bentuk obyék sapertos kitu, ngalangkungan $ global: DefaultVIServers (Connect-VIServer sareng konci -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 $_
           }
       }
   }

Ayeuna hayu urang nerapkeun multithreading ngaliwatan Runspace Pools.  

Algoritme na sapertos kieu:

  1. Kami nampi daptar sadaya VM.
  2. Dina aliran paralel kami meunang cloud.uuid.
  3. Kami ngumpulkeun data tina aliran kana hiji obyék.
  4. Kami nyaring obyék ku ngagolongkeunana ku nilai médan CloudUUID: anu jumlah nilai unikna langkung ageung tibatan 1 nyaéta VM anu kami milarian.

Hasilna, urang meunang naskah:


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
}

Kaéndahan skrip ieu nyaéta yén éta tiasa dianggo dina kasus anu sami ku ngan saukur ngagentos ScriptBlock sareng parameter anu bakal dikirimkeun kana aliran. Eksploitasi eta!

Urang ngukur waktos:

Kumaha carana ngawangun booster rokét pikeun skrip PowerCLI

55 detik. Éta langkung saé, tapi masih tiasa langkung gancang. 

Hayu urang ngalih ka laju kadua: GetView

Hayu urang manggihan naon salah.
Mimitina jeung foremost, Get-VM cmdlet butuh waktu lila pikeun dieksekusi.
Kadua, cmdlet Get-AdvancedOptions nyandak langkung lami kanggo réngsé.
Hayu urang nungkulan nu kadua munggaran. 

Get-AdvancedOptions merenah pikeun objék VM individu, tapi kagok pisan nalika damel sareng seueur objék. Urang tiasa nampi inpormasi anu sami tina obyék mesin virtual sorangan (Get-VM). Ieu ngan dikubur ogé dina obyék ExtensionData. Bersenjata sareng nyaring, urang nyepetkeun prosés kéngingkeun data anu diperyogikeun.

Kalayan gerakan sakedik leungeun ieu:


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

Ngajadi ieu:


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

Kaluaranna sami sareng Get-AdvancedOptions, tapi tiasa dianggo sababaraha kali langkung gancang. 

Ayeuna meunang-VM. Teu gancang sabab ngurus objék kompléks. Patarosan logis timbul: naha urang kudu informasi tambahan sarta PSObject monstrous dina hal ieu, lamun urang ngan butuh nami VM, kaayaan sarta nilai atribut tricky?  

Salaku tambahan, halangan dina bentuk Get-AdvancedOptions parantos dipiceun tina naskah. Ngagunakeun Runspace Pools ayeuna sigana kawas overkill sabab teu aya deui kudu parallelize tugas slow sakuliah threads squat nalika handing leuwih sési. Alatna saé, tapi henteu pikeun hal ieu. 

Hayu urang tingali kaluaran ExtensionData: éta henteu langkung ti hiji objek Get-View. 

Hayu urang nelepon kana téknik kuno PowerShell masters: hiji baris ngagunakeun saringan, asihan jeung grup. Sadaya horor anu sateuacana sacara elegan runtuh janten hiji garis sareng dieksekusi dina hiji sési:


$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

Urang ngukur waktos:

Kumaha carana ngawangun booster rokét pikeun skrip PowerCLI

detik 9 pikeun ampir 10k objék kalawan nyaring ku kaayaan nu dipikahoyong. Hebat!

Gantina kacindekan

Hasil anu ditarima langsung gumantung kana pilihan alat. Sering sesah nyarios pasti naon anu kedah dipilih pikeun ngahontal éta. Masing-masing metode anu didaptarkeun pikeun nyepetkeun naskah saé dina wates anu tiasa dianggo. Abdi ngarepkeun tulisan ieu bakal ngabantosan anjeun dina tugas anu sesah pikeun ngartos dasar-dasar automation prosés sareng optimasi dina infrastruktur anjeun.

PS: Panulis ngahaturkeun nuhun ka sadaya anggota masarakat pikeun bantosan sareng dukunganana dina nyiapkeun tulisan. Malah nu boga paws. Komo nu teu boga suku, kawas boa.

sumber: www.habr.com

Tambahkeun komentar