使用 Azure 托管标识向 Azure 容器注册表验证身份

使用 Azure 资源的托管标识从另一个 Azure 资源向 Azure 容器注册表验证身份,而无需提供或管理注册表凭据。 例如,在 Linux VM 上设置用户分配或系统分配的托管标识,以便从容器注册表访问容器映像,就像使用公共注册表一样容易。 或者,将 Azure Kubernetes 服务群集设置为使用其托管标识从用于 pod 部署的 Azure 容器注册表拉取容器映像。

本文将详细介绍托管标识以及如何:

  • 在 Azure VM 上启用用户分配或系统分配的标识
  • 授予标识对 Azure 容器注册表的访问权限
  • 使用托管标识访问注册表并拉取容器映像

为了创建 Azure 资源,本文要求运行 Azure CLI 版本 2.0.55 或更高版本。 运行 az --version 即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure CLI

若要设置容器注册表并向其推送容器映像,还必须在本地安装 Docker。 Docker 提供的包可在任何 macOSWindowsLinux 系统上轻松配置 Docker。

为什么使用托管标识?

如果不熟悉 Azure 资源功能的托管标识,请参阅此概述

为所选的 Azure 资源设置托管标识后,便可以根据需要授予该标识对另一资源的访问权限,这一点与所有安全主体一样。 例如,为托管标识分配角色,该角色对 Azure 中的专用注册表具有拉取、推送和拉取或其他权限。 (有关完整的注册表角色列表,请参阅 Azure 容器注册表角色和权限。)可以授予标识对一个或多个资源的访问权限。

然后,使用此标识向任何支持 Microsoft Entra 身份验证的服务进行身份验证,这样就无需在代码中插入任何凭据了。 选择如何使用托管标识进行身份验证,具体取决于你的方案。 若要使用该标识从虚拟机访问 Azure 容器注册表,请向 Azure 资源管理器验证身份。

创建容器注册表

如果还没有 Azure 容器注册表,请创建一个注册表并向其推送示例容器映像。 有关步骤,请参阅快速入门:使用 Azure CLI 创建专用容器注册表

本文假设你在注册表中存储了 aci-helloworld:v1 容器映像。 以下示例使用注册表名称 myContainerRegistry。 请在后续步骤中替换为你自己的注册表和映像名称。

创建一个启用了 Docker 的 VM

创建一个启用了 Docker 的 Ubuntu 虚拟机。 还需要在该虚拟机上安装 Azure CLI。 如果已有 Azure 虚拟机,请跳过此虚拟机创建步骤。

使用 az vm create 部署默认的 Ubuntu Azure 虚拟机。 以下示例在名为 myResourceGroup 的现有资源组中创建名为 myDockerVM 的 VM:

az vm create \
    --resource-group myResourceGroup \
    --name myDockerVM \
    --image Ubuntu2204 \
    --admin-username azureuser \
    --generate-ssh-keys

创建 VM 需要几分钟时间。 等该命令完成后,记下 Azure CLI 显示的 publicIpAddress。 使用此地址与 VM 建立 SSH 连接。

在 VM 上安装 Docker

等 VM 正常运行后,与 VM 建立 SSH 连接。 将 publicIpAddress 替换为 VM 的公共 IP 地址。

ssh azureuser@publicIpAddress

运行以下命令以在 VM 上安装 Docker:

sudo apt update
sudo apt install docker.io -y

安装完成后,运行以下命令验证 Docker 在 VM 上是否正常运行:

sudo docker run -it mcr.microsoft.com/hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
[...]

安装 Azure CLI

按照使用 apt 安装 Azure CLI 中的步骤在 Ubuntu 虚拟机上安装 Azure CLI。 在本文中,请确保安装版本 2.0.55 或更高版本。

退出 SSH 会话。

示例 1:使用用户分配的标识进行访问

创建标识

使用 az identity create 命令在订阅中创建标识。 可以使用先前用于创建容器注册表或虚拟机的相同资源组,也可以使用不同的资源组。

az identity create --resource-group myResourceGroup --name myACRId

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

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

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

当你从虚拟机登录 CLI 时,需要在稍后的步骤中使用标识的 ID,因此请显示以下值:

echo $userID

ID 的格式如下:

/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myACRId

为 VM 配置标识

以下 az vm identity assign 命令可为 Docker VM 配置用户分配的标识:

az vm identity assign --resource-group myResourceGroup --name myDockerVM --identities $userID

授予标识对容器注册表的访问权限

现在将标识配置为访问容器注册表。 首先使用 az acr show 命令获取注册表的资源 ID:

resourceID=$(az acr show --resource-group myResourceGroup --name myContainerRegistry --query id --output tsv)

使用 az role assignment create 命令向标识分配 AcrPull 角色。 此角色将提供对注册表的拉取权限。 若要同时提供拉取和推送权限,请分配 AcrPush 角色。

az role assignment create --assignee $spID --scope $resourceID --role acrpull

使用标识访问注册表

通过 SSH 连接到配置了标识的 Docker 虚拟机。 使用 VM 上安装的 Azure CLI 运行以下 Azure CLI 命令。

首先,使用在 VM 上配置的标识,通过 az login 向 Azure CLI 进行身份验证。 对于 <userID>,请替换成在上一步中检索到的标识 ID。

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

然后,使用 az acr login 向注册表进行身份验证。 使用此命令时,CLI 使用运行 az login 时创建的 Active Directory 令牌,以无缝的方式向容器注册表验证会话的身份。 (根据 VM 的设置,可能需要使用 sudo 运行此命令和 docker 命令。)

az acr login --name myContainerRegistry

你应该会看到 Login succeeded 消息。 之后,便可以在不提供凭据的情况下运行 docker 命令。 例如,运行 docker pull 以拉取 aci-helloworld:v1 映像,并指定注册表的登录服务器名称。 登录服务器名称由容器注册表名称(全部小写)后跟 .azurecr.cn 组成 - 例如,mycontainerregistry.azurecr.cn

docker pull mycontainerregistry.azurecr.cn/aci-helloworld:v1

示例 2:使用系统分配的标识进行访问

为 VM 配置系统托管标识

以下 az vm identity assign 命令可为 Docker VM 配置系统分配的标识:

az vm identity assign --resource-group myResourceGroup --name myDockerVM

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

spID=$(az vm show --resource-group myResourceGroup --name myDockerVM --query identity.principalId --out tsv)

授予标识对容器注册表的访问权限

现在将标识配置为访问容器注册表。 首先使用 az acr show 命令获取注册表的资源 ID:

resourceID=$(az acr show --resource-group myResourceGroup --name myContainerRegistry --query id --output tsv)

使用 az role assignment create 命令向标识分配 AcrPull 角色。 此角色将提供对注册表的拉取权限。 若要同时提供拉取和推送权限,请分配 AcrPush 角色。

az role assignment create --assignee $spID --scope $resourceID --role acrpull

使用标识访问注册表

通过 SSH 连接到配置了标识的 Docker 虚拟机。 使用 VM 上安装的 Azure CLI 运行以下 Azure CLI 命令。

首先,使用 VM 上的系统分配标识通过 az login 向 Azure CLI 进行身份验证。

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

然后,使用 az acr login 向注册表进行身份验证。 使用此命令时,CLI 使用运行 az login 时创建的 Active Directory 令牌,以无缝的方式向容器注册表验证会话的身份。 (根据 VM 的设置,可能需要使用 sudo 运行此命令和 docker 命令。)

az acr login --name myContainerRegistry

你应该会看到 Login succeeded 消息。 之后,便可以在不提供凭据的情况下运行 docker 命令。 例如,运行 docker pull 以拉取 aci-helloworld:v1 映像,并指定注册表的登录服务器名称。 登录服务器名称由容器注册表名称(全部小写)后跟 .azurecr.cn 组成 - 例如,mycontainerregistry.azurecr.cn

docker pull mycontainerregistry.azurecr.cn/aci-helloworld:v1

后续步骤

本文介绍了如何将托管标识与 Azure 容器注册表配合使用,以及如何:

  • 在 Azure VM 中启用用户分配或系统分配的标识
  • 授予标识对 Azure 容器注册表的访问权限
  • 使用托管标识访问注册表并拉取容器映像