在 Azure Arc 群集启用的 AKS 上部署和配置工作负荷标识(预览版)

适用于:Azure 本地版本 23H2

工作负载标识联合允许在 Microsoft Entra ID 中配置用户分配的托管标识或应用注册,以信任来自外部标识提供者(IdP)(例如 Kubernetes)的令牌,从而访问受 Microsoft Entra 保护的资源,例如 Azure 密钥库 或 Azure Blob 存储。

Azure Arc 启用Azure Kubernetes 服务(AKS)是一种托管的 Kubernetes 服务,可用于轻松部署已启用工作负荷标识的 Kubernetes 群集。 本文介绍如何执行以下任务:

  • 创建启用了工作负荷标识的 AKS Arc 群集(预览版)。
  • 创建 Kubernetes 服务帐户并将其绑定到 Azure 托管标识。
  • 在托管标识上创建联合凭据,以信任 OIDC 颁发者。
  • 部署应用程序。
  • 示例:向群集中的 Pod 授予对 Azure 密钥保管库中机密的访问权限。

重要

这些预览功能在自助服务上可用,可选择加入。 预览功能是“按现状”和“按可用”提供的,不包括在服务级别协议和有限保证中。 Azure Kubernetes 服务,由 Azure Arc 预览版启用,部分由客户支持人员尽最大努力涵盖。

注意

在公共预览版中,Azure Stack HCI 上的 AKS 支持在 AKS 群集创建期间启用工作负荷标识。 但是,群集创建或禁用工作负荷标识后,当前不受支持。

先决条件

在部署启用了 Azure Arc 的 Kubernetes 群集之前,必须满足以下先决条件:

  • 如果没有 Azure 订阅,请在开始之前创建一个 Azure 免费帐户
  • 本文需要 Azure CLI 1.4.23 或更高版本。 如果你使用的是 Azure Cloud Shell,则表示已安装最新版本。

导出环境变量

为了帮助简化配置所需标识的步骤,以下命令定义本文示例中引用的环境变量。 将以下值替换为你自己的值:

$AZSubscriptionID = "00000000-0000-0000-0000-000000000000" 
$Location = "westeurope" 
$resource_group_name = "myResourceGroup" 

$aks_cluster_name = "myAKSCluster" 

$SERVICE_ACCOUNT_NAMESPACE = "default" 
$SERVICE_ACCOUNT_NAME = "workload-identity-sa" 

$FedIdCredentialName = "myFedIdentity" 
$MSIName = "myIdentity" 

# To access key vault secrets from a pod in the cluster, include these variables:
$KVName = "KV-workload-id" 
$KVSecretName= "KV-secret"

设置活动订阅

首先,将订阅设置为当前活动订阅。 使用 订阅 ID 运行 az account set 命令:

az login  
az account set -s $AZSubscriptionID

创建资源组

Azure 资源组是用于部署和管理 Azure 资源的逻辑组。 创建资源组时,系统会提示你指定一个位置。 此位置是资源组元数据的存储位置,也是资源在 Azure 中运行的位置(如果你在创建资源期间未指定其他区域)。

若要创建资源组,请运行 az group create 命令:

az group create --name $resource_group_name --location $Location

以下示例输出显示成功创建资源组:

{ 
  "id": "/subscriptions/<guid>/resourceGroups/myResourceGroup", 
  "location": "westeurope", 
  "managedBy": null, 
  "name": "$resource_group_name", 
  "properties": { 
    "provisioningState": "Succeeded" 
  }, 
  "tags": null 
}

步骤 1:创建启用了工作负荷标识的 AKS Arc 群集

若要创建 AKS Arc 群集,需要这 $customlocation_ID 两个值和 $logicnet_Id 值。

  • $customlocation_ID:自定义位置的 Azure 资源管理器 ID。 自定义位置是在 Azure Stack HCI 群集部署期间配置的。 基础结构管理员应提供自定义位置资源管理器 ID。 如果基础结构管理员提供自定义位置名称和资源组名称,还可以使用 $customlocation_ID = $(az customlocation show --name "<your-custom-location-name>" --resource-group $resource_group_name --query "id" -o tsv) 获取资源管理器 ID。
  • $logicnet_Id:执行以下步骤创建的 Azure 本地逻辑网络的 Azure 资源管理器 ID。 基础结构管理员应提供逻辑网络的资源管理器 ID。 如果基础结构管理员提供逻辑网络名称和资源组名称,还可以使用 $logicnet_Id = $(az stack-hci-vm network lnet show --name "<your-lnet-name>" --resource-group $resource_group_name --query "id" -o tsv) 获取资源管理器 ID。

使用--enable-oidc-issuer --enable-workload-identity参数运行 az aksarc create 命令。 提供 entra-admin-group-object-ids,并确保你是代理模式访问的 Microsoft Entra ID 管理员组的成员:

az aksarc create  
-n $aks_cluster_name -g $resource_group_name  
--custom-location $customlocation_ID --vnet-ids $logicnet_Id  
--aad-admin-group-object-ids <entra-admin-group-object-ids> 
--generate-ssh-keys  
--enable-oidc-issuer --enable-workload-identity

片刻之后,该命令将会完成,并返回有关群集的 JSON 格式信息。

成功创建预配的群集后,可能需要一些时间来部署工作负荷标识扩展。 使用以下命令检查工作负荷标识扩展状态:

az connectedk8s show -n $aks_cluster_name -g $resource_group_name
# agentState = "Succeeded" 
"agentPublicKeyCertificate": "", 
  "agentVersion": "1.21.10", 
  "arcAgentProfile": { 
    "agentAutoUpgrade": "Enabled", 
    "agentErrors": [], 
    "agentState": "Succeeded", 
    "desiredAgentVersion": "", 
    "systemComponents": null 

# oidcIssuerProfile "enabled": true and "issuerUrl" present 

"oidcIssuerProfile": { 
    "enabled": true, 
    "issuerUrl": "https://oidcdiscovery-{location}-endpoint-1111111111111111.000.azurefd.net/00000000-0000-0000-0000-000000000000/11111111-1111-1111-1111-111111111111/"}

在Azure 门户中,可以在 Kubernetes 群集的“属性”部分下查看 wiextension 扩展。

重要

作为 AKS Arc 群集的安全增强的一部分,工作负荷标识启用会触发两项更改。 首先,Kubernetes 服务帐户签名密钥每 45 天自动轮换一次,有效期为 90 天。 其次, --service-account-extend-token-expiration 标志处于禁用状态,将令牌有效性从一年减少到最多 24 小时。

将 OIDC 颁发者 URL 保存到环境变量

成功创建 AKS 群集后,可以获取 OIDC 颁发者 URL 并将其保存到环境变量。 运行下面的命令:

$SERVICE_ACCOUNT_ISSUER =$(az connectedk8s show --n $aks_cluster_name --resource-group $resource_group_name --query "oidcIssuerProfile.issuerUrl" --output tsv)

步骤 2:创建 Kubernetes 服务帐户并将其绑定到 Azure 托管标识

首先,创建托管标识。 运行 az identity create 命令:

az identity create --name $MSIName --resource-group $resource_group_name --location $Location --subscription $AZSubscriptionID

接下来,为托管标识的客户端 ID 创建变量:

$MSIId=$(az identity show --resource-group $resource_group_name --name $MSIName --query 'clientId' --output tsv)
$MSIPrincipalId=$(az identity show --resource-group $resource_group_name --name $MSIName --query 'principalId' --output tsv)

创建 Kubernetes 服务帐户

创建 Kubernetes 服务帐户,并使用在上一步中创建的托管标识的客户端 ID 对其进行批注:

az connectedk8s proxy -n $aks_cluster_name -g $resource_group_name

打开新 窗口。 复制并粘贴以下 CLI 命令:

$yaml = @" apiVersion: v1 kind: ServiceAccount metadata: annotations: azure.workload.identity/client-id: $MSIId name: $SERVICE_ACCOUNT_NAME namespace: $SERVICE_ACCOUNT_NAMESPACE "@ $yaml = $yaml -replace '\$MSIId', $MSIId ` -replace '\$SERVICE_ACCOUNT_NAME', $SERVICE_ACCOUNT_NAME ` -replace '\$SERVICE_ACCOUNT_NAMESPACE', $SERVICE_ACCOUNT_NAMESPACE $yaml | kubectl apply -f -

以下输出显示成功创建服务帐户:

serviceaccount/workload-identity-sa created

步骤 3:在托管标识上创建联合凭据以信任 OIDC 颁发者

首先,创建联合标识凭据。 调用 az identity federated-credential create 命令在托管标识、服务帐户颁发者和使用者之间创建联合标识凭据。 有关 Microsoft Entra 中联合标识凭据的详细信息,请参阅 Microsoft Entra ID 中的联合标识凭据概述

# Create a federated credential 

az identity federated-credential create --name $FedIdCredentialName --identity-name $MSIName --resource-group $resource_group_name --issuer $SERVICE_ACCOUNT_ISSUER --subject "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}" 

# Show the federated credential 

az identity federated-credential show --name $FedIdCredentialName --resource-group $resource_group_name --identity-name $MSIName

注意

添加联合标识凭据后,传播需要几秒钟时间。 缓存刷新之前,立即发出的令牌请求可能会失败。 若要防止此问题,请考虑在创建联合标识凭据后添加短暂延迟。

步骤 4:部署应用程序

部署应用程序 Pod 时,清单应引用在创建 Kubernetes 服务帐户步骤中创建的服务帐户。 以下清单演示如何引用帐户,特别是帐户 metadata\namespacespec\serviceAccountName 属性。 请确保为 image 指定映像,并为 containerName 指定容器名称:

$image = "<image>"  # Replace <image> with the actual image name 
$containerName = "<containerName>"  # Replace <containerName> with the actual container name 

$yaml = @" 
apiVersion: v1 
kind: Pod 
metadata: 
  name: sample-quick-start 
  namespace: $SERVICE_ACCOUNT_NAMESPACE 
  labels: 
    azure.workload.identity/use: "true" # Required. Only pods with this label can use workload identity. 
spec: 
  serviceAccountName: $SERVICE_ACCOUNT_NAME 
  containers: 
    - image: $image 
      name: $containerName 
"@ 

# Replace variables within the YAML content 
$yaml = $yaml -replace '\$SERVICE_ACCOUNT_NAMESPACE', $SERVICE_ACCOUNT_NAMESPACE ` 
                -replace '\$SERVICE_ACCOUNT_NAME', $SERVICE_ACCOUNT_NAME 

# Apply the YAML configuration 
$yaml | kubectl apply -f - 

重要

确保使用工作负荷标识的应用程序 Pod 在 Pod 规范中包含标签 azure.workload.identity/use: "true" 。否则,Pod 在重启后会失败。

示例:授予访问 Azure 密钥库的权限

此步骤中的说明介绍如何从 Pod 访问 Azure 密钥保管库中的机密、密钥或证书。 本部分中的示例为工作负载标识配置对密钥保管库中机密的访问权限,但你可以执行类似的步骤来配置对密钥或证书的访问权限。

以下示例演示如何使用 Azure 基于角色的访问控制 (Azure RBAC) 权限模型向 Pod 授予访问密钥保管库的权限。 有关 Azure Key Vault 的 Azure RBAC 权限模型的详细信息,请参阅使用 Azure RBAC 授予应用程序访问 Azure Key Vault 的权限

  1. 创建启用了清除保护功能和 RBAC 授权的新密钥保管库。 如果为清除保护功能和 RBAC 授权配置了现有密钥保管库,也可以使用它:

    az keyvault create --name $KVName --resource-group $resource_group_name --location $Location --enable-purge-protection --enable-rbac-authorization
    
    # retrieve the key vault ID for role assignment
    $KVId=$(az keyvault show --resource-group $resource_group_name --name $KVName --query id --output tsv)
    
  2. 将 RBAC 密钥库 Secrets Officer 角色分配给自己,以便可以在新的密钥保管库中创建机密。 新角色分配可能需要最多 5 分钟完成传播并由授权服务器更新。

    az role assignment create --assignee-object-id $MSIPrincipalId --role "Key Vault Secrets Officer" --scope $KVId --assignee-principal-type ServicePrincipal
    
  3. 在密钥保管库中创建机密:

    az keyvault secret set --vault-name $KVName --name $KVSecretName --value "Hello!"
    
  4. 密钥保管库机密用户角色分配给之前创建的用户分配的托管标识。 此步骤授予托管标识从密钥保管库读取机密的权限:

    az role assignment create --assignee-object-id $MSIPrincipalId --role "Key Vault Secrets User" --scope $KVId --assignee-principal-type ServicePrincipal
    
  5. 为密钥保管库 URL 创建环境变量:

    $KVUrl=$(az keyvault show --resource-group $resource_group_name --name $KVName --query properties.vaultUri --output tsv)
    
  6. 部署引用上服务帐户和密钥保管库 URL 的 Pod:

    $yaml = @" 
    apiVersion: v1 
    kind: Pod 
    metadata: 
      name: sample-quick-start 
      namespace: $SERVICE_ACCOUNT_NAMESPACE 
      labels: 
        azure.workload.identity/use: "true" 
    spec: 
      serviceAccountName: $SERVICE_ACCOUNT_NAME 
      containers: 
        - image: ghcr.io/azure/azure-workload-identity/msal-go 
          name: oidc 
          env: 
          - name: KEYVAULT_URL 
            value: $KVUrl 
          - name: SECRET_NAME 
            value: $KVSecretName 
      nodeSelector: 
        kubernetes.io/os: linux 
    "@ 
    
    # Replace variables within the YAML content 
    $yaml = $yaml -replace '\$SERVICE_ACCOUNT_NAMESPACE', $SERVICE_ACCOUNT_NAMESPACE ` 
                    -replace '\$SERVICE_ACCOUNT_NAME', $SERVICE_ACCOUNT_NAME ` 
                    -replace '\$KVUrl', $KVUrl ` 
                    -replace '\$KVSecretName', $KVSecretName 
    
    # Apply the YAML configuration 
    $yaml | kubectl --kubeconfig $aks_cluster_name apply -f -
    

后续步骤

在本文中,你部署了 Kubernetes 群集并将其配置为使用工作负荷标识,为应用程序工作负荷使用该凭据进行身份验证做好准备。 现在,你已准备好部署应用程序并将其配置为将工作负荷标识与最新版 Azure 标识客户端库配合使用。