在 Azure Kubernetes 服务中使用系统分配的托管标识(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
  • 如果使用的是自定义专用 DNS 区域,则 AKS 不支持使用系统分配的托管标识。

更新群集注意事项

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

  • 仅当有 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 群集时,默认情况下会启用系统分配的托管标识。

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

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

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

使用 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)

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

注意

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

使用 az role assignment create 命令将 Azure RBAC 角色分配给系统分配的托管标识。 以下示例将 网络贡献者 角色分配给系统分配的托管标识。 角色分配的范围限定为包含 VNet 的资源组。

az role assignment create \
    --assignee <client-id> \
    --role "Network Contributor" \
    --scope <custom-resource-group-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 群集

main.tf 中添加以下代码以创建具有系统分配管理标识的 AKS 集群:

resource "azurerm_kubernetes_cluster" "system_assigned" {
 name                = "aks-system"
 location            = azurerm_resource_group.example.location
 resource_group_name = azurerm_resource_group.example.name
 dns_prefix          = "akssystem"
 identity {
   type = "SystemAssigned"
 }
 default_node_pool {
   name       = "system"
   node_count = 1
   vm_size    = "Standard_DS2_v2"
 }
}

使用 Terraform 为系统分配的托管身份添加角色分配

将以下代码添加到 main.tf 以为系统分配的托管标识创建角色分配。 此示例将 网络贡献者 角色分配给由系统分配的托管身份。 角色分配的范围限定为包含 VNet 的资源组。

resource "azurerm_role_assignment" "system_assigned_network_contributor" {
 scope                = azurerm_resource_group.example.id
 role_definition_name = "Network Contributor"
 principal_id         = azurerm_kubernetes_cluster.system_assigned.identity[0].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命令和--query参数来验证部署,以筛选输出并显示标识信息。 例如:

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

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