Claude Platform Docs
管理身份提供商

在 Kubernetes 中使用 WIF

使用投射的服务账户令牌,从自管理的 Kubernetes 集群向 Claude API 进行身份验证。

自管理的 Kubernetes 集群(kubeadm、k3s、OpenShift 以及本地部署发行版)通过 projected service account tokens(投射的服务账户令牌)为每个 pod 签发 OIDC "JSON Web Token"(JSON Web 令牌),即 JWT。集群的 API 服务器充当 OIDC issuer(颁发者),每个令牌的 sub 声明遵循 system:serviceaccount:<namespace>:<service-account> 的形式。您可以通过读取集群的发现文档来找到集群的颁发者 URL:

cURL
kubectl get --raw /.well-known/openid-configuration | jq -r .issuer

前提条件

  • 熟悉 WIF 概念:服务账户、联合颁发者和联合规则。
  • 一个在 API 服务器上配置了 --service-account-issuer 标志的 Kubernetes 集群。大多数发行版默认会设置此项;kubeadm 集群通常使用 https://kubernetes.default.svc.cluster.local。如果您无法直接访问 API 服务器配置,您的平台团队可以确认该值。
  • 满足以下条件之一,以便 Anthropic 能够验证令牌签名:
    • 颁发者的 JWKS 端点可通过 HTTPS 在 443 端口从公共互联网访问,或者
    • 您可以从集群内部获取 JWKS 并以 inline 模式注册它(在配置 Anthropic 中介绍)。
  • 拥有在 Claude Console 中为您的 Anthropic 组织创建服务账户、联合颁发者和联合规则的权限。

配置 Kubernetes

将服务账户令牌投射到您的 pod 中,并使用您的联合规则所期望的受众和生命周期。serviceAccountToken 投射会将一个新的 JWT 写入挂载路径,并在 expirationSeconds 到期之前对其进行轮换。

Pod
apiVersion: v1
kind: Pod
metadata:
  name: inference-worker
  namespace: inference
spec:
  serviceAccountName: inference-worker
  volumes:
    - name: anthropic-token
      projected:
        sources:
          - serviceAccountToken:
              audience: https://api.anthropic.com
              expirationSeconds: 3600
              path: token
  containers:
    - name: app
      image: your-registry/inference-worker:latest
      env:
        - name: ANTHROPIC_IDENTITY_TOKEN_FILE
          value: /var/run/secrets/anthropic.com/token
        - name: ANTHROPIC_FEDERATION_RULE_ID
          value: fdrl_...
        - name: ANTHROPIC_ORGANIZATION_ID
          value: 00000000-0000-0000-0000-000000000000
        - name: ANTHROPIC_SERVICE_ACCOUNT_ID
          value: svac_...
        - name: ANTHROPIC_WORKSPACE_ID  # required when the rule covers multiple workspaces
          value: wrkspc_...
      volumeMounts:
        - name: anthropic-token
          mountPath: /var/run/secrets/anthropic.com
          readOnly: true

为此 pod 签发的令牌携带 sub: "system:serviceaccount:inference:inference-worker"aud: ["https://api.anthropic.com"]

配置 Anthropic

在 Claude Console 中,打开 Settings → Workload identity,点击 Connect workload,然后选择 Kubernetes 磁贴。向导会引导您完成注册颁发者、创建服务账户以及创建联合规则的步骤。

向导会为您创建这些资源。无论您是在向导中输入这些值,还是将它们发送到 Admin API,都请使用以下值:

联合颁发者: 许多自管理集群使用诸如 https://kubernetes.default.svc.cluster.local 之类无法从公共互联网访问的颁发者 URL。如果您的集群属于这种情况,请选择 inline JWKS 来源并粘贴集群的密钥。从集群内部获取它们:

cURL
kubectl get --raw /openid/v1/jwks

然后使用返回的 keys 数组的内容(而不是外层的 {"keys": [...]} 包装)来配置颁发者:

{
  "name": "onprem-k8s",
  "issuer_url": "https://kubernetes.default.svc.cluster.local",
  "jwks": {
    "type": "inline",
    "keys": [{ "kty": "RSA", "kid": "...", "n": "...", "e": "AQAB" }]
  }
}

inline 模式下,issuer_url 仅用于与 JWT 的 iss 声明进行比较;Anthropic 从不尝试访问它。如果您的颁发者可公开访问,请改用 "jwks": {"type": "discovery"}

联合规则: 匹配服务账户的 sub 声明以及您在投射令牌上设置的受众。

{
  "name": "onprem-inference",
  "issuer_id": "fdis_...",
  "match": {
    "subject_prefix": "system:serviceaccount:inference:inference-worker",
    "audience": "https://api.anthropic.com"
  },
  "target": {
    "type": "service_account",
    "service_account_id": "svac_..."
  },
  "workspace_id": "wrkspc_...",
  "oauth_scope": "workspace:developer",
  "token_lifetime_seconds": 600
}

请在工作负载允许的范围内尽可能具体。仅当命名空间中的每个服务账户都应映射到同一个 Anthropic 服务账户时,才将 subject_prefix 放宽为 system:serviceaccount:inference:*(末尾的 * 使其成为前缀匹配)。将规则的 fdrl_... ID 添加到您 pod 的 ANTHROPIC_FEDERATION_RULE_ID 环境变量中。

获取并使用令牌

配置 Kubernetes 中的 pod 规约将 ANTHROPIC_IDENTITY_TOKEN_FILE 设置为投射的挂载路径,同时还设置了 ANTHROPIC_FEDERATION_RULE_IDANTHROPIC_ORGANIZATION_IDANTHROPIC_SERVICE_ACCOUNT_IDANTHROPIC_WORKSPACE_ID。有了这些设置,SDK 会在每次交换时从磁盘读取令牌,并自动刷新 Anthropic 访问令牌。

import anthropic

# 从 pod 的环境中读取 ANTHROPIC_IDENTITY_TOKEN_FILE、ANTHROPIC_FEDERATION_RULE_ID、
# ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID 和 ANTHROPIC_WORKSPACE_ID
# 这些环境变量。
client = anthropic.Anthropic()

message = client.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(next(block.text for block in message.content if block.type == "text"))

验证设置

成功的交换会返回一个以 sk-ant-oat01- 开头的 access_token 以及一个以秒为单位的 expires_in 值。如果交换失败并返回不透明的 401 authentication_error 响应(消息为 Authentication failed),请查看身份验证历史页面以了解拒绝原因,并参阅排查失败的交换;Kubernetes 端最常见的原因是 JWKS 密钥不匹配(对于 inline 模式,请使用 kubectl get --raw /openid/v1/jwks 重新获取并更新颁发者)。

限定规则范围

将规则的 match 块锁定到适合您用例的最小范围:

  • 固定命名空间和服务账户名称: 使用完整的 system:serviceaccount:<namespace>:<name> 值,末尾不带 *
  • 始终设置受众: 在规则上要求 audience,并在 pod 的 serviceAccountToken 投射上设置相同的值,以便拒绝默认受众令牌。
  • 每个命名空间使用单独的规则: 为每个命名空间创建不同的规则和 Anthropic 服务账户,而不是扩大一条规则的范围。
  • 将 inline-JWKS 颁发者限定到单个集群: 当多个集群共享一个颁发者 URL 时,将每个集群的 JWKS 注册为各自的联合颁发者,并仅将规则绑定到该颁发者。

后续步骤

Was this page helpful?