在 ARM 模式下捕获 VM 并创建新 VM
在 ASM 模式下,可以通过 Manage Portal 上捕获 VM 的 Image,并创建新的 VM 。在 ARM 模式下,在 Portal 上目前还没有这个功能,要做 VM 镜像的捕获和创建新的 VM 需要用powershell 或 Azure CLI 来实现。
本文将介绍如何用 Powershell 捕获 VM 的镜像,并用 Powershell 从这个 Image 创建新的 VM 。
一、VM 的 Generalized
本文采用的是 Linux CentOS 的机器,需要通过 waageng 对其进行 Generalized 。就是删除用户信息:
[root@hwhpc04 ~]# waagent -deprovision+user
WARNING! The waagent service will be stopped.
WARNING! All SSH host key pairs will be deleted.
WARNING! Cached DHCP leases will be deleted.
WARNING! Nameserver configuration in /etc/resolv.conf will be deleted.
WARNING! root password will be disabled. You will not be able to login as root.
WARNING! hengwei account and entire home directory will be deleted.
Do you want to proceed (y/n)? y
[root@hwhpc04 ~]#
结束后,在 portal 上关机。
二、在 Powershell 下捕获镜像
下面的 Powershell 脚本进行了
1. VM 的 Generalized
2. Capture VM image
3. 从捕获的 Image 创建一台 VM
具体的 Powershell 代码如下:
function cpt-crtvm {
param(
#The VM resource group
[Parameter(Mandatory=$true)]
[String]$rg,
#The VM name
[Parameter(Mandatory=$true)]
[String]$vm_name,
#The new VM admin name
[Parameter(Mandatory=$true)]
[String]$newuser,
#The new VM password
[Parameter(Mandatory=$true)]
[String]$newpwd,
#The new VM size
[Parameter(Mandatory=$true)]
[String]$newvmsize,
#haset name
[Parameter(Mandatory=$true)]
[String]$haset
)
#Get a random text as the VM new name
$subhash = $null
for ($i = 0; $i -le 4; $i++){
$j = (97..122) | Get-Random -Count 1 | % {[char]$_}
$subhash = $subhash + $j
}
for ($i = 0; $i -le 4; $i++){
$j = (48..57) | Get-Random -Count 1 | % {[char]$_}
$subhash = $subhash + $j
}
#Get the VM need to be generalized
$vm = get-azurermvm -ResourceGroupName $rg -Name $vm_name
#New VM name from the radom text
$newvmname = $subhash + "vm"
#old VM generalized
set-azurermvm -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Generalized
#Catpture the VM to image
Save-AzureRmVMImage -Name $vm.Name -DestinationContainerName $subhash -VHDNamePrefix
$subhash -ResourceGroupName $vm.ResourceGroupName -Path d:\hwhpc.json
#get the storage related information
$sa = Get-AzureRmStorageAccount -ResourceGroupName $vm.ResourceGroupName -Name $vm.
StorageProfile.OsDisk.Vhd.Uri.Split("/")[2].split(".")[0]
$blob = $sa | Get-AzureStorageBlob -Container system | Where-Object {$_.name -match "$subhash.*vhd$"}
$url = $blob.Context.BlobEndPoint + "system/" + $blob.Name
#get the network related information
$nicname = $vm.NetworkProfile.NetworkInterfaces[0].Id.Split("/")[-1]
$vmnic = Get-AzureRmNetworkInterface -Name $nicname -ResourceGroupName $vm.ResourceGroupName
$vnetname = $vmnic.IpConfigurations[0].Subnet.Id.Split("/")[-3]
$vmvnet = Get-AzureRmVirtualNetwork -Name $vnetname -ResourceGroupName $vm.ResourceGroupName
#new VM pip name
$newvmnamepip = $subhash+"vmpip"
#create new public ip address
New-AzureRmPublicIpAddress -Name $newvmname -ResourceGroupName $vm.ResourceGroupName -Location
"China East" -AllocationMethod Dynamic -DomainNameLabel $newvmnamepip
$newvmpip = Get-AzureRmPublicIpAddress -Name $newvmname -ResourceGroupName $vm.ResourceGroupName
#create new nic
New-AzureRmNetworkInterface -Name $newvmname -ResourceGroupName $vm.ResourceGroupName -Location
"China East" -SubnetId $vmvnet.Subnets[0].Id -PublicIpAddressId $newvmpip.Id
$newvmnic = Get-AzureRmNetworkInterface -ResourceGroupName $vm.ResourceGroupName -Name $newvmname
#create the new vm credential
$pwd=ConvertTo-SecureString $newpwd -AsPlainText -Force
$newvmcred=New-Object System.Management.Automation.PSCredential($newuser,$pwd)
#newOSDiskName
$newosDiskName = $newvmname+"osdisk"
#haset
$has = Get-AzureRmAvailabilitySet -ResourceGroupName $vm.ResourceGroupName
$harslt = $false
foreach ($h in $ha){if($h.name -eq $haset){$harslt = $true}}
if(-not $harslt) {New-AzureRmAvailabilitySet -ResourceGroupName $vm.ResourceGroupName
-Name $haset -Location $vm.Location}
$has = Get-AzureRmAvailabilitySet -ResourceGroupName $vm.ResourceGroupName -Name $haset
#Put the VM config to VM
$newvmconfig = New-AzureRmVMConfig -VMName $newvmname -VMSize $newvmsize
-AvailabilitySetId $has.Id
$newvm = Set-AzureRmVMOperatingSystem -VM $newvmconfig -Linux -ComputerName
$newvmname -Credential $newvmcred
$newvm = Add-AzureRmVMNetworkInterface -vm $newvm -Id $newvmnic.Id
$newosDiskUri = '{0}vhds/{1}-{2}.vhd' -f $sa.PrimaryEndpoints.Blob.ToString(), "vm",
$newosDiskName
$newvm = Set-AzureRmVMOSDisk -VM $newvm -name $newosDiskName -VhdUri $newosDiskUri
-CreateOption FromImage -SourceImageUri $url -Linux
$result = new-azurermvm -ResourceGroupName $vm.ResourceGroupName -Location $vm.Location -VM $newvm
}
cpt-crtvm -rg hwhpc -vm_name hwhpc03 -newuser xxxxxxx -newpwd xxxxxxx -newvmsize Standard_D1 -haset a1
代码中用了随机的 Text (5个字母5个数字)来定义 VM 的名字。当然也可以自己定义机器的名称。
但如果自己定义机器的名称,建议在创建 VM 的各个组件前先检查这些组件是否有重名的情况,否则创建 VM 会失败。