在 Azure Kubernetes Service (AKS) 中使用用户分配的托管标识

本文介绍如何在新的或现有的 AKS 群集上启用用户分配的托管标识,获取用户分配的托管标识的主体 ID,并为用户分配的托管标识添加角色分配。

先决条件

  • 现有的 Azure 资源组。 如果您没有一个账户,可以使用az group create命令创建一个。

    az group create \
        --name <resource-group-name> \
        --location <location>
    
  • 已安装 Azure CLI 2.23.0 或更高版本。 运行 az --version 即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure CLI
  • 若要更新现有群集以使用 用户分配的托管标识,需要安装 Azure CLI 2.49.0 或更高版本。
  • 在本地安装 Terraform。 有关安装说明,请参阅 安装 Terraform

局限性

  • 使用托管标识创建群集后,无法切换回使用服务主体。
  • 不支持将启用托管标识的群集移动或迁移到其他租户。
  • 如果群集已启用 Microsoft Entra pod 托管标识(aad-pod-identity),Node-Managed Identity(NMI)Pod 将修改节点的 iptables,以截获对 Azure 实例元数据(IMDS)终结点的调用。 此配置意味着对 IMDS 终结点发出的任何请求都将被 NMI 拦截,即使特定 Pod 不使用 aad-pod-identity
    • 可以配置 AzurePodIdentityException 自定义资源定义(CRD),以指定来自匹配 CRD 中定义标签的 Pod 的请求应在不经过 NMI 处理的情况下直接代理至 IMDS 终结点。 通过配置 AzurePodIdentityException CRD,排除 kubernetes.azure.com/managedby: aks 中 kube-system 命名空间中带有 aad-pod-identity 标签的系统 Pod。 有关详细信息,请参阅 在 Azure Kubernetes 服务(AKS)中使用 Microsoft Entra pod 托管标识
    • 若要配置例外情况,请安装 mic-exception YAML

更新群集注意事项

更新群集时,请考虑以下信息:

  • 仅当有 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 拉取。

创建用户分配的托管标识

如果你没有用户分配的托管标识资源,请使用 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)

在新 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>"
        }
    }
    },
...

更新群集以使用用户分配的托管标识而不是服务主体后,控制平面和 Pod 在访问 Azure 中的其他服务时会使用用户分配的托管标识进行授权。 Kubelet 继续使用服务主体,直到您升级节点池。 节点池升级会导致 AKS 群集停机,因为节点池中的节点被封锁、清空并重新映像。 可以在您的节点上使用命令将其更新为用户分配的托管身份。

az aks nodepool upgrade \
  --resource-group <resource-group-name> \
  --cluster-name <aks-cluster-name> \
  --name <node-pool-name> \
  --node-image-only

注意

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

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

使用 az role assignment create 命令为用户分配的托管标识添加角色分配。 以下示例将“密钥保管库机密用户”角色分配给用户分配的托管标识,以授予其访问密钥保管库中的机密的权限。 角色的分配范围限定于密钥保管库资源。

az role assignment create \
    --assignee <client-id> \
    --role "Key Vault Secrets User" \
    --scope "<key-vault-resource-id>"

注意

群集托管标识的权限传播可能最长需要 60 分钟才能生效。

创建 Terraform 配置文件

Terraform 配置文件定义 Terraform 创建和管理的基础结构。

  1. 创建名为 main.tf 的文件,并添加以下代码以定义 Terraform 版本并指定Azure提供程序:

    terraform {
    required_version = ">= 1.0"
    required_providers {
      azurerm = {
        source  = "hashicorp/azurerm"
        version = "~> 4.0"
      }
     }
    }
    provider "azurerm" {
     features {}
    }
    
  2. 添加以下代码到 main.tf 来创建 Azure 资源组。 根据需要随时更改资源组的名称和位置。

    resource "azurerm_resource_group" "example" {
     name     = "aks-rg"
     location = "chinanorth3"
    }
    

使用 Terraform 创建具有用户分配的托管标识的 AKS 群集

要创建用户分配的托管标识和使用该标识的 AKS 群集,请在 main.tf 中添加以下代码:

resource "azurerm_user_assigned_identity" "uai" {
 name                = "aks-user-identity"
 resource_group_name = azurerm_resource_group.example.name
 location            = azurerm_resource_group.example.location
}
resource "azurerm_kubernetes_cluster" "user_assigned" {
 name                = "aks-user"
 location            = azurerm_resource_group.example.location
 resource_group_name = azurerm_resource_group.example.name
 dns_prefix          = "aksuser"
 identity {
   type         = "UserAssigned"
   identity_ids = [azurerm_user_assigned_identity.uai.id]
 }
 default_node_pool {
   name       = "system"
   node_count = 1
   vm_size    = "Standard_DS2_v2"
 }
}

使用 Terraform 为用户分配的托管标识添加角色分配

添加以下代码,为 main.tf 用户分配的托管标识创建角色分配。 此示例将 Key Vault 机密用户 角色分配给用户分配的托管标识,以授予它访问密钥保管库中的机密的权限。 角色的分配范围限定于密钥保管库资源。

resource "azurerm_role_assignment" "user_assigned_key_vault_secrets_user" {
 scope                = azurerm_resource_group.example.id
 role_definition_name = "Key Vault Secrets User"
 principal_id         = azurerm_user_assigned_identity.uai.principal_id
}

初始化 Terraform

使用main.tf命令在包含terraform init文件的目录中初始化 Terraform。 此命令下载用于通过 Terraform 管理 Azure 资源所需的 Azure 提供程序。

terraform init

创建 Terraform 执行计划

使用 terraform plan 命令创建 Terraform 执行计划。 此命令显示 Terraform 将在 Azure 订阅中创建或修改的资源。

terraform plan

应用 Terraform 配置

查看并确认执行计划后,使用 terraform apply 命令应用 Terraform 配置。 此命令创建或修改 Azure 订阅中 main.tf 文件中定义的资源。

terraform apply

验证 Terraform 部署

应用 Terraform 配置后,可以使用 [az aks show][az-aks-show] 命令,并结合 --query 参数来验证部署,以筛选输出并显示标识信息。 例如:

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

若要详细了解 AKS 中的托管标识,请参阅以下文章: