使用 Custom Script Extension 自动执行 SQL Server 虚拟机配置

原文链接: https://azure.microsoft.com/blog/2014/07/15/automating-sql-server-vm-configuration-using-custom-script-extension/ 

Haishi Bai

Evangelism 技术专员

 

Azure VM Custom Script Extension 允许您从存储帐户下载 PowerShell 脚本并执行脚本。虽然这个功能听起来简单,但在 PowerShell 的强大支持下,您将能够灵活地自动完成虚拟机配置,从而实现各种虚拟机自定义场景。在这篇博客中,我将会带领大家学习使用 Custom Script Extension 自定义从 Azure 虚拟机图像库中创建的 SQL Server 2014 虚拟机的步骤。我们将使用 SQL PowerShell 脚本启用 SQL Server Managed Backup to Windows Azure,这样就能将 SQL Server 2014 数据库备份到 Azure Blob 存储服务

 

SQL Server 配置脚本

该配置脚本非常简单,如下方的代码列表所示。您需要使用 Azure 存储凭据替换 [ your Azure storage account ][ your Azure storage account key ] 。将此脚本另存为 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

但是,目前我们还无法将此脚本直接提交至 Custom Script Extension。Custom Script Extension 使用 NTAUTHORITY\SYSTEM 帐户执行脚本,但该帐户不具备执行 SQL 配置命令所需的必要权限。为解决这个问题,我们将创建单独的启动脚本,在调用脚本之前模拟管理员帐户。

 

使用不同的凭据调用脚本

使用以下内容创建另一个名为 start.ps1 的脚本。为便于说明,我为每一行添加了行号:

 
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

第 1 行将要模拟的管理员密码从纯文本转换为加密字符串。当然,在脚本中使用纯文本密码并非最佳实践 – 稍后我将回来介绍这个问题。第 2 行创建运行主要脚本将要使用的凭据。您可以使用配置虚拟机时选择的同一帐户。第 3 行提供了指向主要脚本的绝对路径。要使用模拟凭据执行主要脚本,我们将需要使用 Windows 远程管理 (WinRM)。该脚本在第 4 行启动 WinRM,使用完毕后关闭 WinRM(第 6 行)。最后,第 5 行使用 Invoke-Command cmdlet(使用 Credential 参数)调用主脚本。

使用 Custom Script Extension

现在,我们已将两个脚本提交至 Custom Script Extension。将两个脚本上载到存储帐户下的 scripts 容器。有关 Custom Script Extension 工作原理的更多详细信息,请参阅第一个参考链接,特别是当您要使用不同于默认存储帐户的其他存储帐户和不同于 scripts 的其他容器时。然后,您可以从工作站运行如下脚本(同样设置了行号):

 
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 行是上方脚本的关键一行。它可确保在虚拟机上安装 Custom Script Extension,然后指示该扩展下载 start.ps1CustomScriptSQLPS.ps1,然后执行start.ps1

从外部文件读取密码

编写脚本的一项最佳实践是避免包含纯文本密码。在这里,我将使用密码加密/解密证书。我将假设您(或者您的 IT 部门)已经使用私钥为目标虚拟机部署证书,您已经使用同一证书的公钥以 Base-64 格式将密码加密到 password.txt 文件中:

 
$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
 

如果需要使用 makecert 帮助创建新的管理证书,请参阅此链接这篇博客文章将向大家介绍如何使用 Azure 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 文件传输至 Custom Script Extension:

 
Set-AzureVMCustomScriptExtension -ContainerName scripts -StorageAccountName '[your storage account name]' -VM $vm -FileName 'start.ps1', 'CustomScriptSQLPS.ps1', 'password.txt' -Run 'start.ps1' | Update-AzureVM -Verbose

小结

在这篇博客文章中,我们介绍了使用 Custom Script Extension 自定义 SQL Server 2014 虚拟机的各个步骤。本文通过实际场景展示了 Custom Script Extension。本文介绍了若干典型脚本任务,如模拟和密码加密。

致谢

本博客文章由多人合作完成。非常感谢 Madhan Arumugam 和 Sethu Srinivasan 提供的大力协助。