将托管标识与 Azure 容器实例配合使用

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

在本文中,你将详细了解容器实例中的托管标识。 此外,还可以:

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

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

为什么使用托管标识?

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

启用托管标识

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

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

使用托管标识

若要使用托管标识,必须授予标识对订阅中一个或多个 Azure 服务资源(例如 Web 应用、密钥保管库或存储帐户)的访问权限。 在正在运行的容器中使用托管标识类似于在 Azure 虚拟机(VM)中使用标识。 有关详细信息,请参阅有关使用 令牌Azure PowerShell 或 Azure CLI 或 AzureSDK 的 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 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 命令将示例机密存储在密钥保管库中:

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

继续学习以下示例,在容器实例中使用用户分配的托管标识或系统分配的托管标识来访问密钥保管库。

示例 1:使用用户分配的标识访问 Azure 密钥保管库

创建标识

首先使用 az identity create 命令在订阅中创建标识。 可以使用用于创建密钥保管库的同一资源组。 也可以使用其他名称。

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 参数将用户分配的托管标识传递到组。 长时间运行命令将使容器保持运行状态。 此示例使用用于创建密钥保管库的同一资源组,但可以指定不同的资源组。

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输出结果中的部分类似于以下示例,表明标识已在容器组中设置。 在principalID下的userAssignedIdentities是您在 Microsoft Entra ID 中创建的标识的服务主体:

[...]
"identity": {
    "principalId": "null",
    "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
    "type": "UserAssigned",
    "userAssignedIdentities": {
      "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/danlep1018/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myACIId": {
        "clientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
        "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222"
      }
    }
  },
[...]

使用用户分配的标识从密钥保管库获取机密

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

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

在容器的 Bash shell 中运行以下命令。 若要获取访问令牌以使用 Microsoft Entra ID 对密钥保管库进行身份验证,请运行以下命令:

client_id="00001111-aaaa-2222-bbbb-3333cccc4444"
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"}

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

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 密钥保管库

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

运行以下 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": "bbbbbbbb-cccc-dddd-2222-333333333333",
    "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
    "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。 首先,在容器中打开 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"

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

若要使用资源管理器模板在容器组中启用托管标识,请通过identity对象设置Microsoft.ContainerInstance/containerGroups对象的ContainerGroupIdentity属性。 下面的代码段演示针对不同方案配置的 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':{}}