使用托管标识拉取 Azure 容器应用映像

可以使用托管标识进行身份验证,从 Azure 容器注册表中的专用存储库拉取映像,这样就可以避免使用管理凭据。

可以使用用户分配或系统分配的托管标识向 Azure 容器注册表进行身份验证。

  • 使用用户分配的托管标识时,可以在 Azure 容器应用外部创建和管理该标识。 可将它分配到多个 Azure 资源,包括 Azure 容器应用。
  • 使用系统分配的托管标识时,该标识由 Azure 容器应用创建和管理。 该标识与容器应用相关联,删除该应用时也会删除它。
  • 如果可能,应使用用户分配的托管标识来拉取映像。

每当启动容器时,容器应用都会检查是否有新版本的映像。 在 Docker 或 Kubernetes 术语中,容器应用将每个容器的映像拉取策略设置为 always

本文介绍如何使用 Azure 门户将容器应用配置为使用用户分配和系统分配的托管标识从专用 Azure 容器注册表存储库拉取映像。

用户分配的托管标识

以下步骤描述将容器应用配置为使用用户分配的托管标识从专用 Azure 容器注册表存储库拉取映像的过程。

  1. 使用公共映像创建容器应用。
  2. 将用户分配的托管标识添加到该容器应用。
  3. 使用专用映像和用户分配的托管标识创建容器应用修订版。

先决条件

  • 具有活动订阅的 Azure 帐户。

  • 包含你要拉取的映像的专用 Azure 容器注册表。

  • Azure 容器注册表必须允许使用 ARM 受众令牌进行身份验证,才能使用托管标识来拉取映像。 请使用以下命令来检查是否允许使用 ARM 令牌访问 ACR:

    az acr config authentication-as-arm show -r <REGISTRY>
    

    如果不允许使用 ARM 令牌,可以使用以下命令允许它们:

    az acr config authentication-as-arm update -r <REGISTRY> --status enabled
    
  • 创建用户分配的托管标识。 有关详细信息,请参阅创建用户分配的托管标识

创建容器应用

执行以下步骤,使用默认快速入门映像创建容器应用。

  1. 导航到门户“主页”。

  2. 在顶部搜索栏中搜索“容器应用”。

  3. 在搜索结果中选择“容器应用”。

  4. 选择“创建”按钮。

  5. 在“基本”选项卡中执行以下操作。

    设置 操作
    订阅 选择 Azure 订阅。
    资源组 选择现有资源组,或创建一个新组。
    容器应用名称 输入容器应用的名称。
    位置 选择一个位置。
    创建容器应用环境 创建新环境或选择现有环境。
  6. 选择“创建容器应用”页面底部的“查看 + 创建”按钮。

  7. 选择“创建容器应用”窗口底部的“创建”按钮。

等待几分钟让容器应用部署完成。 部署完成后,选择“转到资源”。

添加用户分配的托管标识

  1. 在左侧菜单中选择“标识”。
  2. 选择“用户分配”选项卡。
  3. 选择“添加用户分配的托管标识”按钮。
  4. 选择订阅。
  5. 选择你创建的标识。
  6. 选择 添加

创建容器应用修订版

使用专用映像和系统分配的托管标识创建容器应用修订版。

  1. 在左侧菜单中选择“修订版管理”。

  2. 选择“创建新修订版”。

  3. 在“容器映像”表中选择容器映像。

  4. 在“编辑容器”对话框中输入信息。

    字段 操作
    名称 输入容器的名称。
    映像源 选择“Azure 容器注册表”。
    身份验证 选择“托管标识”。
    标识 在下拉菜单中选择你创建的标识。
    注册表 在下拉菜单中选择要使用的注册表。
    图像 输入要使用的映像名称。
    映像标记 输入要拉取的映像的名称和标记。

    “编辑容器”对话框的屏幕截图,可在该对话框中输入用户分配的托管标识。

    注意

    如果未在 Azure 容器注册表上启用管理凭据,你将看到一条警告消息,并需要手动输入映像名称和标记信息。

  5. 选择“保存”。

  6. 在“创建并部署新修订版”页中选择“创建”。

将创建并部署一个新修订版。 门户会自动尝试将 acrpull 角色添加到用户分配的托管标识。 如果未添加该角色,你可以手动添加。

可以通过在容器应用页面的“标识”窗格中检查标识来验证是否已添加角色。

  1. 在左侧菜单中选择“标识”。
  2. 选择“用户分配”选项卡。
  3. 选择用户分配的托管标识。
  4. 从托管标识资源页上的菜单中选择“Azure 角色分配”。
  5. 验证 acrpull 角色是否已分配给用户分配的托管标识。

使用专用映像创建容器应用

如果不想一开始就使用公共映像创建容器应用,还可执行以下操作。

  1. 创建用户分配的托管标识。
  2. acrpull 角色添加到用户分配的托管标识。
  3. 使用专用映像和用户分配的托管标识创建容器应用。

此方法在基础结构即代码 (IaC) 方案中是典型的。

清理资源

如果不打算继续使用此应用程序,可以通过删除资源组来删除 Azure 容器应用实例和所有关联的服务。

警告

删除资源组时,将一并删除该组中的所有资源。 如果该组中有其他资源,也会一并删除这些资源。 如果你想要保留资源,可以删除容器应用实例和容器应用环境。

  1. 在“概述”部分选择你的资源组。
  2. 选择资源组“概述”顶部的“删除资源组”按钮。
  3. 在确认对话框中输入该资源组的名称。
  4. 选择“删除”。 删除资源组的过程可能需要几分钟才能完成。

系统分配的托管标识

在 Azure 门户中配置系统分配的托管标识的方法与配置用户分配的托管标识相同。 唯一的差别在于,不需要创建用户分配的托管标识。 当你创建容器应用时,会创建系统分配的托管标识。

在 Azure 门户中配置系统分配的托管标识的方法是:

  1. 使用公共映像创建容器应用。
  2. 使用专用映像和系统分配的托管标识创建容器应用修订版。

先决条件

创建容器应用

执行以下步骤,使用默认快速入门映像创建容器应用。

  1. 导航到门户“主页”。

  2. 在顶部搜索栏中搜索“容器应用”。

  3. 在搜索结果中选择“容器应用”。

  4. 选择“创建”按钮。

  5. 在“基本”选项卡中执行以下操作。

    设置 操作
    订阅 选择 Azure 订阅。
    资源组 选择现有资源组,或创建一个新组。
    容器应用名称 输入容器应用的名称。
    位置 选择一个位置。
    创建容器应用环境 创建新环境或选择现有环境。
  6. 选择“创建容器应用”页面底部的“查看 + 创建”按钮。

  7. 选择“创建容器应用”页面底部的“创建”按钮。

等待几分钟让容器应用部署完成。 部署完成后,选择“转到资源”。

编辑并部署修订版

编辑容器以使用专用 Azure 容器注册表中的映像,并将身份验证配置为使用系统分配的标识。

  1. 在左侧菜单中选择“容器”。

  2. 选择“编辑并部署”。

  3. 从列表中选择“simple-hello-world-container”容器。

    设置 操作
    名称 输入容器应用名称。
    映像源 选择“Azure 容器注册表”。
    身份验证 选择“托管标识” 。
    标识 选择“系统分配”。
    注册表 输入注册表名称。
    图像 输入映像名称。
    映像标记 输入标记。

    “编辑容器”的屏幕截图,其中显示了系统分配的托管标识。

    注意

    如果未在 Azure 容器注册表上启用管理凭据,你将看到一条警告消息,并需要手动输入映像名称和标记信息。

  4. 选择页面底部的“保存” 。

  5. 选择“创建并部署新修订版”页面底部的“创建”

  6. 几分钟后,在“修订版管理”页上选择“刷新”以查看新修订版。

将创建并部署一个新修订版。 门户会自动尝试将 acrpull 角色添加到系统分配的托管标识。 如果未添加该角色,你可以手动添加。

可以通过在容器应用页面的“标识”窗格中检查标识来验证是否已添加角色。

  1. 在左侧菜单中选择“标识”。
  2. 选择“系统分配”选项卡。
  3. 选择“Azure 角色分配”。
  4. 验证 acrpull 角色是否已分配给系统分配的托管标识。

清理资源

如果不打算继续使用此应用程序,可以通过删除资源组来删除 Azure 容器应用实例和所有关联的服务。

警告

删除资源组时,将一并删除该组中的所有资源。 如果该组中有其他资源,也会一并删除这些资源。 如果你想要保留资源,可以删除容器应用实例和容器应用环境。

  1. 在“概述”部分选择你的资源组。
  2. 选择资源组“概述”顶部的“删除资源组”按钮。
  3. 在确认对话框中输入该资源组的名称。
  4. 选择“删除”。 删除资源组的过程可能需要几分钟才能完成。

本文将介绍如何使用 Azure CLI 和 Azure PowerShell 将容器应用配置为使用托管标识从专用 Azure 容器注册表存储库中拉取映像。

先决条件

必备项 说明
Azure 帐户 具有活动订阅的 Azure 帐户。 如果没有订阅,可以创建一个试用版订阅
Azure CLI 如果要使用 Azure CLI,请在本地计算机上安装 Azure CLI
Azure PowerShell 如果要使用 PowerShell,请在本地计算机上安装 Azure PowerShell。 运行命令 Install-Module -Name Az.App,确保安装最新版本的 Az.App 模块。
Azure 容器注册表 包含你要拉取的映像的专用 Azure 容器注册表。 快速入门:使用 Azure CLI 创建专用容器注册表快速入门:使用 Azure PowerShell 创建专用容器注册表

安装

若要从 CLI 登录到 Azure,请运行以下命令,然后按照提示完成身份验证过程。

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

为了确保运行最新版本的 CLI,请运行升级命令。

az upgrade

接下来,安装或更新适用于 CLI 的 Azure 容器应用扩展。

如果在 Azure CLI 中运行 az containerapp 命令,或在 Azure PowerShell 中运行 Az.App 模块中的 cmdlet 时收到有关缺少参数的错误,请确保已安装最新版本的 Azure 容器应用扩展。

az extension add --name containerapp --upgrade

注意

从 2024 年 5 月开始,Azure CLI 扩展不再默认启用预览功能。 要访问容器应用预览功能,请使用 --allow-preview true 安装容器应用扩展。

az extension add --name containerapp --upgrade --allow-preview true

现在已安装当前扩展或模块,接下来请注册 Microsoft.AppMicrosoft.OperationalInsights 命名空间。

注意

Azure 容器应用资源已从 Microsoft.Web 命名空间迁移到 Microsoft.App 命名空间。 如需更多详细信息,请参阅 2022 年 3 月的从 Azure.Web 到 Microsoft.App 的命名空间迁移

az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights

接下来,设置以下环境变量。 将括在 <> 中的占位符替换为你的值。

RESOURCE_GROUP="<YOUR_RESOURCE_GROUP_NAME>"
LOCATION="<YOUR_LOCATION>"
CONTAINERAPPS_ENVIRONMENT="<YOUR_ENVIRONMENT_NAME>"
REGISTRY_NAME="<YOUR_REGISTRY_NAME>"
CONTAINERAPP_NAME="<YOUR_CONTAINERAPP_NAME>"
IMAGE_NAME="<YOUR_IMAGE_NAME>"

如果你已有资源组,请跳过此步骤。 否则请创建一个资源组。

az group create \
  --name $RESOURCE_GROUP \
  --location $LOCATION

创建容器应用环境

如果没有环境,请运行以下命令:

若要创建环境,请运行以下命令:

az containerapp env create \
  --name $CONTAINERAPPS_ENVIRONMENT \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION

转到下一部分以配置用户分配的托管标识,或跳到系统分配的托管标识部分。

用户分配的托管标识

按照以下过程配置用户分配的托管标识:

  1. 创建用户分配的托管标识。
  2. 如果使用的是 PowerShell,请将注册表的 acrpull 角色分配到托管标识。 Azure CLI 会自动进行这种分配。
  3. 使用专用注册表(通过用户分配的托管标识向其进行身份验证)中的映像创建容器应用。

创建用户分配的托管标识

创建用户分配的托管标识。 在运行以下命令之前,将 <PLACEHOLDERS> 替换为你的托管标识的名称。

IDENTITY="<YOUR_IDENTITY_NAME>"
az identity create \
  --name $IDENTITY \
  --resource-group $RESOURCE_GROUP

获取标识的资源 ID。

IDENTITY_ID=`az identity show \
  --name $IDENTITY \
  --resource-group $RESOURCE_GROUP \
  --query id`

创建容器应用

使用专用注册表(通过标识向其进行身份验证)中的映像创建容器应用。

复制标识的资源 ID 并将其粘贴到以下命令中的 <IDENTITY_ID> 占位符中。 如果映像标记不是 latest,请将“latest”替换为你的标记。

echo $IDENTITY_ID
az containerapp create \
  --name $CONTAINERAPP_NAME \
  --resource-group $RESOURCE_GROUP \
  --environment $CONTAINERAPPS_ENVIRONMENT \
  --user-assigned <IDENTITY_ID> \
  --registry-identity <IDENTITY_ID> \
  --registry-server "$REGISTRY_NAME.azurecr.cn" \
  --image "$REGISTRY_NAME.azurecr.cn/$IMAGE_NAME:latest"

清理

注意

以下命令删除指定的资源组及其包含的所有资源。 如果指定的资源组中存在本快速入门范围外的资源,这些资源也会被删除。

az group delete --name $RESOURCE_GROUP

系统分配的托管标识

若要配置系统分配的标识,需要:

  1. 使用公共映像创建容器应用。
  2. 将系统分配的托管标识分配到容器应用。
  3. 使用专用映像更新容器应用。

创建容器应用

使用公共映像创建容器。

az containerapp create \
  --name $CONTAINERAPP_NAME \
  --resource-group $RESOURCE_GROUP \
  --environment $CONTAINERAPPS_ENVIRONMENT \
  --image mcr.microsoft.com/k8se/quickstart:latest \
  --target-port 80 \
  --ingress external

更新容器应用

使用专用容器注册表中的映像更新容器应用,并添加系统分配的标识来对 Azure 容器注册表拉取操作进行身份验证。 还可以包含容器应用所需的其他设置,例如引入、缩放和 Dapr 设置。

设置注册表服务器,并在容器应用中打开系统分配的托管标识。

az containerapp registry set \
  --name $CONTAINERAPP_NAME \
  --resource-group $RESOURCE_GROUP \
  --identity system \
  --server "$REGISTRY_NAME.azurecr.cn"
az containerapp update \
  --name $CONTAINERAPP_NAME \
  --resource-group $RESOURCE_GROUP \
  --image "$REGISTRY_NAME.azurecr.cn/$IMAGE_NAME:latest"

清理

注意

以下命令删除指定的资源组及其包含的所有资源。 如果指定的资源组中存在本快速入门范围外的资源,这些资源也会被删除。

az group delete --name $RESOURCE_GROUP

本文介绍如何使用 Bicep 模板将容器应用配置为使用用户分配的托管标识从专用 Azure 容器注册表存储库拉取映像。

先决条件

安装

若要从 CLI 登录到 Azure,请运行以下命令,然后按照提示完成身份验证过程。

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

为了确保运行最新版本的 CLI,请运行升级命令。

az upgrade

接下来,安装或更新适用于 CLI 的 Azure 容器应用扩展。

如果在 Azure CLI 中运行 az containerapp 命令,或在 Azure PowerShell 中运行 Az.App 模块中的 cmdlet 时收到有关缺少参数的错误,请确保已安装最新版本的 Azure 容器应用扩展。

az extension add --name containerapp --upgrade

注意

从 2024 年 5 月开始,Azure CLI 扩展不再默认启用预览功能。 要访问容器应用预览功能,请使用 --allow-preview true 安装容器应用扩展。

az extension add --name containerapp --upgrade --allow-preview true

现在已安装当前扩展或模块,接下来请注册 Microsoft.AppMicrosoft.OperationalInsights 命名空间。

注意

Azure 容器应用资源已从 Microsoft.Web 命名空间迁移到 Microsoft.App 命名空间。 如需更多详细信息,请参阅 2022 年 3 月的从 Azure.Web 到 Microsoft.App 的命名空间迁移

az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights

安装 Bicep

如果尚未安装 Bicep,可按如下方式安装它。

az bicep install

如果已安装 Bicep,请确保具有最新版本。

az bicep upgrade

有关详细信息,请参阅安装 Bicep

设置环境变量。

接下来,设置以下环境变量。 将括在 <> 中的占位符替换为你的值。

RESOURCE_GROUP="<RESOURCE_GROUP_NAME>"
LOCATION="<LOCATION>"
REGISTRY_NAME="<REGISTRY_NAME>"
IMAGE_NAME="<IMAGE_NAME>"
IMAGE_TAG="<IMAGE_TAG>"
BICEP_TEMPLATE="<BICEP_TEMPLATE>"
CONTAINERAPPS_ENVIRONMENT="<ENVIRONMENT_NAME>"
CONTAINER_NAME="<CONTAINER_NAME>"
CONTAINERAPP_NAME="<CONTAINERAPP_NAME>"
USER_ASSIGNED_IDENTITY_NAME="<USER_ASSIGNED_IDENTITY_NAME>"
LOG_ANALYTICS_WORKSPACE_NAME="<LOG_ANALYTICS_WORKSPACE_NAME>"
APP_INSIGHTS_NAME="<APP_INSIGHTS_NAME>"
ACR_PULL_DEFINITION_ID="7f951dda-4ed3-4680-a7ca-43fe172d538d"

AcrPull 角色授予用户分配的托管标识权限,以从注册表拉取映像。

Bicep 模板

复制以下 Bicep 模板并将其另存为扩展名为 .bicep 的文件。

param environmentName string 
param logAnalyticsWorkspaceName string
param appInsightsName string
param containerAppName string 
param azureContainerRegistry string
param azureContainerRegistryImage string 
param azureContainerRegistryImageTag string
param acrPullDefinitionId string
param userAssignedIdentityName string
param location string = resourceGroup().location

resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2022-01-31-preview' = {
  name: userAssignedIdentityName
  location: location 
}

resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(resourceGroup().id, azureContainerRegistry, 'AcrPullTestUserAssigned')
  properties: {
    principalId: identity.properties.principalId  
    principalType: 'ServicePrincipal'
    // acrPullDefinitionId has a value of 7f951dda-4ed3-4680-a7ca-43fe172d538d
    roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', acrPullDefinitionId)
  }
}

resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
  name: logAnalyticsWorkspaceName
  location: location
  properties: any({
    retentionInDays: 30
    features: {
      searchVersion: 1
    }
    sku: {
      name: 'PerGB2018'
    }
  })
}

resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: appInsightsName
  location: location
  kind: 'web'
  properties: {
    Application_Type: 'web'
    WorkspaceResourceId: logAnalyticsWorkspace.id
  }
}

resource appEnvironment 'Microsoft.App/managedEnvironments@2022-06-01-preview' = {
  name: environmentName
  location: location
  properties: {
    daprAIInstrumentationKey: appInsights.properties.InstrumentationKey
    appLogsConfiguration: {
      destination: 'log-analytics'
      logAnalyticsConfiguration: {
        customerId: logAnalyticsWorkspace.properties.customerId
        sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
      }
    }
  }
}

resource containerApp 'Microsoft.App/containerApps@2022-06-01-preview' = {
  name: containerAppName
  location: location
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '${identity.id}': {}
    }
  }
  properties: {
    environmentId: appEnvironment.id
    configuration: {
      ingress: {
        targetPort: 8080
        external: true
      }
      registries: [
        {
          server: '${azureContainerRegistry}.azurecr.cn'
          identity: identity.id
        }
      ]
    }
    template: {
      containers: [
        {
          image: '${azureContainerRegistry}.azurecr.cn/${azureContainerRegistryImage}:${azureContainerRegistryImageTag}'
          name: '${azureContainerName}'
          resources: {
            cpu: 1
            memory: '2Gi'
          }
        }
      ]
      scale: {
        minReplicas: 1
        maxReplicas: 1
      }
    }
  }
}

output location string = location
output environmentId string = appEnvironment.id

部署容器应用

使用以下命令部署容器应用。

az deployment group create \
  --resource-group "$RESOURCE_GROUP" \
  --template-file "$BICEP_TEMPLATE" \
  --parameters environmentName="$CONTAINERAPPS_ENVIRONMENT" \
  logAnalyticsWorkspaceName="$LOG_ANALYTICS_WORKSPACE_NAME" \
  appInsightsName="$APP_INSIGHTS_NAME" \
  containerAppName="$CONTAINERAPP_NAME" \
  azureContainerRegistry="$REGISTRY_NAME" \
  azureContainerRegistryImage="$IMAGE_NAME" \
  azureContainerRegistryImageTag="$IMAGE_TAG" \
  azureContainerName="$CONTAINER_NAME" \
  acrPullDefinitionId="$ACR_PULL_DEFINITION_ID" \
  userAssignedIdentityName="$USER_ASSIGNED_IDENTITY_NAME" \
  location="$LOCATION"

此命令会部署以下资源。

  • Azure 资源组。
  • 一个容器应用环境。
  • 一个与容器应用环境关联的 Log Analytics 工作区。
  • 一个用于分布式跟踪的 Application Insights 资源。
  • 用户分配的托管标识。
  • 一个用于存储映像的容器。
  • 一个基于映像的容器应用。

如果收到 Failed to parse '<YOUR_BICEP_FILE_NAME>', please check whether it is a valid JSON format 错误,请确保 Bicep 模板文件具有扩展名 .bicep

其他资源

有关详细信息,请参阅以下内容。

后续步骤