[Azure]使用Powershell将ARM虚拟机加入可用性集

60 篇文章 0 订阅
59 篇文章 0 订阅

Azure ARM模式下创建的虚拟机只有一次机会加入可用性集,也就是在这台虚拟机新创建的时候,创建完成后,就不能变更可用性集的设置了。

而偏偏可用性集又与负载均衡等功能密切相关,只有加入同一可用性集的虚拟机才能配置负载均衡等功能,所以这就尴尬了,只能删除虚拟机保留磁盘,然后再重建虚拟机将其加入可用性集。

下面的脚本可以帮助自动完成这个过程,首先脚本会收集当前虚拟机的信息(基本信息,磁盘,网络等),然后将当前虚拟机删除,然后根据收集到的信息重新将虚拟机创建出来。

注意:虚拟机的扩展和诊断设置目前不能在重建过程中恢复,脚本适用于非托管磁盘的虚拟机(托管磁盘虚拟机的脚本以后会给出),脚本不会保留虚拟机的IP地址,因此如果有需要,请将IP地址设置为静态。

脚本如下(有一些注释掉的内容可以自行删除):

param(
    [Parameter(Mandatory = $true)] 
    [string]$SubscriptionName, 
 
    [Parameter(Mandatory = $true)]
    [string]$ResourceGroupName,


    [Parameter(Mandatory = $true)]
    [string]$VMName,


    [Parameter(Mandatory = $true)]
    [string]$AvailabilitySetName
)


#Function GetResourceNameFromResourceId($resourceId)
#{
#    return $resourceId.Substring($resourceId.LastIndexOf('/') + 1);
#}


#Function GetResourcePropertyFromResourceId($resourceId, $propertyName)
#{
#    $propertyName = $propertyName + "/";
#    $rgName = $resourceId.Substring($resourceId.IndexOf($propertyName) + $propertyName.Length);
#    return $rgName.Substring(0, $rgName.IndexOf("/"));
#}


Function CollectVMInformation($rgName, $vmName, $avaSetName)
{
    $vmInfo = @{};
    $vmInfo.Add("ResourceGroup", $rgName);
    $vmInfo.Add("Name", $vmName);
    
    $vm = Get-AzureRmVM -ResourceGroupName $rgName -Name $vmName -ErrorAction Ignore -WarningAction Ignore;
    if ($vm -eq $null)
    {
        return $null;
    }


    $vmInfo.Add("Size", $vm.HardwareProfile.VmSize);
    $vmInfo.Add("Location", $vm.Location);
    if (!(CreateAvailabilitySet $rgName $avaSetName $vm.Location))
    {
        return $null;
    }
    $avaSet = Get-AzureRmAvailabilitySet -ResourceGroupName $rgName -Name $avaSetName;
    $vmInfo.Add("AvailabilitySet", $avaSet.Id);


    $vmInfo.Add("OSType", $vm.StorageProfile.OsDisk.OsType.ToString());


    #network properties
    $nicId = ($vm.NetworkProfile.NetworkInterfaces | where {$_.Primary -eq $true}).Id;
    if ($nicId -eq $null -and $vm.NetworkProfile.NetworkInterfaces.Count -eq 1)
    {
        $nicId = $vm.NetworkProfile.NetworkInterfaces[0].Id;
    }
    #$nicName = GetResourceNameFromResourceId $nicId;
    #$nic = Get-AzureRmNetworkInterface -Name $nicName -ResourceGroupName $rgName;
    #$subnetId = $nic.IpConfigurations[0].Subnet.Id;
    #$subnetName = GetResourceNameFromResourceId $subnetId;
    #$vnetName = GetResourcePropertyFromResourceId $subnetId "virtualNetworks";
    #$vmInfo.Add("VirtualNetwork", $vnetName);
    #$vmInfo.Add("Subnet", $subnetName);
    $vmInfo.Add("PrimaryNetworkInterfaceId", $nicId);


    $secondaryNics = @($vm.NetworkProfile.NetworkInterfaces | where {$_.Primary -eq $false});
    $vmInfo.Add("SecondaryNetworkInterfaces", $secondaryNics);
    #$vnet = Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $rgName;
    #$subnet01 = Get-AzureRmVirtualNetworkSubnetConfig -Name $subnetName -VirtualNetwork $vnet;


    #disk
    $vmInfo.Add("OSDisk", $vm.StorageProfile.OsDisk);
    $vmInfo.Add("DataDisks", @($vm.StorageProfile.DataDisks));


    return $vmInfo;
}


Function DeleteOldVM($rgName, $vmName)
{
    [void](Remove-AzureRmVM -ResourceGroupName $rgName -Name $vmName -Force);
    #if lease is not broken, we need to sleep for some time
    #sleep 10
}


Function CreateAvailabilitySet($rgName, $avaSetName, $location)
{
    $avaSet = Get-AzureRmAvailabilitySet -ResourceGroupName $rgName -Name $avaSetName -ErrorAction Ignore;
    if ($avaSet -eq $null)
    {
        $avaSet = New-AzureRmAvailabilitySet -ResourceGroupName $rgName -Name $avaSetName -Location $location;
        return $true;
    } 
    elseif ($avaSet.Sku -ne "Classic")
    {
        Write-Host "There's an existing availability set whose sku is not Classic, conflict!";
        return $false;
    } else {
        return $true;
    }
}


Function RebuildVM($vmInfo)
{
    #basic information
    $rgName = $vmInfo["ResourceGroup"];
    $vmName = $vmInfo["Name"];
    $vmSize = $vmInfo["Size"];
    $location = $vmInfo["Location"];
    $osType = $vmInfo["OSType"];


    #network
    #$vnetName = $vmInfo["VirtualNetwork"];
    #$subnetName = $vmInfo["Subnet"];
    $primaryNicId = $vmInfo["PrimaryNetworkInterfaceId"];
    $secondaryNics = $vmInfo["SecondaryNetworkInterfaces"];
    
    #disk
    $osDisk = $vmInfo["OSDisk"];
    $dataDisks = $vmInfo["DataDisks"];


    $avaSetId = $vmInfo["AvailabilitySet"];
    $vmconfig = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize -AvailabilitySetId $avaSetId;
    $vmconfig = $vmconfig | Set-AzureRmVMBootDiagnostics -Disable;


    if ($osType -eq "Windows")
    {
        $vmconfig = $vmconfig | Set-AzureRmVMOSDisk –Name $osDisk.Name -VhdUri $osDisk.Vhd.Uri -Caching $osDisk.Caching -CreateOption attach -Windows;
    } else {
        $vmconfig = $vmconfig | Set-AzureRmVMOSDisk –Name $osDisk.Name -VhdUri $osDisk.Vhd.Uri -Caching $osDisk.Caching -CreateOption attach -Linux;
    }
    $vmconfig.StorageProfile.ImageReference = $null;


    foreach ($dataDisk in $dataDisks)
    {
        $vmconfig = $vmconfig | Add-AzureRmVMDataDisk -Name $dataDisk.Name -VhdUri $dataDisk.Vhd.Uri -Lun $dataDisk.Lun -Caching $dataDisk.Caching -CreateOption attach;
    }


    $vmconfig = $vmconfig | Add-AzureRmVMNetworkInterface -Id $primaryNicId -Primary;
    foreach ($secondaryNic in $secondaryNics)
    {
        $secondaryNicId = $secondaryNic.Id;
        $vmconfig = $vmconfig | Add-AzureRmVMNetworkInterface -Id $secondaryNicId;
    }


    [void](New-AzureRmVM -ResourceGroupName $rgName -Location $location -VM $vmconfig);
}


[void](Select-AzureRmSubscription -SubscriptionName $SubscriptionName);


Write-Host "Collecting VM information...";
$vmInfo = (CollectVMInformation $ResourceGroupName $VMName $AvailabilitySetName);
if ($vmInfo -eq $null)
{
    Write-Host "Failed to collect vm information." -ForegroundColor Red;
    return;
}


Write-Host "Deleting old VM...";
DeleteOldVM $ResourceGroupName $VMName;


Write-Host "Rebuilding VM...";
RebuildVM $vmInfo;


Write-Host "Finished";


脚本运行示例:


脚本参数中指定的AvailabilitySetName可以是已有的,也可以指定不存在的,如果不存在的话,会新建一个AvailabilitySet,注意AvailabilitySet是区分托管和非托管的。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值