PowerCLI skriptlari uchun raketa kuchaytirgichni qanday qurish mumkin 

Ertami-kechmi, har qanday VMware tizim administratori odatiy vazifalarni avtomatlashtirish uchun keladi. Hammasi buyruq satridan boshlanadi, keyin PowerShell yoki VMware PowerCLI keladi.

Aytaylik, siz PowerShell-ni ISE-ni ishga tushirish va “qandaydir sehr” tufayli ishlaydigan modullardan standart cmdletlardan foydalanishdan biroz ko'proq o'zlashtirgansiz. Virtual mashinalarni yuzlab hisoblashni boshlaganingizda, kichik miqyosda yordam beradigan skriptlar katta miqyosda sezilarli darajada sekinroq ishlashini ko'rasiz. 

Bunday holda, ikkita vosita yordam beradi:

  • PowerShell ish joylari – jarayonlarning bajarilishini alohida oqimlarda parallellashtirish imkonini beruvchi yondashuv; 
  • Ko'rish – asosiy PowerCLI funksiyasi, Windows-dagi Get-WMIObject-ning analogi. Ushbu cmdlet ob'ektlarga hamroh bo'lgan ob'ektlarni tortmaydi, lekin oddiy ma'lumotlar turlariga ega oddiy ob'ekt shaklida ma'lumot oladi. Ko'p hollarda u tezroq chiqadi.

Keyinchalik, men har bir vosita haqida qisqacha gapirib beraman va foydalanish misollarini ko'rsataman. Keling, aniq skriptlarni tahlil qilaylik va ulardan biri boshqasidan yaxshiroq ishlayotganini ko'rib chiqaylik. Bor!

PowerCLI skriptlari uchun raketa kuchaytirgichni qanday qurish mumkin

Birinchi bosqich: yugurish maydoni

Shunday qilib, Runspace asosiy moduldan tashqaridagi vazifalarni parallel ravishda qayta ishlash uchun mo'ljallangan. Albatta, siz biroz xotira, protsessor va hokazolarni yeb qo'yadigan boshqa jarayonni ishga tushirishingiz mumkin. Agar skriptingiz bir necha daqiqada ishga tushsa va bir gigabayt xotirani iste'mol qilsa, sizga Runspace kerak bo'lmaydi. Ammo o'n minglab ob'ektlar uchun skriptlar uchun bu kerak.

Siz bu erda o'rganishni boshlashingiz mumkin: 
PowerShell ishga tushirish maydonlaridan foydalanishni boshlash: 1-qism

Runspace-dan foydalanish nimani beradi:

  • bajarilgan buyruqlar ro'yxatini cheklash orqali tezlik,
  • vazifalarni parallel ravishda bajarish,
  • xavfsizlik.

Runspace yordam beradigan Internetdan misol:

“Saqlash bo'yicha bahslar vSphere-da kuzatishning eng qiyin ko'rsatkichlaridan biridir. vCenter ichida siz shunchaki borib, qaysi VM ko'proq saqlash resurslarini iste'mol qilayotganini ko'ra olmaysiz. Yaxshiyamki, PowerShell tufayli siz ushbu ma'lumotlarni bir necha daqiqada to'plashingiz mumkin.
Men VMware tizim ma'murlariga vCenter bo'ylab tezda qidirish va o'rtacha iste'moli haqidagi ma'lumotlar bilan VMlar ro'yxatini olish imkonini beradigan skriptni baham ko'raman.  
Skript har bir ESXi xostiga alohida Runspace-da o'z VM-laridan iste'mol ma'lumotlarini to'plash va yakunlanganligi haqida darhol hisobot berish uchun PowerShell ish maydonlaridan foydalanadi. Bu PowerShell-ga xostlar orqali takrorlash va ularning har biri o'z so'rovini bajarishini kutish o'rniga, darhol ishlarni yopish imkonini beradi.

Manba: ESXi boshqaruv panelida virtual mashinaning kirish/chiqarishini qanday ko'rsatish mumkin

Quyidagi holatda Runspace endi foydali emas:

“Men VM dan koʻp maʼlumotlarni toʻplaydigan va kerak boʻlganda yangi maʼlumotlarni yozadigan skript yozishga harakat qilyapman. Muammo shundaki, VMlar juda ko'p va bitta mashinaga 5-8 soniya sarflanadi. 

Manba: RunspacePool bilan ko'p qirrali PowerCLI

Bu erda sizga Get-View kerak bo'ladi, keling, unga o'tamiz. 

Ikkinchi bosqich: Get-View

Get-View nima uchun foydali ekanligini tushunish uchun, umuman olganda, cmdletlar qanday ishlashini esga olish kerak. 

Cmdletlar API ma'lumotnomalarini o'rganish va keyingi g'ildirakni qayta ixtiro qilmasdan qulay ma'lumot olish uchun kerak. Qadimgi kunlarda yuz yoki ikki qator kod olgan PowerShell sizga bitta buyruq bilan bajarishga imkon beradi. Biz bu qulaylik uchun tezlik bilan to'laymiz. Cmdletlarning o'zlari ichida hech qanday sehr yo'q: xuddi shu skript, lekin pastroq darajada, quyoshli Hindistonlik ustaning mohir qo'llari bilan yozilgan.

Endi Get-View bilan taqqoslash uchun Get-VM cmdletini olaylik: u virtual mashinaga kiradi va kompozit ob'ektni qaytaradi, ya'ni unga boshqa tegishli ob'ektlarni biriktiradi: VMHost, Datastore va boshqalar.  

Get-View o'z o'rnida qaytarilgan ob'ektga keraksiz narsalarni qo'shmaydi. Bundan tashqari, bu bizga qanday ma'lumot kerakligini aniq belgilashga imkon beradi, bu esa chiqish ob'ektini osonlashtiradi. Umuman Windows Serverda va xususan Hyper-V da Get-WMIObject cmdlet to'g'ridan-to'g'ri analogdir - g'oya aynan bir xil.

Get-View nuqtali ob'ektlarda muntazam operatsiyalar uchun noqulay. Ammo minglab va o'n minglab ob'ektlar haqida gap ketganda, uning narxi yo'q.

VMware blogida ko'proq o'qishingiz mumkin: Get-View dasturiga kirish

Endi men sizga hamma narsani haqiqiy ish yordamida ko'rsataman. 

VMni tushirish uchun skript yozish

Bir kuni hamkasbim ssenariysini optimallashtirishimni so‘radi. Vazifa umumiy tartib: bulut.uuid dublikat parametriga ega barcha VM-larni toping (ha, bu vCloud Director-da VMni klonlashda mumkin). 

Aqlga keladigan aniq yechim:

  1. Barcha VMlar ro'yxatini oling.
  2. Ro'yxatni qandaydir tarzda tahlil qiling.

Asl versiya bu oddiy skript edi:

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

Hammasi juda oddiy va tushunarli. Buni kofe tanaffusi bilan bir necha daqiqada yozish mumkin. Filtrni vidalang va u tugadi.

Ammo vaqtni o'lchaymiz:

PowerCLI skriptlari uchun raketa kuchaytirgichni qanday qurish mumkin

PowerCLI skriptlari uchun raketa kuchaytirgichni qanday qurish mumkin

2 daqiqa 47 soniya deyarli 10k VMni qayta ishlashda. Bonus - bu filtrlarning yo'qligi va natijalarni qo'lda saralash zarurati. Shubhasiz, skript optimallashtirishni talab qiladi.

Bir vaqtning o'zida vCenter-dan xost ko'rsatkichlarini olishingiz yoki o'n minglab ob'ektlarni qayta ishlashingiz kerak bo'lganda, Runspaces yordamga birinchi bo'lib keladi. Keling, bu yondashuv nima olib kelishini ko'rib chiqaylik.

Birinchi tezlikni yoqing: PowerShell Runspaces

Ushbu skript uchun aqlga kelgan birinchi narsa - tsiklni ketma-ket emas, balki parallel iplarda bajarish, barcha ma'lumotlarni bitta ob'ektga to'plash va uni filtrlash. 

Ammo muammo bor: PowerCLI bizga vCenter-da ko'plab mustaqil seanslarni ochishga ruxsat bermaydi va kulgili xatoga yo'l qo'yadi:

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.

Buni hal qilish uchun avval seans ma'lumotlarini oqim ichida o'tkazishingiz kerak. Eslatib o'tamiz, PowerShell funksiyaga yoki ScriptBlock ga parametr sifatida uzatilishi mumkin bo'lgan ob'ektlar bilan ishlaydi. Keling, $global:DefaultVIServers (Connect-VIServer -NotDefault kaliti bilan) ni chetlab o'tib, shunday ob'ekt shaklida sessiyani o'tkazamiz:

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

Keling, Runspace Pools orqali multithreadingni amalga oshiramiz.  

Algoritm quyidagicha:

  1. Biz barcha VMlar ro'yxatini olamiz.
  2. Parallel oqimlarda biz cloud.uuid olamiz.
  3. Biz oqimlardan ma'lumotlarni bitta ob'ektga yig'amiz.
  4. Biz ob'ektni CloudUUID maydonining qiymati bo'yicha guruhlash orqali filtrlaymiz: noyob qiymatlar soni 1 dan ortiq bo'lganlar biz izlayotgan VMlardir.

Natijada biz skriptni olamiz:


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
}

Ushbu skriptning go'zalligi shundaki, uni boshqa shunga o'xshash holatlarda oddiygina ScriptBlock va oqimga uzatiladigan parametrlarni almashtirish orqali ishlatish mumkin. Undan foydalaning!

Biz vaqtni o'lchaymiz:

PowerCLI skriptlari uchun raketa kuchaytirgichni qanday qurish mumkin

55 soniya. Bu yaxshiroq, lekin tezroq bo'lishi mumkin. 

Keling, ikkinchi tezlikka o'tamiz: GetView

Keling, nima bo'lganini bilib olaylik.
Avvalo, Get-VM cmdletini bajarish uchun uzoq vaqt ketadi.
Ikkinchidan, Get-AdvancedOptions buyrug'ini bajarish uchun ko'proq vaqt ketadi.
Keling, birinchi navbatda ikkinchisiga murojaat qilaylik. 

Get-AdvancedOptions individual VM ob'ektlari uchun qulay, lekin ko'p ob'ektlar bilan ishlashda juda noqulay. Xuddi shu ma'lumotni virtual mashina ob'ektining o'zidan (Get-VM) olishimiz mumkin. U ExtensionData ob'ektida yaxshi ko'milgan. Filtrlash bilan qurollangan holda biz kerakli ma'lumotlarni olish jarayonini tezlashtiramiz.

Qo'lning engil harakati bilan bu:


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

Bunga aylanadi:


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

Chiqish Get-AdvancedOptions bilan bir xil, lekin u bir necha marta tezroq ishlaydi. 

Endi Get-VM ga. Bu tez emas, chunki u murakkab ob'ektlar bilan shug'ullanadi. Mantiqiy savol tug'iladi: nima uchun bizga VM nomi, uning holati va murakkab atributning qiymati kerak bo'lganda, bu holatda bizga qo'shimcha ma'lumot va dahshatli PSObject kerak?  

Bundan tashqari, Get-AdvancedOptions ko'rinishidagi to'siq skriptdan olib tashlandi. Runspace Pools-dan foydalanish endi ortiqcha ish kabi ko'rinadi, chunki seansni topshirishda squat iplari bo'ylab sekin vazifani parallellashtirishning hojati yo'q. Asbob yaxshi, lekin bu holat uchun emas. 

ExtensionData chiqishini ko'rib chiqaylik: bu Get-View obyektidan boshqa narsa emas. 

Keling, PowerShell ustalarining qadimiy texnikasiga murojaat qilaylik: filtrlardan foydalangan holda bitta chiziq, saralash va guruhlash. Oldingi barcha dahshat oqlangan tarzda bitta qatorga yig'iladi va bitta seansda bajariladi:


$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

Biz vaqtni o'lchaymiz:

PowerCLI skriptlari uchun raketa kuchaytirgichni qanday qurish mumkin

9 soniya kerakli holat bo'yicha filtrlash bilan deyarli 10k ob'ektlar uchun. Ajoyib!

Xulosa o'rniga

Qabul qilinadigan natija to'g'ridan-to'g'ri vositani tanlashga bog'liq. Bunga erishish uchun nimani tanlash kerakligini aniq aytish ko'pincha qiyin. Skriptlarni tezlashtirish uchun sanab o'tilgan usullarning har biri qo'llanilishi doirasida yaxshi. Umid qilamanki, ushbu maqola sizga infratuzilmangizdagi jarayonlarni avtomatlashtirish va optimallashtirish asoslarini tushunish qiyin vazifada yordam beradi.

PS: Muallif hamjamiyatning barcha a'zolariga maqolani tayyorlashda ko'rsatgan yordami va yordami uchun minnatdorchilik bildiradi. Hatto panjalari bo'lganlar ham. Va hatto oyoqlari bo'lmaganlar ham, boa konstriktori kabi.

Manba: www.habr.com

a Izoh qo'shish