PowerCLI сценарийлері үшін зымыран күшейткішті қалай жасауға болады 

Ерте ме, кеш пе, кез келген VMware жүйелік әкімшісі күнделікті тапсырмаларды автоматтандыруға келеді. Мұның бәрі пәрмен жолынан басталады, содан кейін PowerShell немесе VMware PowerCLI келеді.

ISE іске қосудан және «сиқырдың» арқасында жұмыс істейтін модульдерден стандартты командлеттерді пайдаланудан гөрі PowerShell-ті аздап игердіңіз делік. Виртуалды машиналарды жүздеген санауды бастағанда, шағын масштабта көмектесетін сценарийлердің үлкен масштабта айтарлықтай баяу жұмыс істейтінін көресіз. 

Бұл жағдайда 2 құрал көмектеседі:

  • PowerShell жұмыс кеңістігі – жекелеген ағындардағы процестердің орындалуын параллельдеуге мүмкіндік беретін тәсіл; 
  • Get-View – негізгі PowerCLI функциясы, Windows жүйесіндегі Get-WMIObject аналогы. Бұл командлет нысандарға ілеспе нысандарды тартпайды, бірақ қарапайым деректер түрлері бар қарапайым нысан түрінде ақпаратты алады. Көптеген жағдайларда ол тезірек шығады.

Әрі қарай, мен әрбір құрал туралы қысқаша айтып, пайдалану мысалдарын көрсетемін. Нақты сценарийлерді талдап көрейік және олардың қайсысы екіншісінен жақсы жұмыс істейтінін көрейік. Бар!

PowerCLI сценарийлері үшін зымыран күшейткішті қалай жасауға болады

Бірінші кезең: жүгіру

Сонымен, Runspace негізгі модульден тыс тапсырмаларды параллель өңдеуге арналған. Әрине, жадты, процессорды және т.б. біраз жадты жейтін басқа процесті іске қосуға болады. Егер сценарий бірнеше минут ішінде жұмыс істеп, гигабайт жадты тұтынса, сізге Runspace қажет болмауы мүмкін. Бірақ ондаған мың нысандарға арналған сценарийлер үшін бұл қажет.

Сіз мына жерден оқуды бастай аласыз: 
PowerShell жұмыс кеңістігін пайдалануды бастау: 1 бөлім

Runspace пайдалану не береді:

  • орындалатын командалар тізімін шектеу арқылы жылдамдық,
  • тапсырмаларды қатар орындау,
  • қауіпсіздік.

Мұнда Runspace көмектесетін Интернеттен мысал келтірілген:

«Сақтау дауы – vSphere жүйесінде бақылауға болатын ең қиын көрсеткіштердің бірі. vCenter ішінде сіз жай ғана барып, қай виртуалды құрылғы көбірек сақтау ресурстарын тұтынатынын көре алмайсыз. Бақытымызға орай, PowerShell арқасында бұл деректерді бірнеше минут ішінде жинай аласыз.
Мен VMware жүйелік әкімшілеріне vCenter бойынша жылдам іздеуге және олардың орташа тұтынуы туралы деректері бар VM тізімін алуға мүмкіндік беретін сценариймен бөлісемін.  
Сценарий әрбір ESXi хостына жеке іске қосу кеңістігінде жеке VM құрылғыларынан тұтыну ақпаратын жинауға және аяқталу туралы дереу есеп беруге мүмкіндік беру үшін PowerShell жұмыс кеңістігін пайдаланады. Бұл хосттар арқылы итерациялау және әрқайсысының сұрауын аяқтауын күтудің орнына PowerShell-ке тапсырмаларды дереу жабуға мүмкіндік береді.”

Ақпарат көзі: ESXi бақылау тақтасында виртуалды машинаның енгізу/шығаруын қалай көрсетуге болады

Төмендегі жағдайда Runspace енді пайдалы емес:

«Мен VM-ден көптеген деректерді жинайтын және қажет болғанда жаңа деректерді жазатын сценарий жазуға тырысамын. Мәселе мынада, VM-лер өте көп және бір машинаға 5-8 секунд кетеді». 

Ақпарат көзі: RunspacePool көмегімен көп ағынды PowerCLI

Мұнда сізге Get-View қажет болады, оған көшейік. 

Екінші кезең: Get-View

Get-View неліктен пайдалы екенін түсіну үшін командлеттердің жалпы қалай жұмыс істейтінін есте ұстаған жөн. 

Командлеттер API анықтамалық кітаптарын зерделеуді және келесі дөңгелекті қайта ойлап табуды қажет етпестен ақпаратты ыңғайлы алу үшін қажет. Ескі күндерде жүз немесе екі жол код қажет болса, PowerShell бір пәрменмен жасауға мүмкіндік береді. Біз бұл ыңғайлылық үшін жылдамдықпен төлейміз. Комдлеттердің өзінде ешқандай сиқыр жоқ: бірдей сценарий, бірақ күн шуақты Үндістаннан келген шебердің шебер қолдарымен жазылған төменгі деңгейде.

Енді Get-View-пен салыстыру үшін Get-VM командлетін алайық: ол виртуалды машинаға кіріп, құрама нысанды қайтарады, яғни оған басқа қатысты нысандарды тіркейді: VMHost, Datastore және т.б.  

Get-View өз орнына қайтарылған нысанға қажетсіз ештеңе қоспайды. Оның үстіне, ол бізге қандай ақпарат қажет екенін қатаң түрде көрсетуге мүмкіндік береді, бұл шығыс объектісін жеңілдетеді. Жалпы Windows Server серверінде және әсіресе Hyper-V жүйесінде Get-WMIObject командлеті тікелей аналог болып табылады - идея дәл солай.

Get-View нүктелік нысандардағы әдеттегі әрекеттер үшін қолайсыз. Бірақ мыңдаған, он мыңдаған нысандарға келетін болсақ, оның бағасы жоқ.

Толығырақ VMware блогында оқи аласыз: Get-View бағдарламасына кіріспе

Енді мен сізге нақты істің көмегімен бәрін көрсетемін. 

VM жүктеу үшін сценарий жазу

Бір күні әріптесім сценарийін оңтайландыруымды өтінді. Тапсырма жалпыға ортақ жұмыс болып табылады: cloud.uuid қайталанатын параметрі бар барлық виртуалды компьютерлерді табыңыз (иә, бұл vCloud Director бағдарламасында VM клондау кезінде мүмкін). 

Ойға келетін айқын шешім:

  1. Барлық VM тізімін алыңыз.
  2. Тізімді қандай да бір жолмен талдаңыз.

Түпнұсқа нұсқасы мына қарапайым сценарий болды:

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

Барлығы өте қарапайым және түсінікті. Оны кофе-брейкпен бір-екі минутта жазуға болады. Сүзуді бұрап, ол аяқталды.

Бірақ уақытты өлшейік:

PowerCLI сценарийлері үшін зымыран күшейткішті қалай жасауға болады

PowerCLI сценарийлері үшін зымыран күшейткішті қалай жасауға болады

2 минут 47 секунд 10 мыңға жуық VM өңдеу кезінде. Бонус - сүзгілердің болмауы және нәтижелерді қолмен сұрыптау қажеттілігі. Сценарий оңтайландыруды қажет ететіні анық.

Runspaces бір уақытта vCenter жүйесінен хост көрсеткіштерін алу қажет болғанда немесе ондаған мың нысандарды өңдеу қажет болғанда бірінші болып көмекке келеді. Бұл тәсіл не әкелетінін көрейік.

Бірінші жылдамдықты қосыңыз: PowerShell Runspaces

Бұл сценарий үшін бірінші ойға келетін нәрсе - циклды дәйекті емес, параллельді ағындарда орындау, барлық деректерді бір нысанға жинап, оны сүзгілеу. 

Бірақ мәселе бар: PowerCLI бізге vCenter-ге көптеген тәуелсіз сеанстарды ашуға мүмкіндік бермейді және күлкілі қате жібереді:

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.

Мұны шешу үшін алдымен сеанс ақпаратын ағынның ішіне жіберу керек. PowerShell параметрі функцияға немесе ScriptBlock-қа жіберуге болатын нысандармен жұмыс істейтінін еске түсірейік. $global:DefaultVIServers (Connect-VIServer -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 $_
           }
       }
   }

Енді Runspace Pools арқылы көп ағынды іске асырамыз.  

Алгоритм келесідей:

  1. Біз барлық VM тізімін аламыз.
  2. Параллельді ағындарда біз cloud.uuid аламыз.
  3. Біз ағындардан деректерді бір нысанға жинаймыз.
  4. Біз нысанды CloudUUID өрісінің мәні бойынша топтау арқылы сүзгіден өткіземіз: бірегей мәндер саны 1-ден асатындар біз іздеп жатқан VM болып табылады.

Нәтижесінде біз сценарийді аламыз:


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
}

Бұл сценарийдің сұлулығы, оны ScriptBlock және ағынға берілетін параметрлерді жай ғана ауыстыру арқылы басқа ұқсас жағдайларда пайдалануға болады. Оны пайдалан!

Біз уақытты өлшейміз:

PowerCLI сценарийлері үшін зымыран күшейткішті қалай жасауға болады

55 секунд. Бұл жақсырақ, бірақ ол тезірек болуы мүмкін. 

Екінші жылдамдыққа көшейік: GetView

Ненің дұрыс емес екенін анықтайық.
Ең алдымен, Get-VM командлетін орындау үшін көп уақыт қажет.
Екіншіден, Get-AdvancedOptions командлетін аяқтау үшін одан да көп уақыт қажет.
Алдымен екіншісімен айналысайық. 

Get-AdvancedOptions жеке VM нысандары үшін ыңғайлы, бірақ көптеген нысандармен жұмыс істегенде өте ыңғайсыз. Біз бірдей ақпаратты виртуалды машина нысанының өзінен ала аламыз (Get-VM). Ол ExtensionData нысанында жақсы көмілген. Сүзгілеу арқылы біз қажетті деректерді алу процесін тездетеміз.

Қолдың аздап қозғалысымен бұл:


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

Бұған айналады:


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

Шығару Get-AdvancedOptions сияқты бірдей, бірақ ол бірнеше есе жылдамырақ жұмыс істейді. 

Енді Get-VM. Ол жылдам емес, өйткені ол күрделі нысандармен айналысады. Логикалық сұрақ туындайды: бұл жағдайда бізге VM атауы, оның күйі және күрделі атрибуттың мәні қажет болғанда, бізге неліктен қосымша ақпарат пен құбыжық PSObject қажет?  

Бұған қоса, Get-AdvancedOptions түріндегі кедергі сценарийден жойылды. Runspace Pools пайдалану енді шамадан тыс жұмыс сияқты болып көрінеді, өйткені сеансты тапсыру кезінде скват ағындары бойынша баяу тапсырманы параллельдеу қажет емес. Құрал жақсы, бірақ бұл жағдайда емес. 

ExtensionData шығысын қарастырайық: бұл Get-View нысанынан басқа ештеңе емес. 

PowerShell шеберлерінің ежелгі техникасын шақырайық: сүзгілерді қолданатын бір жол, сұрыптау және топтау. Барлық алдыңғы сұмдық талғампаздықпен бір жолға жиналып, бір сеанста орындалады:


$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

Біз уақытты өлшейміз:

PowerCLI сценарийлері үшін зымыран күшейткішті қалай жасауға болады

9 секунд қалаған шарт бойынша сүзу арқылы 10 мыңға жуық нысандар үшін. Тамаша!

Орнына жасасу

Қолайлы нәтиже құралды таңдауға тікелей байланысты. Оған қол жеткізу үшін нені таңдау керектігін нақты айту қиын. Сценарийлерді жылдамдату үшін аталған әдістердің әрқайсысы оның қолданылу шегінде жақсы. Бұл мақала сізге инфрақұрылымыңыздағы процестерді автоматтандыру және оңтайландыру негіздерін түсіну қиын тапсырмада көмектеседі деп үміттенемін.

PS: Автор мақаланы дайындауда көрсеткен көмегі мен қолдауы үшін барлық қауымдастық мүшелеріне алғыс білдіреді. Тіпті табаны барлар да. Тіпті аяқтары жоқ адамдар да боа тартқышы сияқты.

Ақпарат көзі: www.habr.com

пікір қалдыру