在已启用 Azure Arc 的 Kubernetes 中部署和配置工作负载身份联合

可以使用 Azure CLI 在已启用 Azure Arc 的 Kubernetes 群集上启用 工作负荷标识功能 。 此过程遵循以下高级步骤:

  1. 在已启用 Arc 的新或现有 Kubernetes 群集上启用工作负荷标识功能。
  2. 创建托管标识(或应用注册)和 Kubernetes 服务帐户。
  3. 配置托管标识以进行令牌联合身份验证。
  4. 配置服务帐户注释和应用程序 Pod 标签以使用工作负载标识。
  5. 在 Kubernetes 群集上配置工作负荷标识设置。
  6. 在群集上禁用工作负荷标识。

有关此功能的概述,请参阅 Azure Arc 启用的 Kubernetes 中的工作负载身份联合

小窍门

本文介绍在已启用 Arc 的 Kubernetes 群集上部署和配置工作负荷标识所需的步骤。 若要了解如何在其他类型的群集上启用工作负荷标识,请参阅以下文章:

先决条件

  • 启用 Azure Arc 的 Kubernetes 群集的工作负载标识支持以下 Kubernetes 发行版:

    • 运行 K3s 的 Ubuntu Linux 群集
    • Azure Arc 启用的 AKS
    • 红帽 OpenShift
    • VMware Tanzu TKGm
    • Edge Essentials 上的 AKS

若要使用工作负荷标识功能,必须具有 Azure CLI 2.64 或更高版本,以及 az connectedk8s 版本 1.10.0 或更高版本。 请先更新 Azure CLI 版本,然后再更新 az connectedk8s 版本。

在群集上启用工作负荷标识

按照相应的步骤为已启用 Arc 的新 Kubernetes 群集或现有群集启用工作负荷标识功能。 在这两种情况下,请将名称和资源组替换为值,并根据需要配置参数。

参数 DESCRIPTION 必选
--enable-oidc-issuer 生成并托管 OIDC 颁发者 URL,这是一个可公开访问的 URL,它允许 API 服务器查找用于验证令牌的公共签名密钥。  必选
--enable-workload-identity 安装一个变更准入 Webhook,该 Webhook 将签名的服务帐户令牌投影到已知路径,并根据带批注的服务帐户的设置,将身份验证相关的环境变量注入到应用程序 Pod。 对于新群集,如果不启用此参数,则必须在知名路径上装载投射卷,以便在该路径上公开已签名的服务帐户令牌。 可选

设置环境变量。

为方便起见,本文中的示例引用了以下部分中定义的环境变量。 将这些值替换为你自己的值:

export RESOURCE_GROUP="myRG"
export LOCATION="chinaeast2"
export CLUSTER_NAME="mycluster"
export SERVICE_ACCOUNT_NAMESPACE="myKubernetesnamespace"
export SERVICE_ACCOUNT_NAME="mysa"
export SUBSCRIPTION="$(az account show --query id --output tsv)"
export USER_ASSIGNED_IDENTITY_NAME="myIdentity"
export FEDERATED_IDENTITY_CREDENTIAL_NAME="myFedIdentity"

若要创建启用了工作负荷标识的已启用 Azure Arc 的群集,请使用以下命令:

az connectedk8s connect --name "${CLUSTER_NAME}" --resource-group "${RESOURCE_GROUP}" --enable-oidc-issuer --enable-workload-identity

若要在已启用 Arc 的现有 Kubernetes 群集上启用工作负荷标识,请使用 update 该命令。

az connectedk8s update --name "${CLUSTER_NAME}" --resource-group "${RESOURCE_GROUP}" --enable-oidc-issuer --enable-workload-identity

检索 OIDC 颁发者 URL

提取 OIDC 颁发者 URL 并将其保存到环境变量。 在以下步骤中使用此颁发者 URL。

export OIDC_ISSUER="$(az connectedk8s show --name "${CLUSTER_NAME}" --resource-group "${RESOURCE_GROUP}" \ 
    --query "oidcIssuerProfile.issuerUrl" \  
    --output tsv)"

若要查看环境变量,请输入 echo ${OIDC_ISSUER}。 环境变量应包含类似于以下示例的证书颁发者 URL:

https://northamerica.oic.prod-arc.azure.com/00000000-0000-0000-0000-000000000000/12345678-1234-1234-1234-123456789123/

默认情况下,颁发者使用基 URL https://{region}.oic.prod-arc.azure.com/{tenant_id}/{uuid},其中 {region} 的值与你创建 Arc 启用的 Kubernetes 集群的位置匹配。 该值 {uuid} 表示 OpenID Connect (OIDC) 键,该键是一个不可变的随机生成的 GUID,用于每个群集。

创建托管标识

使用 az identity create 命令创建用户分配的托管标识。 通过使用工作负荷标识,可以在用户分配的托管标识的令牌与 Kubernetes 群集的服务帐户令牌之间建立信任关系。

az identity create \ 
    --name "${USER_ASSIGNED_IDENTITY_NAME}" \
    --resource-group "${RESOURCE_GROUP}" \
    --location "${LOCATION}" \
    --subscription "${SUBSCRIPTION}"

提取托管标识的客户端 ID 并将其存储在环境变量中。

export USER_ASSIGNED_CLIENT_ID="$(az identity show \ 
    --resource-group "${RESOURCE_GROUP}" \
    --name "${USER_ASSIGNED_IDENTITY_NAME}" \
    --query 'clientId' \
    --output tsv)"

创建 Kubernetes 服务帐户

创建 Kubernetes 服务帐户,并使用在上一步中创建的托管标识的客户端 ID 对其进行批注。 在两者之间建立信任关系后,与 Kubernetes 服务帐户关联的已签名令牌将交换为Microsoft Entra ID令牌。

应用以下 YAML 代码片段以创建添加工作负荷标识注释的服务帐户。

apiVersion: v1 
kind: ServiceAccount 
metadata: 
  annotations: 
    azure.workload.identity/client-id: "${USER_ASSIGNED_CLIENT_ID}" 
  name: "${SERVICE_ACCOUNT_NAME}" 
  namespace: "${SERVICE_ACCOUNT_NAMESPACE}" 

创建联合标识凭据

使用 az identity federated-credential create 命令在托管标识、服务帐户颁发者和使用者之间创建联合标识凭据。 此步骤建立 Kubernetes 群集与用于交换令牌的 Microsoft Entra 之间的信任关系。 有关 Microsoft Entra 中联合标识凭据的详细信息,请参阅 Microsoft Entra ID 中的联合标识凭据概述

az identity federated-credential create \ 
    --name ${FEDERATED_IDENTITY_CREDENTIAL_NAME} \ 
    --identity-name "${USER_ASSIGNED_IDENTITY_NAME}" \ 
    --resource-group "${RESOURCE_GROUP}" \ 
    --issuer "${OIDC_ISSUER}" \ 
    --subject system:serviceaccount:"${SERVICE_ACCOUNT_NAMESPACE}":"${SERVICE_ACCOUNT_NAME}" \ 
    --audience api://AzureADTokenExchange 

注释

添加联合标识凭据后,传播需要几秒钟时间。 如果在添加联合标识凭据后立即发出令牌请求,则在刷新缓存之前,请求可能会失败。 若要避免此问题,请在添加联合标识凭据后在脚本中添加轻微延迟。

配置服务帐户注释和 Pod 标签

以下服务帐户和 Pod 注释可用于根据应用程序要求配置工作负载标识。 如果您将 --enable-workload-identity 设置为 true,则以下部分中指定的容器组标签是必需的。

服务帐户批注

所有服务帐户注释都是可选的。 如果未指定批注,则使用默认值。

注释 DESCRIPTION 违约
azure.workload.identity/client-id 用于 Pod 的 Microsoft Entra 应用程序客户端 ID。
azure.workload.identity/tenant-id 注册 Microsoft Entra 应用程序的 Azure 租户 ID。 AZURE_TENANT_IDazure-wi-webhook-config ConfigMap 中提取的环境变量。
azure.workload.identity/service-account-token-expiration 投影服务帐户令牌的 expirationSeconds 字段。 配置以防止服务帐户令牌刷新期间出现错误导致的停机。 Kubernetes 服务帐户令牌过期时间与 Microsoft Entra 令牌无关。 Microsoft Entra 令牌在颁发后 24 小时过期。 3600 (支持的范围为 3600-86400)

Pod 标签

标签 DESCRIPTION 建议的值 必选
azure.workload.identity/use 在 Pod 模板规范中是必需的。如果将 --enable-workload-identity 设置为 true,变更准入 Webhook 仅将 Azure 特定的环境变量和投影的服务帐户令牌卷添加到带有此标签的 Pod。 true 是的

Pod 注释

所有 Pod 标注都是可选的。 如果未指定批注,则使用默认值。

注释 DESCRIPTION 违约
azure.workload.identity/service-account-token-expiration 投影服务帐户令牌的 expirationSeconds 字段。 配置以防止服务帐户令牌刷新期间出现错误导致的停机。 Kubernetes 服务帐户令牌过期时间与 Microsoft Entra 令牌无关。 Microsoft Entra 令牌在颁发后 24 小时过期。 3600 (支持的范围为 3600-86400)
azure.workload.identity/skip-containers 表示用于跳过添加投影服务账户令牌卷的容器的以分号分隔的列表。 例如: container1;container2 默认情况下,如果为 Pod 打上 azure.workload.identity/use: true 标签,则投影的服务帐户令牌卷将添加到所有容器。

在 Kubernetes 群集上配置工作负荷标识设置

需要将 Kubernetes 群集上的 API 服务器配置为颁发包含可公开访问的 OIDC 颁发者 URL 的服务帐户令牌(以便 Entra 知道在何处查找用于验证令牌的公钥)。

若要在各种 Kubernetes 分发版上配置工作负荷标识设置,请按照以下步骤完成配置。

K3s 群集

  1. 创建 k3s 配置文件。

  2. 编辑 /etc/rancher/k3s/config.yaml 以添加以下设置:

       kube-apiserver-arg:  
         - "service-account-issuer=${OIDC_ISSUER}"
         - "service-account-max-token-expiration=24h"
    
  3. 保存 config.yaml。

  4. 通过运行 systemctl restart k3s 来重启 k3s API 服务器。

    经常轮换服务帐户密钥。 了解更多信息,请参阅 在 K3s 集群上旋转服务帐户签名密钥

Red Hat OpenShift 群集

  1. 编辑群集的身份验证配置:

    1. 打开群集的身份验证配置:

      kubectl edit authentications cluster
      
    2. 找到关于发行者值的部分并更新。

    3. 保存文件并退出编辑器。

  2. 在所需的命名空间中重启相关部署:

    kubectl rollout restart deployment -n azure-arc
    kubectl rollout restart deployment -n arc-workload-identity
    
  3. 或者,通过补丁命令应用更改以在不手动编辑的情况下更新颁发者值:

    kubectl patch authentication cluster \ 
    --type merge \ 
    -p '{"spec":{"serviceAccountIssuer":"<NEW_ISSUER_VALUE>"}}' \ 
    --kubeconfig /etc/kubernetes/admin.conf
    
  4. 确认更改:

    1. 验证发行者值:

      kubectl get authentications cluster
      
    2. 检查重启的部署的状态:

      kubectl get pods -n azure-arc
      kubectl get pods -n arc-workload-identity 
      

VMware Tanzu TKGm 群集

  1. 将群集连接到启用工作负载身份验证的 Azure Arc。

    1. 在 Arc 连接过程中启用工作负荷标识。
    2. 连接后,检索 OIDC 颁发者 URL。
  2. 编辑工作负荷群集配置:

    1. 将上下文切换到管理群集:

      kubectl config use-context mgmt-cluster-admin@mgmt-cluster 
      
    2. 查看群集:

      kubectl get cluster
      
    3. 编辑目标群集配置:

      1. 搜索 apiServerExtraArgs
      2. 如果存在该值,请将其更新为包含颁发者 URL。
      3. 如果不存在,请按如下所示将其添加到以下位置 spec:topology:variables
      name: apiServerExtraArgs
      value:
        - 'service-account-issuer=<OIDC_ISSUER_URL>'
      
  3. 将上下文切换回工作负荷群集:

    kubectl config use-context <WORKLOAD_CLUSTER_CONTEXT>
    
  4. 创建服务帐户和测试令牌:

    1. 为服务帐户创建令牌:

      kubectl create token <SERVICE_ACCOUNT_NAME> -n <NAMESPACE>
      
    2. 验证令牌颁发者是否与预期的 OIDC URL 匹配。

  5. 重启部署以应用更改:

    kubectl rollout restart deployment -n azure-arc
    

在 K3s 集群上轮换服务帐户签名密钥

对于借助工作负荷身份联合而加入到 Azure Arc 的 K3s 群集,轮换服务帐户颁发者密钥是一项重要的安全操作。 密钥轮换是安全卫生所必需的,可能需要作为事件修正的一部分。

服务帐户颁发者密钥 (service.key) 是用于对服务帐户令牌进行签名的 RSA 私钥。 轮换密钥时,请将旧密钥保留在文件中,使现有令牌保持有效。 这两个密钥都应共存,直到所有现有令牌过期或刷新(至少 24 小时)。

最佳做法是,应 每隔三个月至少轮换一次服务帐户颁发者密钥。

先决条件

若要轮换 K3s 群集上的服务帐户颁发者密钥,请确保满足以下先决条件:

  • 载入到启用了工作负荷身份联合认证的 Azure Arc 的 K3s 群集
  • sudo K3s 服务器节点上的 root 访问权限
  • 节点上安装的 OpenSSL 3
  • 熟悉 K3s 证书 CLI

生成新密钥并执行轮换

在 K3s 服务器节点上运行以下命令,生成新的密钥并将其暂存以供轮换:

# Create a temporary directory for staging
mkdir -p /opt/k3s/server/tls

# Check OpenSSL version (OpenSSL 3.x requires -traditional flag)
openssl version | grep -qF 'OpenSSL 3' && OPENSSL_GENRSA_FLAGS=-traditional

# Generate a new RSA key
openssl genrsa ${OPENSSL_GENRSA_FLAGS:-} -out /opt/k3s/server/tls/service.key 2048

# Append the existing (old) key to preserve validity of current tokens
cat /var/lib/rancher/k3s/server/tls/service.key >> /opt/k3s/server/tls/service.key

# Load the updated key into the K3s datastore
k3s certificate rotate-ca --path=/opt/k3s/server

# Restart K3s to apply
sudo systemctl restart k3s

Important

请勿直接覆盖当前正在使用的数据 /var/lib/rancher/k3s/server/tls。 始终将更新文件添加到一个单独的目录中,例如 /opt/k3s/server/tls

重启后:

  • 使用新密钥来铸造新令牌。
  • 现有令牌保持有效,因为旧密钥仍在文件中。

有关轮换服务帐户颁发者密钥的更多详细信息,请参阅 K3s 文档中 Service-Account 颁发者密钥轮换

删除旧的服务帐户颁发者密钥

Important

为了确保使用旧服务帐户颁发者密钥签名的所有现有令牌都过期或刷新,请在删除旧密钥之前至少等待 24 小时。

在 K3s 服务器节点上运行以下命令,安全地删除旧密钥:

# Backup the current key file
sudo cp /var/lib/rancher/k3s/server/tls/service.key /var/lib/rancher/k3s/server/tls/service.key.bak.$(date +%s)

# Split the keys into individual files
csplit -f /tmp/service-key- /var/lib/rancher/k3s/server/tls/service.key '/BEGIN RSA PRIVATE KEY/' '{*}'

# Copy only the new key (first key in the file) to staging
sudo cp /tmp/service-key-01 /opt/k3s/server/tls/service.key

# Load the updated key into the datastore
k3s certificate rotate-ca --path=/opt/k3s/server

# Restart K3s
sudo systemctl restart k3s

禁用工作负载标识

若要在启用了Azure Arc的 Kubernetes 群集上禁用工作负荷标识功能,请运行以下命令:

az connectedk8s update \
    --resource-group "${RESOURCE_GROUP}" \
    --name "${CLUSTER_NAME}" \
    --disable-workload-identity

后续步骤