使用 C# 和资源管理器模板部署 Azure 虚拟机

本文介绍如何使用 C# 部署 Azure 资源管理器模板。 创建的模板在具有单个子网的新虚拟网络中部署运行 Windows Server 的单个虚拟机。

有关虚拟机资源的详细说明,请参阅 Azure 资源管理器模板中的虚拟机。 有关模板中所有资源的详细信息,请参阅 Azure 资源管理器模板演练

执行这些步骤大约需要 10 分钟。

创建 Visual Studio 项目

在此步骤中,请确保已安装 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
    Install-Package WindowsAzure.Storage
    

创建文件

在此步骤中,你将创建一个模板文件,用于部署资源,以及一个参数文件,该文件向模板提供参数值。 还可以创建用于执行 Azure 资源管理器操作的授权文件。

创建模板文件

  1. 在解决方案资源管理器中,右键单击 myDotnetProject>添加新>,然后选择 Visual C# 项中的文本文件 将文件命名为CreateVMTemplate.json,然后单击“添加”。

  2. 将此 JSON 代码添加到所创建的文件:

    {
      "$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 文件。

创建参数文件

若要在模板中指定资源参数的值,请创建一个包含这些值的参数文件。

  1. 在解决方案资源管理器中,右键单击 myDotnetProject>添加新>,然后选择 Visual C# 项中的文本文件 将文件命名为Parameters.json,然后单击“添加”。

  2. 将此 JSON 代码添加到所创建的文件:

    {
      "$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 文件。

创建授权文件

在部署模板之前,请确保有权访问 Active Directory 服务主体。 从服务主体获取用于对 Azure 资源管理器的请求进行身份验证的令牌。 还应在授权文件中记录应用程序 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.windows.net/
    baseURL=https://management.azure.com/
    authURL=https://login.windows.net/
    graphURL=https://graph.microsoft.com/
    

    订阅 ID> 替换为<订阅标识符,<将应用程序 ID> 替换为 Active Directory 应用程序标识符,<将身份验证密钥>替换为应用程序密钥,将<租户 ID> 替换为租户标识符。

  3. 保存 azureauth.properties 文件。

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

    [Environment]::SetEnvironmentVariable("AZURE_AUTH_LOCATION", "C:\Visual Studio 2019\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;
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Blob;
    
  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 ___location = Region.USWest;

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

创建存储帐户

模板和参数是从 Azure 中的存储帐户部署的。 在此步骤中,将创建帐户并上传文件。

若要创建帐户,请将此代码添加到 Main 方法:

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

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

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

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();

部署模板

从创建的存储帐户部署模板和参数。

若要部署模板,请将此代码添加到 Main 方法:

var templatePath = "https://" + storageAccountName + ".blob.core.windows.net/templates/CreateVMTemplate.json";
var paramPath = "https://" + storageAccountName + ".blob.core.windows.net/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();

删除资源

由于对 Azure 中使用的资源收费,因此最好删除不再需要的资源。 无需从资源组中单独删除每个资源。 自动删除资源组及其所有资源。

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

azure.ResourceGroups.DeleteByName(groupName);

运行应用程序

此控制台应用程序需要大约五分钟才能完全从头到尾运行。

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

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

后续步骤