Compartir a través de

在 Azure Kubernetes 服务 (AKS) 中使用托管标识

Azure Kubernetes 服务 (AKS) 群集需要 Microsoft Entra 标识才能访问负载均衡器和托管磁盘等 Azure 资源。 建议使用 Azure 资源托管标识来授权从 AKS 群集访问其他 Azure 服务。

可以使用托管标识授权从 AKS 群集访问任何支持 Microsoft Entra 授权的服务,而无需管理凭据或将其包含在代码中。 为托管标识分配 Azure 基于角色的访问控制 (Azure RBAC) 角色,以授予其对 Azure 中特定资源的权限。 例如,可以向托管标识授予权限,以访问 Azure 密钥保管库中的机密供群集使用。 有关 Azure RBAC 的详细信息,请参阅什么是 Azure 基于角色的访问控制 (Azure RBAC)?

本文介绍如何在新的或现有的 AKS 群集上启用以下类型的托管标识:

  • 系统分配的托管标识。 系统分配的托管标识与单个 Azure 资源(例如 AKS 群集)相关联。 它仅在群集的生命周期内存在。
  • 用户分配的托管标识。 用户分配的托管标识是一个独立的 Azure 资源,AKS 群集可以使用它来授权访问其他 Azure 服务。 它独立于 AKS 群集存在,可供多个 Azure 资源使用。
  • 预先创建的 kubelet 托管标识。 预先创建的 kubelet 托管标识是一个可选的用户分配标识,kubelet 可以使用它来访问 Azure 中的其他资源。 如果你未为 kubelet 指定用户分配的托管标识,AKS 将在节点资源组中创建用户分配的 kubelet 标识。

若要了解托管标识的详细信息,请参阅 Azure 资源托管标识

概述

AKS 群集使用托管标识从 Microsoft Entra 请求令牌。 这些令牌用于授权访问 Azure 中运行的其他资源。 可以将 Azure RBAC 角色分配到托管标识,以授予群集访问特定资源的权限。 例如,如果你的群集需要访问 Azure 密钥保管库中的机密,则可为群集的托管标识分配授予这些权限的 Azure RBAC 角色。

托管标识可以由系统分配,也可以由用户分配。 这两种类型的托管标识相似,因为你可以使用任一类型来授权从 AKS 群集访问 Azure 资源。 它们的主要差别在于,系统分配的托管标识与单个 Azure 资源(例如 AKS 群集)相关联,而用户分配的托管标识本身就是一个独立的 Azure 资源。 有关托管标识类型之间差异的更多详细信息,请参阅 Azure 资源托管标识中的“托管标识类型”

这两种类型的托管标识均由 Azure 平台管理,因此可以授权从应用程序进行访问,而无需配置或轮换任何机密。 Azure 将为你管理标识的凭据。

部署 AKS 群集时,默认情况下会为你创建系统分配的托管标识。 还可以使用用户分配的托管标识来创建群集。

还可以使用应用程序服务主体而不是托管标识来创建群集。 为了安全性和易用性,建议使用托管标识而不是服务主体。 有关使用服务主体创建群集的详细信息,请参阅将服务主体与 Azure Kubernetes 服务 (AKS) 配合使用

可以更新现有群集以使用来自应用程序服务主体的托管标识。 还可以将现有群集更新为不同类型的托管标识。 如果群集已在使用托管标识,并且该标识已发生更改,例如,如果将群集标识类型从系统分配更新为用户分配,那么控制平面组件切换到新标识时会出现延迟。 控制平面组件将继续使用旧标识,直到其令牌过期。 刷新令牌后,这些组件会切换到新标识。 此过程可能需要几小时的时间。

系统分配和用户分配的标识类型不同于 Microsoft Entra 工作负载标识,后者旨在供 Pod 上运行的应用程序使用。

开始之前

在运行本文中的示例之前,请先调用 az account set 命令并传入订阅 ID,将订阅设置为当前活动订阅。

az account set --subscription <subscription-id>

如果你没有 Azure 资源组,也可以通过调用 az group create 命令创建一个。

az group create \
    --name myResourceGroup \
    --location chinanorth3

启用系统分配的托管标识

系统分配的托管标识是与 AKS 群集或其他 Azure 资源相关联的标识。 系统分配的托管标识与群集的生命周期相关联。 删除群集时,也会删除系统分配的托管标识。

AKS 群集可以使用系统分配的托管标识来授权访问 Azure 中运行的其他资源。 可以将 Azure RBAC 角色分配到系统分配的托管标识,以授予群集访问特定资源的权限。 例如,如果你的群集需要访问 Azure 密钥保管库中的机密,则可为系统分配的托管标识分配授予这些权限的 Azure RBAC 角色。

在新的 AKS 群集上启用系统分配的托管标识

若要在新群集上启用系统分配的托管标识,请调用 az aks create。 默认情况下,新群集上启用系统分配的托管标识。

使用 az aks create 命令创建 AKS 群集。

az aks create \
    --resource-group myResourceGroup \
    --name myManagedCluster \
    --generate-ssh-keys

若要验证群集创建后是否启用了系统分配的托管标识,请参阅确定群集正在使用哪种类型的托管标识

更新现有 AKS 群集以使用系统分配的托管标识

若要将使用服务主体的现有 AKS 群集更新为使用系统分配的托管标识,请运行带有 --enable-managed-identity 参数的 az aks update 命令。

az aks update \
    --resource-group myResourceGroup \
    --name myManagedCluster \
    --enable-managed-identity

将群集更新为使用系统分配的托管标识而不是服务主体后,控制平面和 Pod 在访问 Azure 中的其他服务时将使用系统分配的托管标识进行授权。 Kubelet 会继续使用服务主体,直到你同时升级代理池。 可以在节点上使用 az aks nodepool upgrade --resource-group myResourceGroup --cluster-name myAKSCluster --name mynodepool --node-image-only 命令更新到托管标识。 节点池升级会导致 AKS 群集停机,因为节点池中的节点将被封锁、排空,然后重置映像。

注意

更新集群时请牢记以下信息:

  • 仅当有要使用的 VHD 更新时,更新才有效。 如果你运行的是最新的 VHD,则需要等到下一个 VHD 可用才能执行更新。

  • Azure CLI 可以确保你的插件权限在迁移后正确设置。 如果不使用 Azure CLI 执行迁移操作,则需要自行处理插件身份的权限。 有关使用 Azure 资源管理器 (ARM) 模板的示例,请参阅使用 ARM 模板分配 Azure 角色

  • 如果群集使用 --attach-acr 从 Azure 容器注册表 (ACR) 的映像中进行拉取,则需要在更新群集后运行 az aks update --resource-group myResourceGroup --name myAKSCluster --attach-acr <ACR resource ID>,以便让新建的用于托管标识的 kubelet 能够获得从 ACR 进行拉取的权限。 否则,升级后将无法从 ACR 进行拉取。

为系统分配的托管标识添加角色分配

可以将 Azure RBAC 角色分配到系统分配的托管标识,以授予群集对另一个 Azure 资源的权限。 Azure RBAC 支持指定权限级别的内置和自定义角色定义。 有关分配 Azure RBAC 角色的详细信息,请参阅分配 Azure 角色的步骤

将 Azure RBAC 角色分配到托管标识时,必须定义该角色的范围。 一般情况下,最佳做法是将角色的范围限制为托管标识所需的最低特权。 有关确定 Azure RBAC 角色范围的详细信息,请参阅了解 Azure RBAC 的范围

如果你创建并使用自己的 VNet、附加的 Azure 磁盘、静态 IP 地址、路由表或用户分配的 kubelet 标识,并且其中的资源位于工作器节点资源组的外部,则 Azure CLI 将自动添加角色分配。 如果使用 ARM 模板或其他方法,请使用托管标识的主体 ID 来执行角色分配。

如果你没有使用 Azure CLI,而是使用自己的 VNet、附加的 Azure 磁盘、静态 IP 地址、路由表或用户分配的 kubelet 标识,并且它们位于工作器节点资源组的外部,则建议使用用户分配的控制平面托管标识。 当控制平面使用系统分配的托管标识时,该标识与群集同时创建,因此在创建群集之前无法执行角色分配。

获取系统分配的托管标识的主体 ID

若要将 Azure RBAC 角色分配到群集的系统分配托管标识,首先需要获取该托管标识的主体 ID。 通过调用 az aks show 命令获取群集的系统分配托管标识的主体 ID。

# Get the principal ID for a system-assigned managed identity.
CLIENT_ID=$(az aks show \
    --name myAKSCluster \
    --resource-group myResourceGroup \
    --query identity.principalId \
    --output tsv)

将 Azure RBAC 角色分配到系统分配的托管标识

若要向系统分配的托管标识授予对 Azure 中资源的权限,请调用 az role assignment create 命令以将 Azure RBAC 角色分配到托管标识。

对于默认工作器节点资源组外部的 VNet、附加的 Azure 磁盘、静态 IP 地址或路由表,需要对自定义资源组分配 Network Contributor 角色。

例如,使用 az role assignment create 命令在自定义资源组上分配 Network Contributor 角色。 对于 --scope 参数,请提供群集资源组的资源 ID。

az role assignment create \
    --assignee $CLIENT_ID \
    --role "Network Contributor" \
    --scope "<resource-group-id>"

注意

向群集托管标识授予的权限最长可能需要 60 分钟才能填充。

启用用户分配的托管标识

用户分配的托管标识是独立的 Azure 资源。 为控制平面创建具有用户分配的托管标识的群集时,用户分配的托管标识资源必须在群集创建之前存在。 此功能可实现多种方案,例如使用自定义 VNet 或出站类型的用户定义的路由 (UDR) 创建群集。

创建用户分配的托管标识

如果你没有用户分配的托管标识资源,请使用 az identity create 命令创建一个。

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

输出应与下面的示例输出类似:

{                                  
  "clientId": "<client-id>",
  "clientSecretUrl": "<clientSecretUrl>",
  "id": "/subscriptions/<subscriptionid>/resourcegroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity", 
  "location": "chinaeast2",
  "name": "myIdentity",
  "principalId": "<principal-id>",
  "resourceGroup": "myResourceGroup",                       
  "tags": {},
  "tenantId": "<tenant-id>",
  "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
}

获取用户分配的托管标识的主体 ID

若要获取用户分配的托管标识的主体 ID,请调用 az Identity Show 并查询 principalId 属性:

CLIENT_ID=$(az identity show \
    --name myIdentity \
    --resource-group myResourceGroup \
    --query principalId \
    --output tsv)

获取用户分配的托管标识的资源 ID

若要创建具有用户分配的托管标识的群集,需要获取新托管标识的资源 ID。 若要获取用户分配的托管标识的资源 ID,请调用 az aks show 并查询 id 属性:

RESOURCE_ID=$(az identity show \
    --name myIdentity \
    --resource-group myResourceGroup \
    --query id \
    --output tsv)

将 Azure RBAC 角色分配给用户分配的托管标识

在创建群集之前,通过调用 az role assignment create 命令为托管标识添加角色分配。

以下示例将“密钥保管库机密用户”角色分配给用户分配的托管标识,以授予其访问密钥保管库中的机密的权限。 角色分配的范围限定为密钥保管库资源:

az role assignment create \
    --assignee $CLIENT_ID \
    --role "Key Vault Secrets User" \
    --scope "<keyvault-resource-id>"

注意

向群集托管标识授予的权限最长可能需要 60 分钟才能填充。

使用用户分配的托管标识创建群集

若要使用用户分配的托管标识创建 AKS 群集,请调用 az aks create 命令。 包含 --assign-identity 参数并传入用户分配的托管标识的资源 ID:

az aks create \
    --resource-group myResourceGroup \
    --name myManagedCluster \
    --network-plugin azure \
    --vnet-subnet-id <subnet-id> \
    --dns-service-ip 10.2.0.10 \
    --service-cidr 10.2.0.0/24 \
    --assign-identity $RESOURCE_ID \
    --generate-ssh-keys

更新现有群集以使用用户分配的托管标识

若要更新现有群集以使用用户分配的托管标识,请调用 az aks update 命令。 包含 --assign-identity 参数并传入用户分配的托管标识的资源 ID:

az aks update \
    --resource-group myResourceGroup \
    --name myManagedCluster \
    --enable-managed-identity \
    --assign-identity $RESOURCE_ID

成功更新群集以使用用户分配的托管标识后,输出应如以下示例所示:

  "identity": {
    "principalId": null,
    "tenantId": null,
    "type": "UserAssigned",
    "userAssignedIdentities": {
      "/subscriptions/<subscriptionid>/resourcegroups/resourcegroups/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity": {
        "clientId": "<client-id>",
        "principalId": "<principal-id>"
      }
    }
  },

注意

将控制平面的托管标识从“系统分配”迁移到“用户分配”不会导致控制平面和代理池停机。 控制平面组件将继续使用旧的系统分配的标识长达几个小时,直到下一次令牌刷新。

确定群集正在使用哪种类型的托管标识

若要确定现有 AKS 群集正在使用哪种类型的托管标识,请调用 az aks show 命令并查询标识的 type 属性

az aks show \
    --name myAKSCluster \
    --resource-group myResourceGroup \
    --query identity.type \
    --output tsv       

如果群集使用托管标识,则 type 属性的值将为 SystemAssigned 或 UserAssigned

如果群集正在使用服务主体,则 type 属性的值为 null。 请考虑升级群集以使用托管标识。

使用预先创建的 kubelet 托管标识

预先创建的 kubelet 标识是在群集创建之前存在的用户分配的管理标识。 此功能支持在创建群集期间连接到 Azure 容器注册表 (ACR) 等方案。

注意

如果你未指定自己的 kubelet 托管标识,AKS 将在节点资源组中创建用户分配的 kubelet 标识。

kubelet 托管标识

如果你没有 kubelet 托管标识,请使用 az identity create 命令创建一个。

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

输出应与下面的示例输出类似:

{
  "clientId": "<client-id>",
  "clientSecretUrl": "<clientSecretUrl>",
  "id": "/subscriptions/<subscriptionid>/resourcegroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myKubeletIdentity", 
  "location": "chinaeast2",
  "name": "myKubeletIdentity",
  "principalId": "<principal-id>",
  "resourceGroup": "myResourceGroup",                       
  "tags": {},
  "tenantId": "<tenant-id>",
  "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
}

为 kubelet 托管标识分配 RBAC 角色

使用 az role assignment create 命令在 kubelet 标识上分配 ACRPull 角色。 为 $KUBELET_CLIENT_ID 变量提供 kubelet 标识的主体 ID,为 $ACR_REGISTRY_ID 变量提供 ACR 注册表 ID。

az role assignment create \
    --assignee $KUBELET_CLIENT_ID \
    --role "acrpull" \
    --scope "$ACR_REGISTRY_ID"

创建群集以使用 kubelet 标识

现在,可以使用现有标识来创建 AKS 群集。 请确保通过包括 assign-identity 参数和 kubelet 托管标识(使用 assign-kubelet-identity 参数)为控制平面提供托管标识的资源 ID。

使用 az aks create 命令创建具有现有标识的 AKS 群集。

az aks create \
    --resource-group myResourceGroup \
    --name myManagedCluster \
    --network-plugin azure \
    --vnet-subnet-id <subnet-id> \
    --dns-service-ip 10.2.0.10 \
    --service-cidr 10.2.0.0/24 \
    --assign-identity <identity-resource-id> \
    --assign-kubelet-identity <kubelet-identity-resource-id> \
    --generate-ssh-keys

使用 kubelet 托管标识成功创建 AKS 群集后,应生成如下所示的输出:

  "identity": {
    "principalId": null,
    "tenantId": null,
    "type": "UserAssigned",
    "userAssignedIdentities": {
      "/subscriptions/<subscriptionid>/resourcegroups/resourcegroups/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity": {
        "clientId": "<client-id>",
        "principalId": "<principal-id>"
      }
    }
  },
  "identityProfile": {
    "kubeletidentity": {
      "clientId": "<client-id>",
      "objectId": "<object-id>",
      "resourceId": "/subscriptions/<subscriptionid>/resourcegroups/resourcegroups/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myKubeletIdentity"
    }
  },

更新现有群集以使用 kubelet 标识

若要更新现有群集以使用 kubelet 托管标识,请首先获取 AKS 群集的当前控制平面托管标识。

警告

更新 kubelet 托管标识会升级 AKS 群集的节点池,这会导致群集停机,因为节点池中的节点被封锁/排空并重置映像。

  1. 使用 az aks show 命令确认 AKS 群集是否在使用用户分配的托管标识。

    az aks show \
        --resource-group <RGName> \
        --name <ClusterName> \
        --query "servicePrincipalProfile"
    

    如果群集使用托管标识,则输出会显示 clientId,其值为 msi。 使用服务主体的群集会显示一个对象 ID。 例如:

    # The cluster is using a managed identity.
    {
      "clientId": "msi"
    }
    
  2. 确认群集正在使用托管标识后,可使用 az aks show 命令查找托管标识的资源 ID。

    az aks show --resource-group <RGName> \
        --name <ClusterName> \
        --query "identity"
    

    对于用户分配的托管标识,输出应类似于以下示例输出:

    {
      "principalId": null,
      "tenantId": null,
      "type": "UserAssigned",
      "userAssignedIdentities": <identity-resource-id>
          "clientId": "<client-id>",
          "principalId": "<principal-id>"
    },
    
  3. 使用 az aks update 命令更新具有现有标识的群集。 为 assign-identity 参数提供控制平面的用户分配托管标识的资源 ID。 为 assign-kubelet-identity 参数提供 kubelet 托管标识的资源 ID。

    az aks update \
        --resource-group myResourceGroup \
        --name myManagedCluster \
        --enable-managed-identity \
        --assign-identity <identity-resource-id> \
        --assign-kubelet-identity <kubelet-identity-resource-id>
    

使用你自己的 kubelet 托管标识成功更新 AKS 群集后,应会显示类似于以下示例输出的信息:

  "identity": {
    "principalId": null,
    "tenantId": null,
    "type": "UserAssigned",
    "userAssignedIdentities": {
      "/subscriptions/<subscriptionid>/resourcegroups/resourcegroups/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity": {
        "clientId": "<client-id>",
        "principalId": "<principal-id>"
      }
    }
  },
  "identityProfile": {
    "kubeletidentity": {
      "clientId": "<client-id>",
      "objectId": "<object-id>",
      "resourceId": "/subscriptions/<subscriptionid>/resourcegroups/resourcegroups/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myKubeletIdentity"
    }
  },