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

本文提供有关如何在 Azure Kubernetes 服务(AKS)中启用和使用系统分配的、用户分配的或预先创建的 kubelet 托管标识的分步说明。

AKS 托管标识先决条件

  • 阅读 Azure Kubernetes 服务(AKS)中的托管标识概述 ,了解 AKS 中可用的不同类型的托管标识,以及如何使用这些标识安全地访问 Azure 资源。

  • 运行本文中的示例之前,请使用 az account set 命令将订阅设置为当前活动订阅。

    az account set --subscription <subscription-id>
    
  • 如果还没有 Azure 资源组,请通过调用 az group create 该命令来创建一个。

    az group create \
        --name <resource-group-name> \
        --location <location>
    

Azure CLI 版本最低要求

局限性

  • 不支持将启用托管标识的群集移动或迁移到其他租户。

  • 如果群集启用了 Microsoft Entra pod 托管标识 (aad-pod-identity),节点托管标识 (NMI) pod 将修改节点的 iptable,以拦截对 Azure 实例元数据终结点 (IMDS) 的调用。 此配置意味着对 IMDS 终结点发出的任何请求都将被 NMI 拦截,即使特定 Pod 不使用 aad-pod-identity

    可以配置 AzurePodIdentityException 自定义资源定义 (CRD),以指定应该中转来自与 CRD 中定义的标签匹配的 Pod 对 IMDS 终结点的请求,而不在 NMI 中进行任何处理。 通过配置 AzurePodIdentityException CRD,排除 kubernetes.azure.com/managedby: aks 中 kube-system 命名空间中带有 aad-pod-identity 标签的系统 Pod。 有关详细信息,请参阅在 Azure Kubernetes 服务中使用 Microsoft Entra Pod 托管标识

    若要配置例外情况,请安装 mic-exception YAML

  • 如果使用的是自定义专用 DNS 区域,则 AKS 不支持使用系统分配的托管标识。

  • Azure 美国政府云中的 USDOD Central、USDOD East 和 USGov Iowa 区域不支持创建具有用户分配的托管标识的群集。

  • 预先创建的 kubelet 托管标识必须是用户分配的托管标识。
  • 不支持由世纪互联运营的 Azure 中的“中国东部”和“中国北部”区域。

注意

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

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

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

  • 如果您的群集使用 --attach-acr 从 Azure 容器注册表(ACR)中拉取映像,那么在更新群集后,您需要运行 az aks update --resource-group <resource-group-name> --name <aks-cluster-name> --attach-acr <acr-resource-id> 命令,以便让新创建用于托管身份的 kubelet 获得从 ACR 拉取映像的权限。 否则,升级后将无法从 ACR 进行拉取。

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

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

创建新的 AKS 群集时,默认情况下会启用系统分配的托管标识。

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

    az aks create \
        --resource-group <resource-group-name> \
        --name <aks-cluster-name> \
        --generate-ssh-keys
    

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

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

    az aks update \
        --resource-group <resource-group-name> \
        --name <aks-cluster-name> \
        --enable-managed-identity
    

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

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

  • 使用 az aks show 命令获取群集系统分配的托管标识的主体 ID。

    CLIENT_ID=$(az aks show \
        --name <aks-cluster-name> \
        --resource-group <resource-group-name> \
        --query identity.principalId \
        --output tsv)
    

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

  • 使用 az role assignment create 命令将 Azure RBAC 角色分配给系统分配的托管标识。

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

    以下示例将 网络贡献者 角色分配给系统分配的托管标识。 角色分配的范围限定为包含 VNet 的资源组。

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

    注意

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

创建用户分配的托管标识

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

    az identity create \
        --name <identity-name> \
        --resource-group <resource-group-name>
    

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

    {                                  
      "clientId": "<client-id>",
      "clientSecretUrl": "<clientSecretUrl>",
      "id": "/subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<identity-name>",
      "location": "<location>",
      "name": "<identity-name>",
      "principalId": "<principal-id>",
      "resourceGroup": "<resource-group-name>",
      "tags": {},
      "tenantId": "<tenant-id>",
      "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
    }
    

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

  • 使用 az identity show 命令获取用户分配的托管身份的主体 ID。

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

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

  • 使用 az identity show 命令获取用户定义的托管身份的资源 ID。

    RESOURCE_ID=$(az identity show \
        --name <identity-name> \
        --resource-group <resource-group-name> \
        --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 群集上启用用户分配的托管标识

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

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

    az aks create \
        --resource-group <resource-group-name> \
        --name <cluster-name> \
        --network-plugin azure \
        --vnet-subnet-id <vnet-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 <resource-group-name> \
        --name <cluster-name> \
        --enable-managed-identity \
        --assign-identity $RESOURCE_ID
    

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

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

    注意

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

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

  • 使用az aks show命令验证群集使用的托管标识类型。

    az aks show \
        --name <aks-cluster-name> \
        --resource-group <resource-group-name> \
        --query identity.type \
        --output tsv       
    

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

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

创建 kubelet 托管标识

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

    az identity create \
        --name <kubelet-identity-name> \
        --resource-group <resource-group-name>
    

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

    {
      "clientId": "<client-id>",
      "clientSecretUrl": "<clientSecretUrl>",
      "id": "/subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<kubelet-identity-name>",
      "location": "<location>",
      "name": "<kubelet-identity-name>",
      "principalId": "<principal-id>",
      "resourceGroup": "<resource-group-name>",
      "tags": {},
      "tenantId": "<tenant-id>",
      "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
    }
    

为 kubelet 托管标识分配 RBAC 角色

  • 使用acrpull命令在 kubelet 托管标识上分配az role assignment create角色。

    az role assignment create \
        --assignee <kubelet-client-id> \
        --role "acrpull" \
        --scope "<acr-registry-id>"
    

在 AKS 群集上启用 kubelet 的托管标识

在新 AKS 群集上启用 kubelet 托管标识

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

    az aks create \
        --resource-group <resource-group-name> \
        --name <aks-cluster-name> \
        --network-plugin azure \
        --vnet-subnet-id <vnet-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/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<identity-name>": {
            "clientId": "<client-id>",
            "principalId": "<principal-id>"
          }
        }
      },
      "identityProfile": {
        "kubeletidentity": {
          "clientId": "<client-id>",
          "objectId": "<object-id>",
          "resourceId": "/subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<kubelet-identity-name>"
        }
      },
    

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

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

警告

更新 kubelet 托管标识会升级 AKS 群集的节点池,确保在执行之前配置正确的可用性配置(如 Pod 中断预算),以避免工作负荷中断或在维护时段内执行此作。

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

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

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

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

    az aks show --resource-group <resource-group-name> \
        --name <aks-cluster-name> \
        --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 <resource-group-name> \
        --name <aks-cluster-name> \
        --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/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<identity-name>": {
            "clientId": "<client-id>",
            "principalId": "<principal-id>"
          }
        }
      },
      "identityProfile": {
        "kubeletidentity": {
          "clientId": "<client-id>",
          "objectId": "<object-id>",
          "resourceId": "/subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<kubelet-identity-name>"
        }
      },
    

获取 kubelet 托管标识的属性

  • 使用 az aks show 命令并在 identityProfile.kubeletidentity 属性上查询来获取 kubelet 托管标识的属性。

    az aks show \
        --name <aks-cluster-name> \
        --resource-group <resource-group-name> \
        --query "identityProfile.kubeletidentity"
    

后续步骤

  • 使用 [Azure 资源管理器模板][aks-arm-template] 创建已启用托管标识的群集。
  • 了解如何对 AKS 中所有受支持的 Microsoft Entra 身份验证方法使用 kubelogin