前篇咱們講了怎樣建立一個自動化帳戶以及建立時候「Run As Account」選項背後的奧祕。這一篇針對在Azure自動化帳戶中使用Powershell Runbook的用戶講一下怎樣更新powershell 模塊。shell
更新Powershell模塊api
首先,咱們須要先了解一下Azure Automation的系統架構。咱們已經知道用戶能夠經過運行Runbook來實現自動化運維,Runbook運行則是在Azure Automation的沙盒裏執行的,沙盒是一組由Azure管理的虛機資源, 咱們能夠把其當作是Azure的一個PaaS服務。Pass服務天然是須要提供可伸縮高可用多租客隔離的運行環境。顯然,咱們須要可以爲Runbook的運行環境指定所須要的Powershell模塊和版本。同時,咱們還須要可以升級更新相關的powershell模塊。瀏覽器
打開咱們前面建立的azpoctest自動化帳戶,在左邊菜單選擇「共享的資源」-》「模塊」。架構
很是好,用戶能夠添加自定義的模塊「添加模塊」,也能夠升級已有模塊版本「更新Azure模塊」。用戶還能夠瀏覽powershell模塊庫來導入新模塊。運維
仔細研究一下這個頁面,目測建立自動化帳戶時候自帶的模塊遠少於目前Azure已經release的Powershell模塊。若是須要運行Runbook來自動化運維Azure資源的話,目前這些模塊是遠遠不夠的。編輯器
記得光是ARM相關的powershell模塊就有幾十個,一個個導入的話工做量實在太大,那咱們能不能像在powershell 命令行那樣,用Install-Module和Import-Module兩條命令就能夠完成全部AzureRM測試
相關的模塊安裝呢?this
點擊「瀏覽庫」,選擇「AzureRM」,點擊「導入」。「肯定」按鈕是灰色的,顯然在Azure Portal中不支持有依賴關係的模塊集中導入。spa
記得16年在Global作Automation Account的時候,毫無怨言地填坑,手動一個個把這些模塊導入。今天咱們換個填坑的法子命令行
接下來咱們會寫一個Runbook,用腳原本導入AzureRM的Powershell模塊
建立Runbook
在自動化帳戶左邊菜單選取「流程自動化」-》「Runbook」-》「添加Runbook「 ,建立一個新的Runbook
建立成功後,瀏覽器會自動跳轉到Runbook編輯器,咱們能夠開始寫Powershell腳本了
首先,由於Runbook是運行在一個多租戶的沙盒中,咱們須要登陸這個自動化帳戶所在的Azure訂閱才能爲這個自動化帳戶導入模塊。
登陸的代碼能夠reuse咱們在上一篇提到的Runbook模板
$connectionName = "AzureRunAsConnection" try { # Get the connection "AzureRunAsConnection " $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName "Logging in to Azure..." Add-AzureRmAccount ` -ServicePrincipal ` -TenantId $servicePrincipalConnection.TenantId ` -ApplicationId $servicePrincipalConnection.ApplicationId ` -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint ` -EnvironmentName AzureChinaCloud } catch { if (!$servicePrincipalConnection) { $ErrorMessage = "Connection $connectionName not found." throw $ErrorMessage } else{ Write-Error -Message $_.Exception throw $_.Exception } }
接下來,咱們須要在Powershell Gallery裏查找導入模塊及其版本,若是存在,咱們會先去找一個模塊實際存儲的Blob Storage地址,用New-AzureRmAutomationModule這條命令來導入
若是有Dependency的模塊,腳本會首先去導入Dependency模塊。下文腳本包含了資源組,自動化帳戶,模塊(AzureRM)和模塊版本(最新),考慮到模塊和模塊版本在不一樣時期可能有變化,這2部分其實能夠作參數化,由Automation的variable來存儲。那樣腳本就不須要常常修改。
param( [Parameter(Mandatory=$true)] [String] $ResourceGroupName, [Parameter(Mandatory=$true)] [String] $AutomationAccountName, [Parameter(Mandatory=$true)] [String] $ModuleName, [Parameter(Mandatory=$false)] [String] $ModuleVersion ) $ModulesImported = @() function _doImport { param( [Parameter(Mandatory=$true)] [String] $ResourceGroupName, [Parameter(Mandatory=$true)] [String] $AutomationAccountName, [Parameter(Mandatory=$true)] [String] $ModuleName, # if not specified latest version will be imported [Parameter(Mandatory=$false)] [String] $ModuleVersion ) $Url = "https://www.powershellgallery.com/api/v2/Search()?`$filter=IsLatestVersion&searchTerm=%27$ModuleName%27&targetFramework=%27%27&includePrerelease=false&`$skip=0&`$top=40" $SearchResult = Invoke-RestMethod -Method Get -Uri $Url -UseBasicParsing if($SearchResult.Length -and $SearchResult.Length -gt 1) { $SearchResult = $SearchResult | Where-Object -FilterScript { return $_.properties.title -eq $ModuleName } } if(!$SearchResult) { Write-Error "Could not find module '$ModuleName' on PowerShell Gallery." } else { $ModuleName = $SearchResult.properties.title # get correct casing for the module name $PackageDetails = Invoke-RestMethod -Method Get -UseBasicParsing -Uri $SearchResult.id if(!$ModuleVersion) { # get latest version $ModuleVersion = $PackageDetails.entry.properties.version } $ModuleContentUrl = "https://www.powershellgallery.com/api/v2/package/$ModuleName/$ModuleVersion" # Make sure module dependencies are imported $Dependencies = $PackageDetails.entry.properties.dependencies if($Dependencies -and $Dependencies.Length -gt 0) { $Dependencies = $Dependencies.Split("|") # parse depencencies, which are in the format: module1name:module1version:|module2name:module2version: $Dependencies | ForEach-Object { if($_ -and $_.Length -gt 0) { $Parts = $_.Split(":") $DependencyName = $Parts[0] $DependencyVersion = $Parts[1] # check if we already imported this dependency module during execution of this script if(!$ModulesImported.Contains($DependencyName)) { $AutomationModule = Get-AzureRmAutomationModule ` -ResourceGroupName $ResourceGroupName ` -AutomationAccountName $AutomationAccountName ` -Name $DependencyName ` -ErrorAction SilentlyContinue # check if Automation account already contains this dependency module of the right version if((!$AutomationModule) -or $AutomationModule.Version -ne $DependencyVersion) { $DependencyVersion = $DependencyVersion.Split("[")[0].Split("]")[0] Write-Output "Importing dependency module $DependencyName of version $DependencyVersion first." # this dependency module has not been imported, import it first _doImport ` -ResourceGroupName $ResourceGroupName ` -AutomationAccountName $AutomationAccountName ` -ModuleName $DependencyName ` -ModuleVersion $DependencyVersion $ModulesImported += $DependencyName } } } } } # Find the actual blob storage location of the module do { $ActualUrl = $ModuleContentUrl $ModuleContentUrl = (Invoke-WebRequest -Uri $ModuleContentUrl -MaximumRedirection 0 -UseBasicParsing -ErrorAction Ignore).Headers.Location } while(!$ModuleContentUrl.Contains(".nupkg")) $ActualUrl = $ModuleContentUrl Write-Output "Importing $ModuleName module of version $ModuleVersion from $ActualUrl to Automation" $AutomationModule = New-AzureRmAutomationModule ` -ResourceGroupName $ResourceGroupName ` -AutomationAccountName $AutomationAccountName ` -Name $ModuleName ` -ContentLink $ActualUrl while( $AutomationModule.ProvisioningState -ne "Created" -and $AutomationModule.ProvisioningState -ne "Succeeded" -and $AutomationModule.ProvisioningState -ne "Failed" ) { Write-Verbose -Message "Polling for module import completion" Start-Sleep -Seconds 10 $AutomationModule = $AutomationModule | Get-AzureRmAutomationModule } if($AutomationModule.ProvisioningState -eq "Failed") { Write-Error "Importing $ModuleName module to Automation failed." } else { Write-Output "Importing $ModuleName module to Automation succeeded." } } } _doImport ` -ResourceGroupName "chdaiAC" ` -AutomationAccountName "acpoctest" ` -ModuleName "AzureRM" ` -ModuleVersion $ModuleVersion
編輯完成,點擊保存。隨後繼續點擊「測試窗格」。這個功能將測試咱們剛完成的Runbook。
在輸出窗口會看到後臺沙盒運行腳本把AzureRM的dependency模塊一個個被導入到自動化帳戶
最後導入AzureRM的時候運行會報錯,這個沒有關係。AzureRM模塊自己不包含任何功能。因此ARM管理的Powershell命令都在AzureRM的Dependency 模塊裏。
如今回到模塊列表,能夠看到AzureRM相關模塊已經所有導入了
如今萬事具有,下一篇咱們能夠開始在平常工做中運用Azure自動化帳戶