在 Azure Kubernetes 服务 (AKS) 上配置跨租户工作负载标识

本文介绍如何在 Azure Kubernetes 服务 (AKS) 上配置跨租户工作负载标识。 跨租户工作负载标识允许从你的 AKS 群集访问另一个租户中的资源。 在此示例中,你在一个租户中创建一个 Azure 服务总线,并从另一个租户的 AKS 群集中运行的工作负载向其发送消息。

有关工作负载标识的详细信息,请参阅工作负载标识概述

先决条件

  • 两个 Azure 订阅,每个订阅位于单独的租户中。 在本文中,我们将它们称为租户 A租户 B

  • 已安装到本地计算机的 Azure CLI。 如果未安装 Azure CLI,请参阅安装 Azure CLI

  • Bash shell 环境。 本文使用 Bash shell 语法。

  • 你需要具有以下订阅详细信息:

    • 租户 A 租户 ID
    • 租户 A 订阅 ID
    • 租户 B 租户 ID
    • 租户 B 订阅 ID

重要

请确保在本文的持续时间内停留在同一终端窗口中,以保留你设置的环境变量。 如果关闭了终端窗口,则需要再次设置环境变量。

在租户 A 中配置资源

租户 A 中,创建启用了工作负载标识和 OIDC 颁发者的 AKS 群集。 使用此群集部署一个尝试访问租户 B 中的资源的应用程序。

登录到租户 A

  1. 使用 az login 命令登录到租户 A 订阅。

    # Set environment variable
    TENANT_A_ID=<tenant-id>
    
    az login --tenant $TENANT_A_ID
    
  2. 确保使用 az account set 命令在租户 A 中使用正确的订阅。

    # Set environment variable
    TENANT_A_SUBSCRIPTION_ID=<subscription-id>
    
    # Log in to your Tenant A subscription
    az account set --subscription $TENANT_A_SUBSCRIPTION_ID
    

在租户 A 中创建资源

  1. 使用 az group create 命令在租户 A 中创建资源组以托管 AKS 群集。

    # Set environment variables
    RESOURCE_GROUP=<resource-group-name>
    LOCATION=<location>
    
    # Create a resource group
    az group create --name $RESOURCE_GROUP --location $LOCATION
    
  2. 使用 az aks create 命令在启用了工作负载标识和 OIDC 颁发者的租户 A 中创建 AKS 群集。

    # Set environment variable
    CLUSTER_NAME=<cluster-name>
    
    # Create an AKS cluster
    az aks create \
      --resource-group $RESOURCE_GROUP \
      --name $CLUSTER_NAME \
      --enable-oidc-issuer \
      --enable-workload-identity \
      --generate-ssh-keys
    

从 AKS 群集获取 OIDC 颁发者 URL

  • 使用 az aks show 命令从租户 A 中的群集获取 OIDC 颁发者 URL。

    OIDC_ISSUER_URL=$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --query "oidcIssuerProfile.issuerUrl" --output tsv)
    

在租户 B 中配置资源

租户 B 中,创建 Azure 服务总线、托管标识并为其分配向服务总线读取和写入消息的权限,并在租户 A 中的托管标识与 AKS 群集之间建立信任。

登录到租户 B

  1. 使用 az logout 命令登出租户 A 订阅。

    az logout
    
  2. 使用 az login 命令登录到租户 B 订阅。

    # Set environment variable
    TENANT_B_ID=<tenant-id>
    
    az login --tenant $TENANT_B_ID
    
  3. 确保使用 az account set 命令在租户 B 中使用正确的订阅。

    # Set environment variable
    TENANT_B_SUBSCRIPTION_ID=<subscription-id>
    
    # Log in to your Tenant B subscription
    az account set --subscription $TENANT_B_SUBSCRIPTION_ID
    

在租户 B 中创建资源

  1. 使用 az group create 命令在租户 B 中创建资源组以承载托管标识。

    # Set environment variables
    RESOURCE_GROUP=<resource-group-name>
    LOCATION=<location>
    
    # Create a resource group
    az group create --name $RESOURCE_GROUP --location $LOCATION
    
  2. 使用 az servicebus namespace createaz servicebus queue create 命令在租户 B 中创建服务总线和队列。

    # Set environment variable
    SERVICEBUS_NAME=sb-crosstenantdemo-$RANDOM
    
    # Create a new service bus namespace and and return the service bus hostname
    SERVICEBUS_HOSTNAME=$(az servicebus namespace create \
      --name $SERVICEBUS_NAME \
      --resource-group $RESOURCE_GROUP \
      --disable-local-auth \
      --query serviceBusEndpoint \
      --output tsv | sed -e 's/https:\/\///' -e 's/:443\///')
    
    # Create a new queue in the service bus namespace
    az servicebus queue create \
      --name myqueue \
      --namespace $SERVICEBUS_NAME \
      --resource-group $RESOURCE_GROUP
    
  3. 使用 az identity create 命令在租户 B 中创建用户分配的托管标识。

    # Set environment variable
    IDENTITY_NAME=${SERVICEBUS_NAME}-identity
    
    # Create a user-assigned managed identity
    az identity create --resource-group $RESOURCE_GROUP --name $IDENTITY_NAME
    

在租户 B 中获取资源 ID 并分配权限

  1. 使用 az identity show 命令获取租户 B 中托管标识的主体 ID。

    # Get the user-assigned managed identity principalId
    PRINCIPAL_ID=$(az identity show \
      --resource-group $RESOURCE_GROUP \
      --name $IDENTITY_NAME \
      --query principalId \
      --output tsv)
    
  2. 使用 az identity show 命令获取租户 B 中托管标识的客户端 ID。

    CLIENT_ID=$(az identity show \
      --resource-group $RESOURCE_GROUP \
      --name $IDENTITY_NAME \
      --query clientId \
      --output tsv)
    
  3. 使用 az servicebus namespace show 命令获取租户 B 中服务总线命名空间的资源 ID。

    SERVICEBUS_ID=$(az servicebus namespace show \
      --name $SERVICEBUS_NAME \
      --resource-group $RESOURCE_GROUP \
      --query id \
      --output tsv)
    
  4. 使用 az role assignment create 命令在租户 B 中分配托管标识以读取和写入服务总线消息。

    az role assignment create \
      --role "Azure Service Bus Data Owner" \
      --assignee-object-id $PRINCIPAL_ID \
      --assignee-principal-type ServicePrincipal \
      --scope $SERVICEBUS_ID
    

在 AKS 群集与托管标识之间建立信任

在本部分中,你将创建在租户 A 中的 AKS 群集与租户 B 中的托管标识之间建立信任所需的联合标识凭据。使用租户 A 中 AKS 群集中的 OIDC 颁发者 URL 和租户 B 中托管标识的名称。

  • 使用 az identity federated-credential create 命令创建联合标识凭据。

    az identity federated-credential create \
      --name $IDENTITY_NAME-$RANDOM \
      --identity-name $IDENTITY_NAME \
      --resource-group $RESOURCE_GROUP \
      --issuer $OIDC_ISSUER_URL \
      --subject system:serviceaccount:default:myserviceaccount
    

--subject system:serviceaccount:default:myserviceaccount 是本文后面你在租户 A 中创建的 Kubernetes 服务帐户的名称。 当应用程序 Pod 发出身份验证请求时,此值将作为授权请求中的 subject 发送到 Microsoft Entra ID。 Microsoft Entra ID 根据此值是否与创建联合标识凭据时设置的信息相匹配来确定资格,因此请务必确保值互相匹配。

部署应用程序以将消息发送到 Azure 服务总线队列

在本部分中,你将应用程序部署到租户 A 中的 AKS 群集,而该应用程序会向租户 B 中的 Azure 服务总线队列发送消息。

登录到租户 A 并获取 AKS 凭据

  1. 使用 az logout 命令登出租户 B 订阅。

    az logout
    
  2. 使用 az login 命令登录到租户 A 订阅。

    az login --tenant $TENANT_A_ID
    
  3. 确保使用 az account set 命令在租户 A 中使用正确的订阅。

    az account set --subscription $TENANT_A_SUBSCRIPTION_ID
    
  4. 使用 az aks get-credentials 命令获取租户 A 中 AKS 群集的凭据。

    az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME
    

创建 Kubernetes 资源以将消息发送给 Azure 服务总线队列

  1. default 命名空间中创建新的 Kubernetes ServiceAccount,并将租户 B 中托管标识的客户端 ID 传递给 kubectl apply 命令。 该客户端 ID 用于向租户 B 中的 Azure 服务总线验证租户 A 中的应用。

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      annotations:
        azure.workload.identity/client-id: $CLIENT_ID
      name: myserviceaccount
    EOF
    
  2. default 命名空间中创建新的 Kubernetes 作业,以将 100 条消息发送到你的 Azure 服务总线队列。 该 Pod 模板已配置为使用你在上一步创建的工作负载标识和服务帐户。 另请注意,AZURE_TENANT_ID 环境变量设置为租户 B 的租户 ID。这是必需的,因为工作负载标识默认为 AKS 群集的租户,因此需要显式设置租户 B 的租户 ID。

    kubectl apply -f - <<EOF
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: myproducer
    spec:
      template:
        metadata:
          labels:
            azure.workload.identity/use: "true"
        spec:
          serviceAccountName: myserviceaccount
          containers:
          - image: ghcr.io/azure-samples/aks-app-samples/servicebusdemo:latest
            name: myproducer
            resources: {}
            env:
            - name: OPERATION_MODE
              value: "producer"
            - name: MESSAGE_COUNT
              value: "100"
            - name: AZURE_SERVICEBUS_QUEUE_NAME
              value: myqueue
            - name: AZURE_SERVICEBUS_HOSTNAME
              value: $SERVICEBUS_HOSTNAME
            - name: AZURE_TENANT_ID
              value: $TENANT_B_ID
          restartPolicy: Never
    EOF
    

验证部署

  1. 使用 kubectl describe pod 命令检查 Pod 的状态,验证 Pod 是否已正确配置为与租户 B 中的 Azure 服务总线队列进行交互。

    # Get the dynamically generated pod name
    POD_NAME=$(kubectl get po --selector job-name=myproducer -o jsonpath='{.items[0].metadata.name}')
    
    # Verify the tenant ID environment variable is set for Tenant B
    kubectl describe pod $POD_NAME | grep AZURE_TENANT_ID
    
  2. 检查 Pod 的日志,查看应用程序是否可以使用 kubectl logs 命令跨租户发送消息。

    kubectl logs $POD_NAME
    

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

    ...
    Adding message to batch: Hello World!
    Adding message to batch: Hello World!
    Adding message to batch: Hello World!
    Sent 100 messages
    

注意

作为额外的验证步骤,你可以转到 Azure 门户 并导航到租户 B 中的 Azure 服务总线队列,以查看 Service Bus Explorer 中发送的消息。

清理资源

验证部署成功后,可以清理资源以避免产生 Azure 成本。

删除租户 A 中的资源

  1. 使用 az login 命令登录到租户 A 订阅。

    az login --tenant $TENANT_A_ID
    
  2. 确保使用 az account set 命令在租户 A 中使用正确的订阅。

    az account set --subscription $TENANT_A_SUBSCRIPTION_ID
    
  3. 使用 az group delete 命令删除 Azure 资源组及其中的所有资源。

    az group delete --name $RESOURCE_GROUP --yes --no-wait
    

删除租户 B 中的资源

  1. 使用 az login 命令登录到租户 B 订阅。

    az login --tenant $TENANT_B_ID
    
  2. 确保使用 az account set 命令在租户 B 中使用正确的订阅。

    az account set --subscription $TENANT_B_SUBSCRIPTION_ID
    
  3. 使用 az group delete 命令删除 Azure 资源组及其中的所有资源。

    az group delete --name $RESOURCE_GROUP --yes --no-wait
    

后续步骤

本文介绍了如何在 Azure Kubernetes 服务 (AKS) 上配置跨租户工作负载标识。 若要了解有关工作负载标识的详细信息,请参阅以下文章: