使用 C# 创建和管理 Azure 中的 Windows VM

Azure 虚拟机 (VM) 需要多个支持性 Azure 资源。 本文介绍如何使用 C# 创建、管理和删除 VM 资源。 你将学习如何执行以下操作:

  • 创建 Visual Studio 项目
  • 安装包
  • 创建凭据
  • 创建资源
  • 执行管理任务
  • 删除资源
  • 运行应用程序

完成这些步骤大约需要 20 分钟。

创建 Visual Studio 项目

  1. 如果尚未安装,请安装 Visual Studio。 在“工作负荷”页上选择“.NET 桌面开发”,然后单击“安装”。 在摘要中,可以看到系统自动选择了“.NET Framework 4 - 4.6 开发工具”。 如果已安装 Visual Studio,则可以使用 Visual Studio 启动器添加 .NET 工作负荷。
  2. 在 Visual Studio 中,单击“文件” > “新建” > “项目”。
  3. 在“模板” > “Visual C#”中,选择“控制台应用(.NET Framework)”,输入 myDotnetProject 作为项目名称,选择项目的位置,然后单击“确定”。

安装包

使用 NuGet 包可以最轻松地安装完成这些步骤所需的库。 若要在 Visual Studio 中获取所需的库,请执行以下步骤:

  1. 单击“工具” > “Nuget 包管理器”,然后单击“包管理器控制台”。
  2. 在控制台中键入此命令:

    Install-Package Microsoft.Azure.Management.Fluent
    

创建凭据

在开始此步骤之前,请确保能够访问 Active Directory 服务主体。 此外,应记下应用程序 ID、身份验证密钥和租户 ID,以便在后面的步骤中使用。

创建授权文件

  1. 在解决方案资源管理器中,右键单击“myDotnetProject” > “添加” > “新建项”,然后在“Visual C# 项”中选择“文本文件”。 将文件命名为 azureauth.properties,然后单击“添加”。
  2. 添加这些授权属性:

    subscription=<subscription-id>
    client=<application-id>
    key=<authentication-key>
    tenant=<tenant-id>
    managementURI=https://management.core.chinacloudapi.cn/
    baseURL=https://management.chinacloudapi.cn/
    authURL=https://login.chinacloudapi.cn/
    graphURL=https://graph.chinacloudapi.cn/
    

    将 <subscription-id> 替换为订阅标识符,将 <application-id> 替换为 Active Directory 应用程序标识符,将 <authentication-key> 替换为应用程序密钥,将 <tenant-id> 替换为租户标识符。

  3. 保存 azureauth.properties 文件。

  4. 在 Windows 中设置名为 AZURE_AUTH_LOCATION 的环境变量,其中包含创建的授权文件的完整路径。 例如,可以使用以下 PowerShell 命令:

    [Environment]::SetEnvironmentVariable("AZURE_AUTH_LOCATION", "C:\Visual Studio 2017\Projects\myDotnetProject\myDotnetProject\azureauth.properties", "User")
    

创建管理客户端

  1. 为所创建的项目打开 Program.cs 文件,然后将这些 using 语句添加到文件顶部的现有语句:

    using Microsoft.Azure.Management.Compute.Fluent;
    using Microsoft.Azure.Management.Compute.Fluent.Models;
    using Microsoft.Azure.Management.Fluent;
    using Microsoft.Azure.Management.ResourceManager.Fluent;
    using Microsoft.Azure.Management.ResourceManager.Fluent.Core;
    
  2. 若要创建管理客户端,请将以下代码添加到 Main 方法:

    var credentials = SdkContext.AzureCredentialsFactory
        .FromFile(Environment.GetEnvironmentVariable("AZURE_AUTH_LOCATION"));
    
    var azure = Azure
        .Configure()
        .WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
        .Authenticate(credentials)
        .WithDefaultSubscription();
    

创建资源

创建资源组

必须在资源组中包含所有资源。

若要指定应用程序的值并创建资源组,请将以下代码添加到 Main 方法:

var groupName = "myResourceGroup";
var vmName = "myVM";
var location = Region.USWest;

Console.WriteLine("Creating resource group...");
var resourceGroup = azure.ResourceGroups.Define(groupName)
    .WithRegion(location)
    .Create();

创建可用性集

使用可用性集可以更方便地维护应用程序所用的虚拟机。

若要创建可用性集,请将以下代码添加到 Main 方法:

Console.WriteLine("Creating availability set...");
var availabilitySet = azure.AvailabilitySets.Define("myAVSet")
    .WithRegion(location)
    .WithExistingResourceGroup(groupName)
    .WithSku(AvailabilitySetSkuTypes.Managed)
    .Create();

创建公共 IP 地址

与虚拟机通信需要公共 IP 地址

若要创建虚拟机的公共 IP 地址,请将以下代码添加到 Main 方法:

Console.WriteLine("Creating public IP address...");
var publicIPAddress = azure.PublicIPAddresses.Define("myPublicIP")
    .WithRegion(location)
    .WithExistingResourceGroup(groupName)
    .WithDynamicIP()
    .Create();

创建虚拟网络

虚拟机必须在虚拟网络的子网中。

若要创建子网和虚拟网络,请将以下代码添加到 Main 方法:

Console.WriteLine("Creating virtual network...");
var network = azure.Networks.Define("myVNet")
    .WithRegion(location)
    .WithExistingResourceGroup(groupName)
    .WithAddressSpace("10.0.0.0/16")
    .WithSubnet("mySubnet", "10.0.0.0/24")
    .Create();

创建网络接口

虚拟机需要使用网络接口在虚拟网络上通信。

若要创建网络接口,请将以下代码添加到 Main 方法:

Console.WriteLine("Creating network interface...");
var networkInterface = azure.NetworkInterfaces.Define("myNIC")
    .WithRegion(location)
    .WithExistingResourceGroup(groupName)
    .WithExistingPrimaryNetwork(network)
    .WithSubnet("mySubnet")
    .WithPrimaryPrivateIPAddressDynamic()
    .WithExistingPrimaryPublicIPAddress(publicIPAddress)
    .Create();

创建虚拟机

创建所有支持资源后,即可创建虚拟机。

若要创建虚拟机,请将以下代码添加到 Main 方法:

Console.WriteLine("Creating virtual machine...");
azure.VirtualMachines.Define(vmName)
    .WithRegion(location)
    .WithExistingResourceGroup(groupName)
    .WithExistingPrimaryNetworkInterface(networkInterface)
    .WithLatestWindowsImage("MicrosoftWindowsServer", "WindowsServer", "2012-R2-Datacenter")
    .WithAdminUsername("azureuser")
    .WithAdminPassword("Azure12345678")
    .WithComputerName(vmName)
    .WithExistingAvailabilitySet(availabilitySet)
    .WithSize(VirtualMachineSizeTypes.StandardDS1)
    .Create();
Note

本教程创建运行 Windows Server 操作系统版本的虚拟机。 若要详细了解如何选择其他映像,请参阅使用 Windows PowerShell 和 Azure CLI 来导航和选择 Azure 虚拟机映像

如果要使用现有磁盘而不是商城映像,请使用以下代码:

var managedDisk = azure.Disks.Define("myosdisk")
    .WithRegion(location)
    .WithExistingResourceGroup(groupName)
    .WithWindowsFromVhd("https://mystorage.blob.core.chinacloudapi.cn/vhds/myosdisk.vhd")
    .WithSizeInGB(128)
    .WithSku(DiskSkuTypes.PremiumLRS)
    .Create();

azure.VirtualMachines.Define("myVM")
    .WithRegion(location)
    .WithExistingResourceGroup(groupName)
    .WithExistingPrimaryNetworkInterface(networkInterface)
    .WithSpecializedOSDisk(managedDisk, OperatingSystemTypes.Windows)
    .WithExistingAvailabilitySet(availabilitySet)
    .WithSize(VirtualMachineSizeTypes.StandardDS1)
    .Create();

执行管理任务

在虚拟机生命周期中,可能需要运行管理任务,例如启动、停止或删除虚拟机。 此外,建议创建代码来自动执行重复或复杂的任务。

如需对 VM 执行任何操作,需获取其实例:

var vm = azure.VirtualMachines.GetByResourceGroup(groupName, vmName);

获取有关 VM 的信息

若要获取有关虚拟机的信息,请将以下代码添加到 Main 方法:

Console.WriteLine("Getting information about the virtual machine...");
Console.WriteLine("hardwareProfile");
Console.WriteLine("   vmSize: " + vm.Size);
Console.WriteLine("storageProfile");
Console.WriteLine("  imageReference");
Console.WriteLine("    publisher: " + vm.StorageProfile.ImageReference.Publisher);
Console.WriteLine("    offer: " + vm.StorageProfile.ImageReference.Offer);
Console.WriteLine("    sku: " + vm.StorageProfile.ImageReference.Sku);
Console.WriteLine("    version: " + vm.StorageProfile.ImageReference.Version);
Console.WriteLine("  osDisk");
Console.WriteLine("    osType: " + vm.StorageProfile.OsDisk.OsType);
Console.WriteLine("    name: " + vm.StorageProfile.OsDisk.Name);
Console.WriteLine("    createOption: " + vm.StorageProfile.OsDisk.CreateOption);
Console.WriteLine("    caching: " + vm.StorageProfile.OsDisk.Caching);
Console.WriteLine("osProfile");
Console.WriteLine("  computerName: " + vm.OSProfile.ComputerName);
Console.WriteLine("  adminUsername: " + vm.OSProfile.AdminUsername);
Console.WriteLine("  provisionVMAgent: " + vm.OSProfile.WindowsConfiguration.ProvisionVMAgent.Value);
Console.WriteLine("  enableAutomaticUpdates: " + vm.OSProfile.WindowsConfiguration.EnableAutomaticUpdates.Value);
Console.WriteLine("networkProfile");
foreach (string nicId in vm.NetworkInterfaceIds)
{
    Console.WriteLine("  networkInterface id: " + nicId);
}
Console.WriteLine("vmAgent");
Console.WriteLine("  vmAgentVersion" + vm.InstanceView.VmAgent.VmAgentVersion);
Console.WriteLine("    statuses");
foreach (InstanceViewStatus stat in vm.InstanceView.VmAgent.Statuses)
{
    Console.WriteLine("    code: " + stat.Code);
    Console.WriteLine("    level: " + stat.Level);
    Console.WriteLine("    displayStatus: " + stat.DisplayStatus);
    Console.WriteLine("    message: " + stat.Message);
    Console.WriteLine("    time: " + stat.Time);
}
Console.WriteLine("disks");
foreach (DiskInstanceView disk in vm.InstanceView.Disks)
{
    Console.WriteLine("  name: " + disk.Name);
    Console.WriteLine("  statuses");
    foreach (InstanceViewStatus stat in disk.Statuses)
    {
        Console.WriteLine("    code: " + stat.Code);
        Console.WriteLine("    level: " + stat.Level);
        Console.WriteLine("    displayStatus: " + stat.DisplayStatus);
        Console.WriteLine("    time: " + stat.Time);
    }
}
Console.WriteLine("VM general status");
Console.WriteLine("  provisioningStatus: " + vm.ProvisioningState);
Console.WriteLine("  id: " + vm.Id);
Console.WriteLine("  name: " + vm.Name);
Console.WriteLine("  type: " + vm.Type);
Console.WriteLine("  location: " + vm.Region);
Console.WriteLine("VM instance status");
foreach (InstanceViewStatus stat in vm.InstanceView.Statuses)
{
    Console.WriteLine("  code: " + stat.Code);
    Console.WriteLine("  level: " + stat.Level);
    Console.WriteLine("  displayStatus: " + stat.DisplayStatus);
}
Console.WriteLine("Press enter to continue...");
Console.ReadLine();

停止 VM

可停止虚拟机并保留其所有设置,但需继续付费;还可停止虚拟机并解除分配。 解除分配某个虚拟机也会解除分配与其关联的所有资源,并停止该虚拟机的计费。

若要停止虚拟机而不解除分配虚拟机,请将以下代码添加到 Main 方法:

Console.WriteLine("Stopping vm...");
vm.PowerOff();
Console.WriteLine("Press enter to continue...");
Console.ReadLine();

要解除分配虚拟机,请将 PowerOff 调用更改为以下代码:

vm.Deallocate();

启动 VM

若要启动虚拟机,请将以下代码添加到 Main 方法:

Console.WriteLine("Starting vm...");
vm.Start();
Console.WriteLine("Press enter to continue...");
Console.ReadLine();

重设 VM 大小

决定虚拟机大小时应考虑部署的诸多方面。 有关详细信息,请参见 VM 大小

若要更改虚拟机大小,请将以下代码添加到 Main 方法:

Console.WriteLine("Resizing vm...");
vm.Update()
    .WithSize(VirtualMachineSizeTypes.StandardDS2) 
    .Apply();
Console.WriteLine("Press enter to continue...");
Console.ReadLine();

将数据磁盘添加到 VM

若要将数据磁盘添加到虚拟机,请将以下代码添加到 Main 方法,以添加大小为 2 GB 的数据磁盘,以及为 0 的 LUN 和 ReadWrite 缓存类型:

Console.WriteLine("Adding data disk to vm...");
vm.Update()
    .WithNewDataDisk(2, 0, CachingTypes.ReadWrite) 
    .Apply();
Console.WriteLine("Press enter to delete resources...");
Console.ReadLine();

删除资源

由于需要为 Azure 中使用的资源付费,因此,删除不再需要的资源总是一种良好的做法。 如果要删除虚拟机和所有支持资源,只需删除资源组。

若要删除资源组,请将以下代码添加到 Main 方法:

azure.ResourceGroups.DeleteByName(groupName);

运行应用程序

控制台应用程序从头到尾完成运行大约需要五分钟时间。

  1. 若要运行控制台应用程序,请单击“启动”。

  2. 在按 Enter 开始删除资源之前,可能需要在 Azure 门户中花几分钟时间来验证这些资源是否已创建。 单击部署状态以查看有关部署的信息。

后续步骤