使用客製化腳本擴展自動化 SQL Server VM 設定
Azure VM 客製化腳本擴展 (Custom Script Extension) 將讓您可以從儲存體帳戶下載 PowerShell 腳本並執行之,透過這樣一個簡單的功能,您可以因應各種不同的 VM 客製化情境,彈性地自動化 VM 設定。在本篇文章中我們將帶您了解如何從 Azure VM Image Gallery 中使用客製化腳本擴展來客製一個 SQL Server 2014 VM,我們將使用 SQL Powershell 腳本來啟用 SQL Server Managed Backup 到 Microsoft Azure,這將讓您可以備份您的 SQL Server 2014 資料庫到 Azure Blob 儲存體服務上。
SQL Server 設定腳本
請參閱以下程式碼,您只需要將 [your Azure storage account] 和 [your Azure storage account key] 改為您 Azure 儲存體的帳戶及憑證即可,並另存此腳本為 CustomScriptSQLPS.ps1。
#import SQL Server powershell module
import-module sqlps -DisableNameChecking
#global variables - replace storage account name and key
$credentialName = "AzureStorageCredential_"+(RANDOM)
$storageAccountName = "[your Azure storage account]"
$storageAccountKey = "[your Azure storage account key]"
#start SQL Agent Service
write-host "Starting SQL Server Agent service ..."
Start-Service sqlserveragent -verbose
CD SQLSERVER:SQL\$env:COMPUTERNAME\DEFAULT
write-host "Creating SQL credential ..."
$secureString = convertto-securestring $storageAccountKey -asplaintext -force
#Create Credential
New-SqlCredential –name $credentialName –Identity $storageAccountName –secret $secureString
$encryptionOption = New-SqlBackupEncryptionOption -NoEncryption
write-host "Enabling Managed SQL Server Backup..."
get-sqlsmartadmin | set-sqlsmartadmin -BackupEnabled $True
-BackupRetentionPeriodInDays 7 -SqlCredential $credentialName -EncryptionOption
$encryptionOption
write-host "Managed SQL Server backup current configuration:"
get-sqlsmartadmin | fl
但是,我們無法直接提交此腳本,因客製化腳本擴展是使用 NTAUTHORITY\SYSTEM 帳戶來執行腳本,所以我們必須建立另個腳本,來扮演管理員帳戶角色,才能執行上面這段腳本。
利用另個認證來執行腳本
首先我們建立另個腳本取名作 start.ps1,內容如下。為了方便解說,我在下方加了 Line Number。
1: $password = ConvertTo-SecureString "[your admin account user password]" -AsPlainText -Force
2: $credential = New-Object System.Management.Automation.PSCredential("$env:COMPUTERNAME\[your admin account]", $password)
3: $command = $file = $PSScriptRoot + "\CustomScriptSQLPS.ps1"
4: Enable-PSRemoting –force
5: Invoke-Command -FilePath $command -Credential $credential -ComputerName $env:COMPUTERNAME
6: Disable-PSRemoting -Force
Line 1: 將管理員密碼從 Plain text 轉換到 Secured string,當然將密碼直接放置於腳本中不是一個好的做法,這我們稍後再回來談。
Line 2: 建立執行主要腳本的認證,您可以使用和預備用來建立 VM 相同的帳戶。
Line 3: 指定主要腳本的確切路徑。
Line 4 & 6: 要在一個仿造的認證中執行主要腳本,我們必須啟用 Windows Remote Management (WinRM),也就是 Line 4,而 Line 6 是關閉。
Line 5: 使用 Invoke-Command cmdlet 來執行主要腳本 (會需要認證參數)。
使用客製化腳本擴展
現在我們已經準備好提交以上兩個腳本至客製化腳本擴展,將兩個腳本上傳至您儲存體帳戶下的腳本容器中,接下來在您的工作站上邊可執行以下腳本。
1: $servicename = "[cloud service that hosts the VM]"
2: $vmname = "[name of the VM]"
3: $vm = Get-AzureVM -ServiceName $servicename -Name $vmname
4: Set-AzureVMCustomScriptExtension -ContainerName scripts -StorageAccountName '[your storage account name]' -VM $vm -FileName 'start.ps1', 'CustomScriptSQLPS.ps1' -Run 'start.ps1' | Update-AzureVM -Verbose
5: $status = Get-AzureVM -ServiceName $servicename -Name $vmname
6: $result = $status.ResourceExtensionStatusList.ExtensionSettingStatus.SubStatusList | Select Name, @{"Label"="Message";Expression = {$_.FormattedMessage.Message }}
7: $result |fl
最重要的是第4行,它確保了於VM上安裝客製化腳本擴展,並下載start.ps1 和 CustomScriptSQLPS.ps1,接著執行 start.ps1。
於外部檔案中讀取密碼
我們都知道應避免於程式碼中寫入密碼,所以現在要介紹的是加解密服務,我們將假設您已經利用 private key 於目標 VM 部署了憑證,且利用相同憑證的 public key 來加密到 password.txt 檔案 (base-64 格式)。
$cert = Get-ChildItem Cert:\LocalMachine\My\[certificate thumbprint]
$bytes = [Text.Encoding]::UTF8.GetBytes("abcdefg")
$encrypted = $cert.PublicKey.Key.Encrypt($bytes, $true)
$base64 = [Convert]::ToBase64String($encrypted)
Set-Content .\password.txt $base64
若您對於 VM 憑證管理還不太了解,可以參考這裡 (提供教學影片及命令提示字元下載)。
修改start.ps1 並將以下程式碼複製取代原本的第一行:
$cert = Get-ChildItem Cert:\LocalMachine\My\[certificate thumbprint]
$base64 = Get-Content .\password.txt
$encrypted = [Convert]::FromBase64String($base64)
$bytes = $cert.PrivateKey.Decrypt($encrypted,$true)
$password = [Text.Encoding]::UTF8.GetString($bytes)
最後,於檔案列表增加檔案名稱來確認 password.txt 檔案已傳送至客製化腳本擴展。
Set-AzureVMCustomScriptExtension -ContainerName scripts -StorageAccountName '[your storage account
name]' -VM $vm -FileName 'start.ps1', 'CustomScriptSQLPS.ps1',
'password.txt' -Run 'start.ps1' | Update-AzureVM -Verbose