다음을 통해 공유

使用 Azure Kubernetes 服务 (AKS) 的服务主体

Azure Kubernetes 服务(AKS)群集需要 Microsoft Entra 服务主体托管标识 来动态创建和管理其他 Azure 资源。 本文介绍如何创建Microsoft Entra 服务主体并将其用于 AKS 群集。

注意

为了获得最佳安全性和易用性,我们建议使用托管标识而不是服务主体来授权从 AKS 群集访问 Azure 中的其他资源。 托管标识是一种特殊的服务主体类型,可用于获取 Microsoft Entra 凭据,而无需管理和保护凭据。 有关详细信息,请参阅在 AKS 中使用托管标识

先决条件

  • 需要 Azure CLI 2.0.59 或更高版本。 使用 az --version 命令查找版本。 如果需要进行安装或升级,请参阅安装 Azure CLI
  • 如果使用 Azure PowerShell,则需要 Azure PowerShell 5.0.0 或更高版本。 使用 Get-InstalledModule -Name Az cmdlet 来查找版本。 如果需要安装或升级,请参阅安装 Azure Az PowerShell 模块
  • 需要权限来向 Microsoft Entra 租户注册一个应用程序,并将该应用程序指派给订阅中的一个角色。 如果没有必要的权限,则需要要求Microsoft Entra ID 或订阅管理员分配必要的权限或为你创建服务主体。

使用服务主体时的注意事项

将 Microsoft Entra 服务主体与 AKS 配合使用时,请记住以下注意事项:

  • Kubernetes 的服务主体是群集配置的一部分,但不要使用此标识来部署群集。 而是先 创建服务主体 ,然后使用该服务主体创建 AKS 群集。
  • 每个服务主体都与一个 Microsoft Entra 应用程序相关联。 Kubernetes 群集的服务主体可以与任何有效的 Microsoft Entra 应用程序名称(例如 https://www.contoso.org/example)相关联。 应用程序的 URL 不一定是实际的终结点。
  • 指定服务主体 客户端 ID 时,请使用应用程序 ID 的值(appId 对于 Azure CLI 或 ApplicationId Azure PowerShell)。
  • 在 AKS 群集中的代理节点虚拟机(VM)上,服务主体凭据存储在 /etc/kubernetes/azure.json 文件中。
  • 删除使用 az aks create 命令或 New-AzAksCluster cmdlet 创建的 AKS 群集时,不会自动删除创建的服务主体。 请参阅 删除服务主体的步骤
  • 如果使用来自另一 Microsoft Entra 租户的服务主体,则还需围绕部署群集时可用的权限进行更多的考量。 你可能没有读取和写入目录信息的适当权限。 有关详细信息,请参阅 Microsoft Entra 中的默认用户权限是什么?

创建服务主体

  1. 使用“az ad sp create-for-rbac”命令创建服务主体。

    # Set environment variable
    SERVICE_PRINCIPAL_NAME=<your-service-principal-name>
    
    # Create the service principal
    az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME
    

    输出应类似于以下示例输出:

    {
      "appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "displayName": "myAKSClusterServicePrincipal",
      "name": "http://myAKSClusterServicePrincipal",
      "password": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "tenant": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    }
    
  2. 复制创建 AKS 群集时要使用的输出的值appIdpassword

  1. 使用“New-AzADServicePrincipal”命令创建服务主体。

    # Set environment variable
    $SpName = <your-service-principal-name>
    
    # Create the service principal
    New-AzADServicePrincipal -DisplayName $SpName -OutVariable sp
    

    输出应类似于以下示例输出:

    Secret                : System.Security.SecureString
    ServicePrincipalNames : {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, http://myAKSClusterServicePrincipal}
    ApplicationId         : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    ObjectType            : ServicePrincipal
    DisplayName           : myAKSClusterServicePrincipal
    Id                    : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    Type                  :
    

    这些值存储在创建 AKS 群集时使用的变量中。

  2. 使用以下命令,解密存储在“机密”安全字符串中的值。

    $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($sp.Secret)
    [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
    

使用现有服务主体创建 AKS 群集

  • 使用az aks create命令,通过设置--service-principal参数和--client-secret参数为appIdpassword值,创建具有现有服务主体的 AKS 群集。

    # Set environment variables
    RESOURCE_GROUP=<your-resource-group-name>
    CLUSTER_NAME=<your-aks-cluster-name>
    APP_ID=<app-id>
    CLIENT_SECRET=<password-value>
    
    # Create the AKS cluster
    az aks create \
        --resource-group $RESOURCE_GROUP \
        --name $CLUSTER_NAME \
        --service-principal $APP_ID \
        --client-secret $CLIENT_SECRET \
        --generate-ssh-keys
    
  1. 使用以下命令将服务主体 ApplicationIdSecret 转换为“PSCredential”对象。

    $Cred = New-Object -TypeName System.Management.Automation.PSCredential ($sp.ApplicationId, $sp.Secret)
    
  2. 使用 New-AzAksCluster cmdlet 创建具有现有服务主体的 AKS 群集,并使用 ServicePrincipalIdAndSecret 对象指定参数作为其值。

    # Set environment variables
    $ResourceGroupName = <your-resource-group-name>
    $ClusterName = <your-aks-cluster-name>
    
    # Create the AKS cluster
    New-AzAksCluster -ResourceGroupName $ResourceGroupName -Name $ClusterName -ServicePrincipalIdAndSecret $Cred
    

注意

如果使用的是具有自定义机密的现有服务主体,请确保该机密不超过 190 字节。

委托对其他 Azure 资源的访问权限

AKS 群集的服务主体可以用来访问其他资源。 例如,如果要将 AKS 群集部署到现有的 Azure 虚拟网络(VNet)子网,连接到 ACR,或者从群集访问密钥保管库中的密钥或机密,则需要将对这些资源的访问权限委托给服务主体。 若要委派访问权限,请将 Azure 基于角色的访问控制 (Azure RBAC) 角色分配给服务主体。

分配角色时,可以指定角色分配的范围,例如资源组或 VNet 资源。 角色分配决定服务主体对资源拥有哪些权限以及在什么范围内拥有这些权限。

重要

向与群集关联的服务主体授予的权限可能需要 60 分钟才能传播。

创建角色分配

注意

资源的范围必须是完整的资源 ID,例如 /subscriptions/\<guid\>/resourceGroups/myResourceGroup/subscriptions/\<guid\>/resourceGroups/myResourceGroupVnet/providers/Microsoft.Network/virtualNetworks/myVnet

  • 使用 az role assignment create 命令创建角色分配。 指定 --assignee 参数的服务主体应用 ID 的值和 --scope 参数的角色分配范围。 以下示例将访问密钥保管库中机密的权限授予服务主体:

    az role assignment create \
        --assignee <app-id> \
        --scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.KeyVault/vaults/<vault-name>" \
        --role "Key Vault Secrets User"
    
  • 使用 New-AzRoleAssignment cmdlet 创建角色分配。 指定 -ApplicationId 参数的服务主体应用 ID 的值和 -Scope 参数的角色分配范围。 以下示例将访问密钥保管库中机密的权限授予服务主体:

    New-AzRoleAssignment -ApplicationId <app-id> `
        -Scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.KeyVault/vaults/<vault-name>" `
        -RoleDefinitionName "Key Vault Secrets User"
    

授予对 Azure 容器注册表的访问权限

如果使用 Azure 容器注册表 (ACR) 作为容器映像存储,则需要向 AKS 群集的服务主体授予读取和拉取映像的权限。 建议遵循 Azure Kubernetes 服务中的“使用 Azure 容器注册表进行身份验证 ”中的步骤,以便与注册表集成,并为服务主体分配适当的角色。

授予对网络资源的访问权限

如果您使用高级网络功能,并且在不同的资源组中使用 VNet 和子网或者公共 IP 地址,则可以在 VNet 中的子网上分配网络参与者内置角色。 或者,可以创建有权访问该资源组中网络资源的自定义角色。 有关详细信息,请参阅 AKS 服务权限

授予对存储磁盘的访问权限

如果需要访问另一个资源组中的现有磁盘资源,请分配以下角色权限集之一:

  • 创建自定义 角色 并定义 Microsoft.Compute/disks/readMicrosoft.Compute/disks/write 角色权限。
  • 在资源组中分配虚拟机参与者内置角色。

授予对 Azure 容器实例的访问权限

如果使用 Virtual Kubelet 与 AKS 集成,并在与 AKS 群集不同的资源组中运行 Azure 容器实例 (ACI),则需要为 ACI 资源组的 AKS 群集服务主体分配 Contributor 权限。

删除服务主体

  • 查询服务主体的客户端 ID(servicePrincipalProfile.clientId),然后使用带有az ad sp delete参数的--id命令删除该服务主体。 [az aks show][az-aks-show] 命令检索指定 AKS 群集的客户端 ID。

    # Set environment variables
    RESOURCE_GROUP=<your-resource-group-name>
    CLUSTER_NAME=<your-aks-cluster-name>
    
    # Delete the service principal
    az ad sp delete --id $(az aks show \
        --resource-group $RESOURCE_GROUP \
        --name $CLUSTER_NAME \
        --query servicePrincipalProfile.clientId \
        --output tsv)
    
  • 执行查询以获取服务主体客户端 ID(ServicePrincipalProfile.ClientId),然后使用 Remove-AzADServicePrincipal cmdlet 和 -ApplicationId 参数删除服务主体。 [Get-AzAksCluster][get-azakscluster] cmdlet 检索指定 AKS 群集的客户端 ID。

    # Set environment variables
    $ResourceGroupName = <your-resource-group-name>
    $ClusterName = <your-aks-cluster-name>
    $ClientId = (Get-AzAksCluster -ResourceGroupName myResourceGroup -Name myAKSCluster ).ServicePrincipalProfile.ClientId
    
    # Delete the service principal
    Remove-AzADServicePrincipal -ApplicationId $ClientId
    

解决服务主体凭据问题

Azure CLI 会缓存 AKS 群集的服务主体凭据。

Azure PowerShell 会缓存 AKS 群集的服务主体凭据。

如果这些凭据过期,则可能在 AKS 群集部署期间遇到错误。 如果缓存凭据出现问题,可能会收到类似于以下错误消息的错误消息:

Operation failed with status: 'Bad Request'.
Details: The credentials in ServicePrincipalProfile were invalid. Please see https://aka.ms/aks-sp-help for more details.
Details: adal: Refresh request failed. Status Code = '401'.

可以结合使用 az ad app credential list 命令与 "[].endDateTime" 查询,检查服务主体凭据的到期日期。 输出将显示凭据的 endDateTime

az ad app credential list \
    --id <app-id> \
    --query "[].endDateTime" \
    --output tsv
  • 使用 Get-AzADAppCredential cmdlet 检查服务主体凭据的到期日期。 输出将显示凭据的 EndDate
Get-AzADAppCredential -ApplicationId <app-id> 

服务主体凭据的默认过期时间为一年。 如果凭据超过一年,可以重置现有凭据创建新服务主体