如何将托管标识与 Azure 容器实例结合使用

使用 Azure 资源的托管标识在 Azure 容器实例中运行代码以便与其他 Azure 服务交互,而无需在代码中维护任何机密或凭据。 该功能提供了 Azure 容器实例部署,在 Microsoft Entra ID 中有一个自动托管标识。

本文将介绍有关 Azure 容器实例中托管标识的详细信息以及:

  • 在容器组中启用用户分配或系统分配的标识
  • 授予标识对 Azure Key Vault 的访问权限
  • 使用托管标识从正在运行的容器访问 Key Vault

调整示例,以启用并使用 Azure 容器实例中的标识来访问其他 Azure 服务。 这些示例是交互式的。 但实际上,容器映像将运行代码来访问 Azure 服务。

为什么使用托管标识?

在运行的容器中使用托管标识,可对支持 Microsoft Entra 身份验证的任何服务进行身份验证,而无需在容器代码中管理凭据。 对于不支持 AD 身份验证的服务,可以在 Azure Key Vault 中存储机密并使用托管标识来访问 Key Vault 以检索凭据。 有关使用托管标识的详细信息,请参阅什么是 Azure 资源的托管标识?

启用托管标识

创建容器组时,可通过设置 ContainerGroupIdentity 属性来启用一个或多个托管标识。 还可以在容器组运行后启用或更新托管标识;任何一个操作都会导致容器组重启。 若要在新容器组或现有容器组上设置标识,请使用 Azure CLI、资源管理器模板、YAML 文件或其他 Azure 工具。

Azure 容器实例支持以下两种类型的 Azure 托管标识:用户分配和系统分配。 在容器组中,可以启用系统分配的标识、一个或多个用户分配的标识或这两种类型的标识。 如果不熟悉 Azure 资源的托管标识,请参阅概述

使用托管标识

若要使用托管标识,必须授予标识对订阅中一个或多个 Azure 服务资源(例如 Web 应用、密钥保管库或存储帐户)的访问权限。 在正在运行的容器中使用托管标识与在 Azure 虚拟机 (VM) 中使用标识相似。 请参阅有关使用令牌Azure PowerShell 或 Azure CLIAzure SDK 的 VM 指南。

先决条件

  • 如需在本地运行 CLI 参考命令,请安装 Azure CLI。 如果在 Windows 或 macOS 上运行,请考虑在 Docker 容器中运行 Azure CLI。 有关详细信息,请参阅如何在 Docker 容器中运行 Azure CLI

    • 如果使用的是本地安装,请使用 az login 命令登录到 Azure CLI。 若要完成身份验证过程,请遵循终端中显示的步骤。 有关其他登录选项,请参阅使用 Azure CLI 登录

    • 出现提示时,请在首次使用时安装 Azure CLI 扩展。 有关扩展详细信息,请参阅使用 Azure CLI 的扩展

    • 运行 az version 以查找安装的版本和依赖库。 若要升级到最新版本,请运行 az upgrade

  • 本文要求使用 2.0.49 版或更高版本的 Azure CLI。

    注意

    在可以在由世纪互联运营的 Microsoft Azure 中使用 Azure CLI 之前,请先运行 az cloud set -n AzureChinaCloud 来更改云环境。 若要切换回 Azure 公有云,请再次运行 az cloud set -n AzureCloud

创建 Azure Key Vault

本文中示例使用 Azure 容器实例中的托管标识来访问 Azure Key Vault 机密。

首先,使用以下 az group create 命令在 chinaeast2 位置中创建一个名为“myResourceGroup”的资源组:

az group create --name myResourceGroup --location chinaeast2

使用 az keyvault create 命令创建 Key Vault。 请务必指定唯一的 Key Vault 名称。

az keyvault create \
  --name mykeyvault \
  --resource-group myResourceGroup \
  --location chinaeast2

使用 az keyvault secret set 命令在 Key Vault 中存储实例机密:

az keyvault secret set \
  --name SampleSecret \
  --value "Hello Container Instances" \
  --description ACIsecret --vault-name mykeyvault

继续下面的示例,使用 Azure 容器实例中用户分配或系统分配的托管标识访问 Key Vault。

示例 1:使用用户分配的标识访问 Azure Key Vault

创建标识

首先使用 az identity create 命令在订阅中创建标识。 可以使用用于创建 Key Vault 的相同资源组,也可以使用不同的资源组。

az identity create \
  --resource-group myResourceGroup \
  --name myACIId

若要在以下步骤中使用标识,请使用 az identity show 命令在变量中存储标识的服务主体 ID 和资源 ID。

# Get service principal ID of the user-assigned identity
SP_ID=$(az identity show \
  --resource-group myResourceGroup \
  --name myACIId \
  --query principalId --output tsv)

# Get resource ID of the user-assigned identity
RESOURCE_ID=$(az identity show \
  --resource-group myResourceGroup \
  --name myACIId \
  --query id --output tsv)

授予用户分配的标识对 Key Vault 的访问权限

运行以下 az keyvault set-policy 命令来设置对 Key Vault 的访问策略。 以下示例允许用户分配的标识从 Key Vault 中获取机密:

 az keyvault set-policy \
    --name mykeyvault \
    --resource-group myResourceGroup \
    --object-id $SP_ID \
    --secret-permissions get

在容器组中启用用户分配的标识

运行以下 az container create 命令基于 Azure 的 azure-cli 映像创建容器实例。 此示例提供了单一容器组,可用于以交互方式运行 Azure CLI 以访问其他 Azure 服务。 在本部分中,只使用基本操作系统。 有关在容器中使用 Azure CLI 的示例,请参阅在容器组中启用系统分配的标识

--assign-identity 参数将用户分配的托管标识传递到组。 长时间运行命令将使容器保持运行状态。 此示例使用用于创建 Key Vault 的相同资源组,但可以指定不同的资源组。

az container create \
  --resource-group myResourceGroup \
  --name mycontainer \
  --image mcr.microsoft.com/azure-cli \
  --assign-identity $RESOURCE_ID \
  --command-line "tail -f /dev/null"

在几秒钟内,你应当会从 Azure CLI 收到响应,它指出部署已完成。 使用 az container show 命令检查它的状态。

az container show \
  --resource-group myResourceGroup \
  --name mycontainer

输出的 identity 部分类似于以下内容,显示在容器组中设置的标识。 userAssignedIdentities 下的 principalID 是在 Microsoft Entra ID 中创建的标识的服务主体:

[...]
"identity": {
    "principalId": "null",
    "tenantId": "xxxxxxxx-f292-4e60-9122-xxxxxxxxxxxx",
    "type": "UserAssigned",
    "userAssignedIdentities": {
      "/subscriptions/xxxxxxxx-0903-4b79-a55a-xxxxxxxxxxxx/resourcegroups/danlep1018/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myACIId": {
        "clientId": "xxxxxxxx-5523-45fc-9f49-xxxxxxxxxxxx",
        "principalId": "xxxxxxxx-f25b-4895-b828-xxxxxxxxxxxx"
      }
    }
  },
[...]

使用用户分配的标识从 Key Vault 中获取机密

现在可以使用正在运行的容器实例中的托管标识来访问 Key Vault。 首先在容器中启动 bash shell:

az container exec \
  --resource-group myResourceGroup \
  --name mycontainer \
  --exec-command "/bin/bash"

在容器的 bash shell 中运行以下命令。 若要获取访问令牌来使用 Microsoft Entra ID 向 Key Vault 进行身份验证,请运行以下命令:

client_id="xxxxxxxx-5523-45fc-9f49-xxxxxxxxxxxx"
curl "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fvault.azure.cn&client_id=$client_id" -H Metadata:true -s

输出:

{"access_token":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSIsImtpZCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSJ9......xxxxxxxxxxxxxxxxx","refresh_token":"","expires_in":"28799","expires_on":"1539927532","not_before":"1539898432","resource":"https://vault.azure.cn/","token_type":"Bearer"}

对于 Windows 容器,元数据服务器 (169.254.169.254) 不可用。 运行以下命令或等效命令来获取访问令牌。

curl -G -v %IDENTITY_ENDPOINT% --data-urlencode resource=https://vault.azure.cn --data-urlencode principalId=<principal id> -H secret:%IDENTITY_HEADER%

若要在变量中存储访问令牌以便在后续命令中进行身份验证,运行以下命令:

TOKEN=$(curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fvault.azure.cn' -H Metadata:true | jq -r '.access_token')

现在使用访问令牌对密钥保管库进行身份验证并读取机密。 请务必替换 URL 中 Key Vault 的名称 (https://mykeyvault.vault.azure.cn/...):

curl https://mykeyvault.vault.azure.cn/secrets/SampleSecret/?api-version=7.4 -H "Authorization: Bearer $TOKEN"

响应类似于以下内容,其中显示机密。 在代码中,将分析此输出,以便获取机密。 然后,在后续操作中使用机密来访问另一个 Azure 资源。

{"value":"Hello Container Instances","contentType":"ACIsecret","id":"https://mykeyvault.vault.azure.cn/secrets/SampleSecret/xxxxxxxxxxxxxxxxxxxx","attributes":{"enabled":true,"created":1539965967,"updated":1539965967,"recoveryLevel":"Purgeable"},"tags":{"file-encoding":"utf-8"}}

示例 2:使用系统分配的标识访问 Azure Key Vault

在容器组中启用系统分配的标识

运行以下 az container create 命令基于 Azure 的 azure-cli 映像创建容器实例。 此示例提供了单一容器组,可用于以交互方式运行 Azure CLI 以访问其他 Azure 服务。

没有任何附加值的 --assign-identity 参数在组上启用系统分配的托管标识。 标识的范围限定为容器组的资源组。 长时间运行命令将使容器保持运行状态。 此示例使用用于创建密钥保管库的相同资源组,该资源组在此标识的范围内。

# Get the resource ID of the resource group
RG_ID=$(az group show --name myResourceGroup --query id --output tsv)

# Create container group with system-managed identity
az container create \
  --resource-group myResourceGroup \
  --name mycontainer \
  --image mcr.microsoft.com/azure-cli \
  --assign-identity --scope $RG_ID \
  --command-line "tail -f /dev/null"

在几秒钟内,你应当会从 Azure CLI 收到响应,它指出部署已完成。 使用 az container show 命令检查它的状态。

az container show \
  --resource-group myResourceGroup \
  --name mycontainer

输出中的 identity 部分如下所示,其中显示系统分配的标识是在 Microsoft Entra ID 中创建的:

[...]
"identity": {
    "principalId": "xxxxxxxx-528d-7083-b74c-xxxxxxxxxxxx",
    "tenantId": "xxxxxxxx-f292-4e60-9122-xxxxxxxxxxxx",
    "type": "SystemAssigned",
    "userAssignedIdentities": null
},
[...]

将变量设置为标识的值 principalId(服务主体 ID),以便在后续步骤中使用。

SP_ID=$(az container show \
  --resource-group myResourceGroup \
  --name mycontainer \
  --query identity.principalId --out tsv)

授予容器组对 Key Vault 的访问权限

运行以下 az keyvault set-policy 命令来设置对 Key Vault 的访问策略。 以下示例允许系统托管标识从 Key Vault 中获取机密:

 az keyvault set-policy \
   --name mykeyvault \
   --resource-group myResourceGroup \
   --object-id $SP_ID \
   --secret-permissions get

使用容器组标识从 Key Vault 中获取机密

现在可以使用托管标识来访问正在运行的容器实例中的 Key Vault。 首先在容器中启动 bash shell:

az container exec \
  --resource-group myResourceGroup \
  --name mycontainer \
  --exec-command "/bin/bash"

在容器的 bash shell 中运行以下命令。 首先使用托管标识登录到 Azure CLI:

az cloud set -n AzureChinaCloud
az login --identity
# az cloud set -n AzureCloud   //means return to Public Azure.

从正在运行的容器中检索 Key Vault 中的机密:

az keyvault secret show \
  --name SampleSecret \
  --vault-name mykeyvault --query value

此时会检索机密值:

"Hello Container Instances"

对于 Windows 容器,“az login”命令将不起作用,因为元数据服务器不可用。 此外,无法在 Windows 虚拟网络容器中生成托管标识令牌。

使用资源管理器模板启用托管标识

若要使用资源管理器模板在容器组中启用托管标识,请使用 ContainerGroupIdentity 对象设置 Microsoft.ContainerInstance/containerGroups 对象的 identity 属性。 下面的代码段演示针对不同方案配置的 identity 属性。 请参阅资源管理器模板引用。 指定最小的 apiVersion,即 2018-10-01

用户分配的标识

用户分配的标识是窗体的资源 ID:

"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}"

可以启用一个或多个用户分配的标识。

"identity": {
    "type": "UserAssigned",
    "userAssignedIdentities": {
        "myResourceID1": {
            }
        }
    }

系统分配的标识

"identity": {
    "type": "SystemAssigned"
    }

系统和用户分配的标识

在容器组中,可以同时启用系统分配的标识和一个或多个用户分配的标识。

"identity": {
    "type": "SystemAssigned, UserAssigned",
    "userAssignedIdentities": {
        "myResourceID1": {
            }
        }
    }
...

使用 YAML 文件启用托管标识

若要在使用 YAML 文件部署的容器组中启用托管标识,请包含以下 YAML。 指定最小的 apiVersion,即 2018-10-01

用户分配的标识

用户分配的标识是窗体的资源 ID

'/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}'

可以启用一个或多个用户分配的标识。

identity:
  type: UserAssigned
  userAssignedIdentities:
    {'myResourceID1':{}}

系统分配的标识

identity:
  type: SystemAssigned

系统和用户分配的标识

在容器组中,可以同时启用系统分配的标识和一个或多个用户分配的标识。

identity:
  type: SystemAssigned, UserAssigned
  userAssignedIdentities:
   {'myResourceID1':{}}

后续步骤

本文将介绍有关 Azure 容器实例中托管标识的信息以及如何:

  • 在容器组中启用用户分配或系统分配的标识
  • 授予标识对 Azure Key Vault 的访问权限
  • 使用托管标识从正在运行的容器访问 Key Vault