本次来谈一谈如何在 Azure 中实现一些简单的自动化运维的需求, 一般来讲自动化运维我们通过很多第三方的工具平台实现, 比较流行的目前有很多, 比如老牌的 Chef, Puppet, 新兴的 PowerShell DSC, ansible. 这些应该都是耳熟能详的了.
那么在 Azure 平台, 如何实现自动化部署和运维?
方法其实很多, 第一种方法比较传统, 即仍然使用 Chef, Ansible 等工具平台进行自动化运维, 仍然可以保持以往的体验, 无需学习任何新的技术
在 Azure 中也对这种方式提供了很多的技术支持, 在应用市场中也可以找到这种镜像
在 VM 的 extension 里也可以找到很多相关的 extension
这种方式对于已经很熟悉这些工具的人来说, 应该是最容易的方式
当然, 除此之后还有一些其他的方法也可以实现一些简单的自动化运维, 部署的目的, 如果是一些简单的需求, 也可以考虑使用这类方法, 比如说多台 Windows VM 想要加入同一个域里, 或者是多台 web 服务器想要统一安装某些软件或者角色, 这类较为简单的需求, 则可以使用 Azure 自带的 Custom Script Extension 来实现
举例来说, 想要实现多台 VM 加域, 一般来讲加域可以通过批量推送脚本, 或者是手动的方式来实现, 在 Azure 中, 实际上我们不需要登录到任何一台 VM 中, 只需要在外部网络即可实现加域的效果, 只要要加域的 vm 到 DC 之间的网络是联通的, 并且 DNS 可以正常解析到域名即可.
比如, 现在我们有一台 DC, 两位 Web 服务器, web01 及 web02, 现在有两个需求
1. 将两台服务器加入到域中
2. 对两台服务器安装 IIS 角色
第一个需求, 我们可以通过 Azure 自带的 JsonADDomainExtension 实现, 只需要提供一个加域的 cred, 以及域名, 即可将服务器加入到域中, 命令也非常简单
直接在 PowerShell 中运行以下命令, 将 <> 里的内容替换为实际的内容即可
Set-AzureRmVMADDomainExtension -DomainName <Domain name> -Credential <domain Cred> -Restart -ResourceGroupName <resource group name> -VMName <vm name> -Name <Extension Name> -TypeHandlerVersion "1.3" -JoinOption 3
这里又衍生出另一个问题, credential 如果写在脚本中, 很有可能是以明文的形式, 这样肯定是不行的, 如何能保证 credential 的安全呢? 一种方法是可以通过 Get-Credential 实现, 将账户密码直接以加密形式保存在变量里. 但是这样的话加域过程中, 还需要一些人为的参与. 除此之外, 其实还可以通过 Azure 的 key vault 服务, 将账户密码保存在 key vault 中, 通过 powershell 进行调取
Azure Key Vault 是一个用于安全地存储和访问机密的工具. 可以通过 Azure Key Vault 保存例如 API 密钥, 密码或证书等关键信息. 举例来说, 我们可以把有权限加域的域账户账户名和密码保存在 key vault 中, 然后通过 PowerShell 获取这些信息, 作为加域的 credential 进行加域操作
创建 key vault 的方法很简单, 首先在 Azure 中选择好 Key Vault 服务, 点击添加
这里输入一些基本信息, 比如 location, vault 的名字等
创建完成后, 因为我们是要保护一些明文信息, 所以只需要选择 secrets 即可, 如果是要保存证书, 也可以选择 certificates, 选择 generate secret
之后分别录入 domain username 以及 domain password
可以看到这些信息在 key vault 里是以加密的形式存在的, 之后可以通过 PowerShell 命令 Get-AzureKeyVaultSecret 获取这些值
运行 Get-AzureKeyVaultSecret -VaultName mxytestvault -Name domainuser 可以看到这个 secret 的相关信息
如果获取这个 secret 的 secretvalue, 会看到这是一个加密的字符串
如果想获取明文信息, 可以获取 SecretValueText 属性
通过这种方式, 即可实现无人参与的部署, 同时又能保证信息的安全
下边来看下具体如何将 key vault 与 vm extension 结合在一起, 实现自动化的部署操作
假设要加域的 VM 都在一个资源组中, 则可以通过以下脚本, 直接将资源组中的 VM 添加到域中
脚本内容如下:
- param
- (
- [parameter(Mandatory = $true)]
- [string]$RGName,# 资源组名
- [parameter(Mandatory = $false)]
- [string]$vaultname = "mxytestvault",#Azure key vault 名称
- [parameter(Mandatory = $false)]
- [string]$Domain = "mxyo365.com" #要加入的域名
- )
- function Join-Domain {
- param (
- [Parameter(Mandatory = $true)]
- $RGName,
- [Parameter(Mandatory = $true)]
- $VMName,
- [Parameter(Mandatory = $true)]
- $Cred
- )
- #filter dc vms
- if ($VMName -notlike "*DC*") {
- #Get Azure vm
- $vm = Get-AzureRmVM -ResourceGroupName $RGName -Name $VMName -erroraction SilentlyContinue
- if ($vm -ne $null) {
- $ExtensionName = $VMName + (Get-Random -Minimum 1 -Maximum 100)
- try {
- #join domain with Azure dommain extension
- $Error.Clear()
- Write-Output "Setting domain join extension for vm $VMName, extension name:$ExtensionName"
- Set-AzureRmVMADDomainExtension -DomainName $Domain -Credential $Cred -Restart -ResourceGroupName $RGName -VMName $VMName -Name $ExtensionName -TypeHandlerVersion "1.3" -JoinOption 3
- }
- catch {
- Write-Output $Error[0].Exception.Message
- }
- }
- else {
- Write-Output "VM $VMName does not exist."
- }
- }
- }
- #Get secret with PowerShell
- $domainuname = (Get-AzureKeyVaultSecret -VaultName $vaultname -Name domainuser).SecretValueText
- Write-Output "Get username from vault $vaultname"
- $domainfulluname = "$domainuname@$Domain"
- $domainpwd = (Get-AzureKeyVaultSecret -VaultName $vaultname -Name domainpassword).SecretValue
- Write-Output "Get password from vault $vaultname"
- #Create credential with secret
- $DomainCred = New-Object System.Management.Automation.PSCredential($domainfulluname, $domainpwd)
- #Get VMs
- $VMS = Get-AzureRmVM -ResourceGroupName $RGName
- foreach ($VM in $VMS) {
- Join-Domain -RGName $RGName -VMName $VM.Name -Cred $DomainCred
- }
脚本运行时, 只需要指定资源组名, vault 名称, 要加入的域名即可
.\RGJoinDomain.ps1 -RGNAME test -vaultname mxytestvault -Domain mxyo365.com
通过提示可以看到, Web01 和 web02 已经成功安装 extension
登录到 VM 后, 可以看到 WEB01 和 WEB02 都已经加入到域中了
加域完成后, 如果希望能安装一些 IIS 等功能角色, 或者是软件, 可通过 Azure VM extension 实现, 方法很简单, 以下是通过 extension 安装 IIS 角色的脚本
- param(
- [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
- [Alias('VMName')]
- [string]$Name,
- [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
- [string]$ResourceGroupName
- )
- begin {
- Write-Output "Start to install IIS for vms"
- }
- process {
- try {
- $ExtensionName = $Name + "-IIS-" + (Get-Random -Minimum 1 -Maximum 100)
- Write-Output "Trying to install iis for vm $Name, extension name:$ExtensionName"
- $vm=Get-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $Name -ErrorAction Stop
- Set-AzureRmVMExtension `
- -ResourceGroupName $ResourceGroupName `
- -ExtensionName $ExtensionName `
- -VMName $Name `
- -Publisher Microsoft.Compute `
- -ExtensionType CustomScriptExtension `
- -TypeHandlerVersion 1.4 `
- -SettingString '{"commandToExecute":"powershell Add-WindowsFeature Web-Server; powershell Add-Content -Path \"C:\\inetpub\\wwwroot\\Default.htm\" -Value $($env:computername)"}' `
- -Location $vm.Location
- }
- catch {
- Write-Warning $_
- }
- }
- end {
- }
这个脚本是支持管道操作的, 运行起来非常方便, 比如想给包含 Web 名称的服务器安装 IIS, 可以首先筛选出来这些服务器, 然后通过管道将值传给 install-iis 脚本, 即可通过 extension 进行安装
Get-AzureRMVM -ResourceGroupName test|?{$_.name -like *Web*}|install-iis.ps1
安装完成 IIS 后, 脚本会在 default 页添加计算机名, 访问计算机公网 IP 时, 可以看到已经可以显示计算机的名称
实际上 VM extension 在运行时, 会将命令的内容下载到 VM 内部运行, 可以在 C:\Package\Plugins 里看到这些 extension 的目录
可以直接在文件夹里看到 extension 运行的状态
也可以在 C:\WindowsAzure\Logs\Plugins\Microsoft.Compute.CustomScriptExtension\1.9.3 找到对应的 log 等信息
基本上就是这样, 当然这只是抛砖引玉, Azure VM 的 extension 还是很好用的, 可以做多一些尝试
来源: http://blog.51cto.com/mxyit/2346350