使用 C# 和 Resource Manager 模板部署 Azure 虚拟机Deploy an Azure Virtual Machine using C# and a Resource Manager template

本文介绍如何使用 C# 部署 Azure 资源管理器模板。This article shows you how to deploy an Azure Resource Manager template using C#. 创建的模板会在包含单个子网的新虚拟网络中部署运行 Windows Server 的单个虚拟机。The template that you create deploys a single virtual machine running Windows Server in a new virtual network with a single subnet.

有关虚拟机资源的详细说明,请参阅 Azure 资源管理器模板中的虚拟机For a detailed description of the virtual machine resource, see Virtual machines in an Azure Resource Manager template. 有关模板中所有资源的详细信息,请参阅 Azure 资源管理器模板演练For more information about all the resources in a template, see Azure Resource Manager template walkthrough.

完成这些步骤大约需要 10 分钟。It takes about 10 minutes to do these steps.

创建 Visual Studio 项目Create a Visual Studio project

在此步骤中,请确保已安装 Visual Studio 并已创建用于部署模板的控制台应用程序。In this step, you make sure that Visual Studio is installed and you create a console application used to deploy the template.

  1. 如果尚未安装,请安装 Visual StudioIf you haven't already, install Visual Studio. 在“工作负荷”页上选择“.NET 桌面开发”,然后单击“安装”。Select .NET desktop development on the Workloads page, and then click Install. 在摘要中,可以看到系统已自动选择“.NET Framework 4 4.6 开发工具”。In the summary, you can see that .NET Framework 4 - 4.6 development tools is automatically selected for you. 如果已安装 Visual Studio,则可以使用 Visual Studio 启动器添加 .NET 工作负荷。If you have already installed Visual Studio, you can add the .NET workload using the Visual Studio Launcher.
  2. 在 Visual Studio 中,单击“文件” > “新建” > “项目”。In Visual Studio, click File > New > Project.
  3. 在“模板” > “Visual C#”中,选择“控制台应用(.NET Framework)”,输入 myDotnetProject 作为项目名称,选择项目位置,然后单击“确定”。 In Templates > Visual C#, select Console App (.NET Framework), enter myDotnetProject for the name of the project, select the location of the project, and then click OK.

安装这些包Install the packages

使用 NuGet 包可以最轻松地安装完成这些步骤所需的库。NuGet packages are the easiest way to install the libraries that you need to finish these steps. 若要在 Visual Studio 中获取所需的库,请执行以下步骤:To get the libraries that you need in Visual Studio, do these steps:

  1. 单击“工具” > “Nuget 包管理器”,然后单击“包管理器控制台” 。Click Tools > Nuget Package Manager, and then click Package Manager Console.

  2. 在控制台中键入这些命令:Type these commands in the console:

    Install-Package Microsoft.Azure.Management.Fluent
    Install-Package WindowsAzure.Storage
    

创建文件Create the files

此步骤将创建一个用于部署资源的模板文件和一个用于向模板提供参数值的参数文件。In this step, you create a template file that deploys the resources and a parameters file that supplies parameter values to the template. 还创建用于执行 Azure 资源管理器操作的授权文件。You also create an authorization file that is used to perform Azure Resource Manager operations.

创建模板文件Create the template file

  1. 在解决方案资源管理器中,右键单击myDotnetProject > ,单击“添加 > 新建项,然后在Visual C# 项中选择文本文件In Solution Explorer, right-click myDotnetProject > Add > New Item, and then select Text File in Visual C# Items. 命名文件 CreateVMTemplate.json,然后单击“添加”。Name the file CreateVMTemplate.json, and then click Add.

  2. 将此 JSON 代码添加到创建的文件中:Add this JSON code to the file that you created:

    {
      "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "adminUsername": { "type": "string" },
        "adminPassword": { "type": "securestring" }
      },
      "variables": {
        "vnetID": "[resourceId('Microsoft.Network/virtualNetworks','myVNet')]", 
        "subnetRef": "[concat(variables('vnetID'),'/subnets/mySubnet')]", 
      },
      "resources": [
        {
          "apiVersion": "2016-03-30",
          "type": "Microsoft.Network/publicIPAddresses",
          "name": "myPublicIPAddress",
          "location": "[resourceGroup().location]",
          "properties": {
            "publicIPAllocationMethod": "Dynamic",
            "dnsSettings": {
              "domainNameLabel": "myresourcegroupdns1"
            }
          }
        },
        {
          "apiVersion": "2016-03-30",
          "type": "Microsoft.Network/virtualNetworks",
          "name": "myVNet",
          "location": "[resourceGroup().location]",
          "properties": {
            "addressSpace": { "addressPrefixes": [ "10.0.0.0/16" ] },
            "subnets": [
              {
                "name": "mySubnet",
                "properties": { "addressPrefix": "10.0.0.0/24" }
              }
            ]
          }
        },
        {
          "apiVersion": "2016-03-30",
          "type": "Microsoft.Network/networkInterfaces",
          "name": "myNic",
          "location": "[resourceGroup().location]",
          "dependsOn": [
            "[resourceId('Microsoft.Network/publicIPAddresses/', 'myPublicIPAddress')]",
            "[resourceId('Microsoft.Network/virtualNetworks/', 'myVNet')]"
          ],
          "properties": {
            "ipConfigurations": [
              {
                "name": "ipconfig1",
                "properties": {
                  "privateIPAllocationMethod": "Dynamic",
                  "publicIPAddress": { "id": "[resourceId('Microsoft.Network/publicIPAddresses','myPublicIPAddress')]" },
                  "subnet": { "id": "[variables('subnetRef')]" }
                }
              }
            ]
          }
        },
        {
          "apiVersion": "2016-04-30-preview",
          "type": "Microsoft.Compute/virtualMachines",
          "name": "myVM",
          "location": "[resourceGroup().location]",
          "dependsOn": [
            "[resourceId('Microsoft.Network/networkInterfaces/', 'myNic')]"
          ],
          "properties": {
            "hardwareProfile": { "vmSize": "Standard_DS1" },
            "osProfile": {
              "computerName": "myVM",
              "adminUsername": "[parameters('adminUsername')]",
              "adminPassword": "[parameters('adminPassword')]"
            },
            "storageProfile": {
              "imageReference": {
                "publisher": "MicrosoftWindowsServer",
                "offer": "WindowsServer",
                "sku": "2012-R2-Datacenter",
                "version": "latest"
              },
              "osDisk": {
                "name": "myManagedOSDisk",
                "caching": "ReadWrite",
                "createOption": "FromImage"
              }
            },
            "networkProfile": {
              "networkInterfaces": [
                {
                  "id": "[resourceId('Microsoft.Network/networkInterfaces','myNic')]"
                }
              ]
            }
          }
        }
      ]
    }
    
  3. 保存 CreateVMTemplate.json 文件。Save the CreateVMTemplate.json file.

创建参数文件Create the parameters file

若要为模板中的资源参数指定值,请创建包含值的参数文件。To specify values for the resource parameters in the template, you create a parameters file that contains the values.

  1. 在解决方案资源管理器中,右键单击myDotnetProject > ,单击“添加 > 新建项,然后在Visual C# 项中选择文本文件In Solution Explorer, right-click myDotnetProject > Add > New Item, and then select Text File in Visual C# Items. 命名文件 Parameters.json,然后单击“添加”。Name the file Parameters.json, and then click Add.

  2. 将此 JSON 代码添加到创建的文件中:Add this JSON code to the file that you created:

    {
      "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "adminUserName": { "value": "azureuser" },
        "adminPassword": { "value": "Azure12345678" }
      }
    }
    
  3. 保存 Parameters.json 文件。Save the Parameters.json file.

创建授权文件Create the authorization file

在可部署模板之前,请先确保能够访问 Active Directory 服务主体Before you can deploy a template, make sure that you have access to an Active Directory service principal. 从服务主体中,将获取对 Azure 资源管理器请求进行身份验证的令牌。From the service principal, you acquire a token for authenticating requests to Azure Resource Manager. 还应记录授权文件中所需的应用程序 ID、身份验证秘钥和的租户 ID。You should also record the application ID, the authentication key, and the tenant ID that you need in the authorization file.

  1. 在解决方案资源管理器中,右键单击myDotnetProject > ,单击“添加 > 新建项,然后在Visual C# 项中选择文本文件In Solution Explorer, right-click myDotnetProject > Add > New Item, and then select Text File in Visual C# Items. 命名文件 azureauth.properties,然后单击“添加”。Name the file azureauth.properties, and then click Add.

  2. 添加这些授权属性:Add these authorization properties:

    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> 替换为租户标识符 。Replace <subscription-id> with your subscription identifier, <application-id> with the Active Directory application identifier, <authentication-key> with the application key, and <tenant-id> with the tenant identifier.

  3. 保存 azureauth.properties 文件。Save the azureauth.properties file.

  4. 在 Windows 中设置名为 AZURE_AUTH_LOCATION 的环境变量,其中包含创建的授权文件的完整路径,例如,可以使用以下 PowerShell 命令:Set an environment variable in Windows named AZURE_AUTH_LOCATION with the full path to authorization file that you created, for example you can use the following PowerShell command:

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

创建管理客户端Create the management client

  1. 打开所创建项目的 Program.cs 文件。Open the Program.cs file for the project that you created. 然后,将这些 using 语句添加到文件顶部的现有语句:Then, add these using statements to the existing statements at top of the file:

    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;
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Blob;
    
  2. 若要创建管理客户端,请将以下代码添加到 Main 方法:To create the management client, add this code to the Main method:

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

创建资源组Create a resource group

若要指定应用程序的值,请将代码添加到 Main 方法:To specify values for the application, add code to the Main method:

var groupName = "myResourceGroup";
var location = Region.ChinaNorth;

var resourceGroup = azure.ResourceGroups.Define(groupName)
    .WithRegion(location)
    .Create();

创建存储帐户Create a storage account

模板和参数是从 Azure 中的存储帐户部署的。The template and parameters are deployed from a storage account in Azure. 此步骤将创建帐户并上传文件。In this step, you create the account and upload the files.

若要创建帐户,请将此代码添加到 Main 方法:To create the account, add this code to the Main method:

string storageAccountName = SdkContext.RandomResourceName("st", 10);

Console.WriteLine("Creating storage account...");
var storage = azure.StorageAccounts.Define(storageAccountName)
    .WithRegion(Region.ChinaNorth)
    .WithExistingResourceGroup(resourceGroup)
    .Create();

var storageKeys = storage.GetKeys();
string storageConnectionString = "DefaultEndpointsProtocol=https;"
    + "AccountName=" + storage.Name
    + ";AccountKey=" + storageKeys[0].Value
    + ";EndpointSuffix=core.chinacloudapi.cn";

var account = CloudStorageAccount.Parse(storageConnectionString);
var serviceClient = account.CreateCloudBlobClient();

Console.WriteLine("Creating container...");
var container = serviceClient.GetContainerReference("templates");
container.CreateIfNotExistsAsync().Wait();
var containerPermissions = new BlobContainerPermissions()
    { PublicAccess = BlobContainerPublicAccessType.Container };
container.SetPermissionsAsync(containerPermissions).Wait();

Console.WriteLine("Uploading template file...");
var templateblob = container.GetBlockBlobReference("CreateVMTemplate.json");
templateblob.UploadFromFileAsync("..\\..\\CreateVMTemplate.json").Result();

Console.WriteLine("Uploading parameters file...");
var paramblob = container.GetBlockBlobReference("Parameters.json");
paramblob.UploadFromFileAsync("..\\..\\Parameters.json").Result();

部署模板Deploy the template

从创建的存储帐户部署模板和参数。Deploy the template and parameters from the storage account that was created.

若要部署模板,请将此代码添加到 Main 方法:To deploy the template, add this code to the Main method:

var templatePath = "https://" + storageAccountName + ".blob.core.chinacloudapi.cn/templates/CreateVMTemplate.json";
var paramPath = "https://" + storageAccountName + ".blob.core.chinacloudapi.cn/templates/Parameters.json";
var deployment = azure.Deployments.Define("myDeployment")
    .WithExistingResourceGroup(groupName)
    .WithTemplateLink(templatePath, "1.0.0.0")
    .WithParametersLink(paramPath, "1.0.0.0")
    .WithMode(Microsoft.Azure.Management.ResourceManager.Fluent.Models.DeploymentMode.Incremental)
    .Create();
Console.WriteLine("Press enter to delete the resource group...");
Console.ReadLine();

删除资源Delete the resources

由于需要为 Azure 中使用的资源付费,因此,删除不再需要的资源总是一种良好的做法。Because you are charged for resources used in Azure, it is always good practice to delete resources that are no longer needed. 不需要从资源组中分别删除每个资源,You don't need to delete each resource separately from a resource group. 删除资源组,其中包含的所有资源会一并删除。Delete the resource group and all its resources are automatically deleted.

若要删除资源组,请将以下代码添加到 Main 方法:To delete the resource group, add this code to the Main method:

azure.ResourceGroups.DeleteByName(groupName);

运行应用程序Run the application

控制台应用程序从头到尾完成运行大约需要五分钟时间。It should take about five minutes for this console application to run completely from start to finish.

  1. 若要运行控制台应用程序,请单击“开始”。To run the console application, click Start.

  2. 在按 Enter 开始删除资源之前,可能需要在 Azure 门户中花几分钟时间来验证资源的创建。Before you press Enter to start deleting resources, you could take a few minutes to verify the creation of the resources in the Azure portal. 单击部署状态以查看有关部署的信息。Click the deployment status to see information about the deployment.

后续步骤Next steps