使用适用于 .NET 的 Azure SDK 进行资源管理

用于 .NET 管理平面库的 Azure SDK 将帮助你从 .NET 应用程序中创建、预配和管理 Azure 资源。 所有 Azure 服务都有相应的管理库。

使用管理库(从 Azure.ResourceManager开始的命名空间(例如 Azure.ResourceManager.Compute),可以编写配置和部署程序以执行通过 Azure 门户、Azure CLI 或其他资源管理工具执行的相同任务。

这些包遵循 新的 Azure SDK 指南,这些指南提供 核心功能,这些功能在所有 Azure SDK 之间共享,包括:

  • 直观的 Azure 标识库。
  • 具有自定义策略的 HTTP 管道。
  • 错误处理。
  • 分布式跟踪。

注意

你可能会注意到某些包仍处于预发行版版本。 正在逐步发布其他 Azure 服务的管理平面库。 如果要查找特定 Azure 资源的稳定版本包,并且当前只有预发行版本可用,请在 Azure SDK for .NET GitHub 存储库中提出问题。

入门

先决条件

请安装该软件包

安装适用于 .NET 的 Azure 标识和 Azure 资源管理 NuGet 包。 例如:

Install-Package Azure.Identity
Install-Package Azure.ResourceManager
Install-Package Azure.ResourceManager.Resources
Install-Package Azure.ResourceManager.Compute
Install-Package Azure.ResourceManager.Network

对客户端进行身份验证

创建经过身份验证的客户端的默认选项是使用 DefaultAzureCredential。 由于所有管理 API 都通过同一终结点,因此只需创建一个顶级 ArmClient 即可与资源交互。

若要使用 Azure 进行身份验证并创建一个 ArmClient,请实例化 ArmClient 给定凭据:

using Azure.Identity;
using Azure.ResourceManager;
using System;
using System.Threading.Tasks;

// Code omitted for brevity

ArmClient client = new ArmClient(new DefaultAzureCredential());

有关 Azure.Identity.DefaultAzureCredential 类的详细信息,请参阅 DefaultAzureCredential 类

管理 SDK 速查表

若要开始使用适用于 .NET 的 Azure 管理 SDK,假设有一个创建/列出/更新/删除典型 Azure 服务总线命名空间的任务,请执行以下步骤:

  1. 对要使用的订阅和资源组进行身份验证。
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.ServiceBus;

ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = client.GetDefaultSubscription();
ResourceGroupResource resourceGroup =
    client.GetDefaultSubscription().GetResourceGroup(resourceGroupName);
  1. 找到用于管理 Azure 资源的相应方法。
操作 方法
获取具有资源标识符的资源 client.GetServiceBusQueueResource(ResourceIdentifier resourceIdentifier)
列出 resourceGroup.GetServiceBusNamespaces()
指数 resourceGroup.GetServiceBusNamespace(string servicebusNamespaceName)
添加/更新 resourceGroup.GetServiceBusNamespaces().CreateOrUpdate(Azure.WaitUntil waitUntil, string name, ServiceBusNamespaceData data)
Contains resourceGroup.GetServiceBusNamespaces().Exists(string servicebusNamespaceName)
删除 client.GetServiceBusQueueResource(ResourceIdentifior resourceIdentifior).Delete()resourceGroup.GetServiceBusNamespace(string servicebusNamespaceName).Delete()

请记住,所有 Azure 资源(包括资源组本身)都可以使用类似于上述示例的代码由相应的管理 SDK 管理。 若要查找正确的 Azure 管理 SDK 包,请查找具有以下模式的包 Azure.ResourceManager.{ResourceProviderName}

若要详细了解 ResourceIdentifier,请参阅 结构化资源标识符

关键概念

了解 Azure 资源层次结构

为了减少执行常见任务所需的客户端数以及每个客户端采用的冗余参数数,我们在 SDK 中引入了一个对象层次结构,用于模拟 Azure 中的对象层次结构。 SDK 中的每个资源客户端都有访问其子项的资源客户端的方法,这些客户端的范围已经限定为适当的订阅和资源组。

为此,我们将介绍 Azure 中所有资源的三种标准类型:

{ResourceName}Resource

此类型表示一个完整的资源客户端对象,该对象包含一个 数据 属性,该属性将详细信息公开为 {ResourceName}Data 类型。 它还有权访问该资源上的所有操作,而无需传入范围参数,例如订阅 ID 或资源名称。 这样就可以轻松地直接对列表调用的结果执行操作,因为所有内容现在都作为完整的资源客户端返回。

ArmClient client = new ArmClient(new DefaultAzureCredential());
string resourceGroupName = "myResourceGroup";
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceGroupName);
await foreach (VirtualMachineResource virtualMachine in resourceGroup.GetVirtualMachinesAsync())
{
    //previously we would have to take the resourceGroupName and the vmName from the vm object
    //and pass those into the powerOff method as well as we would need to execute that on a separate compute client
    await virtualMachine.PowerOffAsync(WaitUntil.Completed);
}

{ResourceName}Data

此类型表示构成给定资源的模型。 通常,这是来自服务调用(如 HTTP GET)的响应数据,并提供有关基础资源的详细信息。 以前,这是由 Model 类表示的。

{ResourceName}Collection

此类型表示可以对属于特定父资源的资源集合执行的操作。 此对象提供大多数逻辑集合操作。

集合行为 集合方法
Iterate/List GetAll()
指数 Get(string name)
添加 CreateOrUpdate(Azure.WaitUntil waitUntil, string name, {ResourceName}Data data)
Contains Exists(string name)

在大多数情况下,资源的父级 ResourceGroup,但在某些情况下,资源本身具有子资源,例如 子网VirtualNetwork的子级。 ResourceGroup 本身是订阅的子级

汇总

假设公司要求所有虚拟机都添加有所有者标记。 我们负责编写一个程序,以便将标记添加到给定资源组中缺少的任何虚拟机。

// First we construct our armClient
ArmClient client = new ArmClient(new DefaultAzureCredential());

// Next we get a resource group object
// ResourceGroup is a {ResourceName}Resource object from above
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
ResourceGroupResource resourceGroup =
   await subscription.GetResourceGroupAsync("myRgName");

// Next we get the collection for the virtual machines
// vmCollection is a {ResourceName}Collection object from above
VirtualMachineCollection virtualMachineCollection = await resourceGroup.GetVirtualMachines();

// Next we loop over all vms in the collection
// Each vm is a {ResourceName}Resource object from above
await foreach(VirtualMachineResource virtualMachine in virtualMachineCollection)
{
   // We access the {ResourceName}Data properties from vm.Data
   if(!virtualMachine.Data.Tags.ContainsKey("owner"))
   {
       // We can also access all operations from vm since it is already scoped for us
       await virtualMachine.AddTagAsync("owner", GetOwner());
   }
}

结构化资源标识符

资源 ID 包含有关资源本身的有用信息,但它们是必须分析的纯字符串。 与其实现自己的解析逻辑,您可以使用 ResourceIdentifier 对象来为您解析。

示例:使用 ResourceIdentifier 对象分析 ID

string resourceId = "/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/workshop2021-rg/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/mySubnet";
ResourceIdentifier id = new ResourceIdentifier(resourceId);
Console.WriteLine($"Subscription: {id.SubscriptionId}");
Console.WriteLine($"ResourceGroup: {id.ResourceGroupName}");
Console.WriteLine($"Vnet: {id.Parent.Name}");
Console.WriteLine($"Subnet: {id.Name}");

但是,请记住,其中一些属性可以为 null。 通常可以通过 ID 字符串本身来判断资源 ID 的类型。 但是,如果不确定,请检查属性是否为 null。

示例:资源标识符生成器

你可能不想从纯 string 手动创建 resourceId。 每个 {ResourceName}Resource 类都有一个静态方法,可帮助创建资源标识符字符串。

ResourceIdentifier resourceId =
    AvailabilitySetResource.CreateResourceIdentifier(
        "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
        "resourceGroupName",
        "resourceName");

管理现有资源

使用管理客户端库时,对已存在的资源执行操作是一种常见用例。 在这种情况下,您通常会以字符串形式拥有要处理的资源标识符。 尽管新对象层次结构非常适合在给定父级范围内进行预配和工作,但在涉及到此特定方案时,它并不是最有效的。

下面是一个示例:如何访问 AvailabilitySetResource 对象并直接使用其资源标识符对其进行管理:

using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.Resources;
using Azure.ResourceManager.Compute;
using System;
using System.Threading.Tasks;

// Code omitted for brevity

ResourceIdentifier subscriptionId =
    SubscriptionResource.CreateResourceIdentifier("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");

ResourceIdentifier resourceId =
    AvailabilitySetResource.CreateResourceIdentifier(
        subscriptionId.SubscriptionId,
        "resourceGroupName",
        "resourceName");

// We construct a new armClient to work with
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Next we get the specific subscription this resource belongs to
SubscriptionResource subscription = client.GetSubscriptionResource(subscriptionId);
// Next we get the specific resource group this resource belongs to
ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceId.ResourceGroupName);
// Finally we get the resource itself
// Note: for this last step in this example, Azure.ResourceManager.Compute is needed
AvailabilitySetResource availabilitySet = await resourceGroup.GetAvailabilitySetAsync(resourceId.Name);

此方法要求对 Azure 进行大量代码和三次 API 调用。 使用我们在客户端本身上提供的扩展方法可以减少代码,而无需调用任何 API 调用。 利用这些扩展方法,可以传入资源标识符并检索限定范围的资源客户端。 返回的对象是 {ResourceName}Resource。 由于尚未联系 Azure 检索数据,因此调用 Data 属性将引发异常,因此可以使用 HasData 属性来判断资源实例是否包含数据或调用资源上的 GetGetAsync 方法来检索资源数据。

因此,前面的示例最终将如下所示:

ResourceIdentifier resourceId =
    AvailabilitySetResource.CreateResourceIdentifier(
        "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
        "resourceGroupName",
        "resourceName");
// We construct a new armClient to work with
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Next we get the AvailabilitySet resource client from the armClient
// The method takes in a ResourceIdentifier but we can use the implicit cast from string
AvailabilitySetResource availabilitySet = client.GetAvailabilitySetResource(resourceId);
// At this point availabilitySet.Data will be null and trying to access it will throw exception
// If we want to retrieve the objects data we can simply call get
availabilitySet = await availabilitySet.GetAsync();
// we now have the data representing the availabilitySet
Console.WriteLine(availabilitySet.Data.Name);

检查资源是否存在

如果不确定要获取的资源是否存在,或者只想检查资源是否存在,则可以使用可从任何 {ResourceName}Collection 类调用 Exists()ExistsAsync() 方法。

Exists() 返回 Response<bool>,而 ExistsAsync() 作为其异步版本返回 Task<Response<bool>>。 在 Response<bool> 对象中,可以访问其 Value 属性来检查资源是否存在。 如果资源不存在,则Valuefalse,反过来也是如此。

在以前版本的包中,必须捕获 RequestFailedException 并检查 404 状态代码。 通过这个新的 API,我们希望这样可以提高开发人员的工作效率并优化资源访问。

ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
string resourceGroupName = "myRgName";

try
{
    ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceGroupName);
    // At this point, we are sure that myRG is a not null Resource Group, so we can use this object to perform any operations we want.
}
catch (RequestFailedException ex) when (ex.Status == 404)
{
    Console.WriteLine($"Resource Group {resourceGroupName} does not exist.");
}

现在,通过这些便捷方法,我们只需执行以下操作。

ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
string resourceGroupName = "myRgName";

bool exists = await subscription.GetResourceGroups().ExistsAsync(resourceGroupName).Value;

if (exists)
{
    Console.WriteLine($"Resource Group {resourceGroupName} exists.");

    // We can get the resource group now that we know it exists.
    // This does introduce a small race condition where resource group could have been deleted between the check and the get.
    ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceGroupName);
}
else
{
    Console.WriteLine($"Resource Group {rgName} does not exist.");
}

例子

创建资源组

// First, initialize the ArmClient and get the default subscription
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Now we get a ResourceGroup collection for that subscription
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
ResourceGroupCollection resourceGroupCollection = subscription.GetResourceGroups();

// With the collection, we can create a new resource group with an specific name
string resourceGroupName = "myRgName";
AzureLocation location = AzureLocation.WestUS2;
ResourceGroupData resourceGroupData = new ResourceGroupData(location);
ResourceGroupResource resourceGroup = (await resourceGroupCollection.CreateOrUpdateAsync(resourceGroupName, resourceGroupData)).Value;

列出所有资源组

// First, initialize the ArmClient and get the default subscription
ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
// Now we get a ResourceGroup collection for that subscription
ResourceGroupCollection resourceGroupCollection = subscription.GetResourceGroups();
// With GetAllAsync(), we can get a list of the resources in the collection
await foreach (ResourceGroupResource resourceGroup in resourceGroupCollection)
{
    Console.WriteLine(resourceGroup.Data.Name);
}

更新资源组

// Note: Resource group named 'myRgName' should exist for this example to work.
ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
string resourceGroupName = "myRgName";
ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceGroupName);
resourceGroup = await resourceGroup.AddTagAsync("key", "value");

删除资源组

ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
string resourceGroupName = "myRgName";
ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceGroupName);
await resourceGroup.DeleteAsync();

有关更详细的示例,请查看我们提供的 示例

故障 排除

后续步骤

更多示例代码

其他文档

如果要从旧 SDK 迁移到此预览版,请查看此 迁移指南

有关 Azure SDK 的详细信息,请参阅 Azure SDK 版本