在ARM模式下捕獲VM並建立新VM

衡子發表於2017-03-24

在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會失敗。

相關文章