For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
主导航

为 Kubernetes 配置工作负载身份联合

将投射的 Kubernetes 服务账户 Token 交换为短期有效的 OpenAI 访问令牌,即可将 Kubernetes 用作工作负载身份提供方。

如果您使用 Codex,请按照本页说明获取并检查投射的 Token。然后配置 Codex 工作负载身份,使 Codex 指向挂载的 Token 文件。本页中的服务账户映射和 SDK 示例适用于 OpenAI API。

设置 Kubernetes

本指南假定已启用 Kubernetes 服务账户 Token 投射功能,该功能在较新的 Kubernetes 版本中默认可用。OpenAI 工作负载身份联合要求使用兼容 OIDC 的投射服务账户 Token。不支持存储在 Secret 中的旧版 Kubernetes 服务账户 Token。

为需要调用 OpenAI API 的工作负载使用 Kubernetes ServiceAccount。如果您尚未创建,请先创建一个:

kubectl create serviceaccount openai-wif --namespace default

获取您的 Kubernetes 集群的 OIDC 签发者:

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

即使您上传了 JWKS,且 OpenAI 不向 OIDC 签发者执行 JWKS 发现,此签发者也必须与工作负载身份提供方中配置的签发者一致。

获取集群的 JWKS,并保存返回的密钥集。配置工作负载身份提供方时会用到它:

kubectl get --raw /openid/v1/jwks

为投射的服务账户 Token 配置 OpenAI 预期的受众,以及适合您工作负载的有效期。OpenAI 会验证 Token 的签发者、签名、受众和到期时间。在此示例中,Token 文件挂载在 /var/run/secrets/tokens/token,受众为 https://api.openai.com/v1,并在 3600 秒后到期。您可以使用其他受众,但投射 Token 的受众必须与 OpenAI 工作负载身份提供方的受众一致:

apiVersion: v1
kind: Pod
metadata:
  name: openai-wif-app
  namespace: default
spec:
  serviceAccountName: openai-wif
  containers:
    - name: app
      image: my-image
      volumeMounts:
        - name: ksa-token
          mountPath: /var/run/secrets/tokens
          readOnly: true
  volumes:
    - name: ksa-token
      projected:
        sources:
          - serviceAccountToken:
              path: token
              audience: "https://api.openai.com/v1"
              expirationSeconds: 3600

验证 Token

配置工作负载身份联合之前,请在本地解码一个投射服务账户 Token 样本,并检查其中的声明。从已挂载投射 Token 且正在运行的 Pod 中获取 Token,并将其导出为环境变量 TOKEN

TOKEN=$(kubectl exec -n default openai-wif-app -- cat /var/run/secrets/tokens/token)
export TOKEN

然后运行以下脚本:

const parts = process.env.TOKEN?.split(".") ?? [];
if (parts.length !== 3) {
  throw new Error("Expected a compact JWT with three segments");
}
if (!/^[A-Za-z0-9_-]+$/.test(parts[1]) || parts[1].length % 4 === 1) {
  throw new Error("JWT payload is not valid Base64URL");
}

const bytes = Buffer.from(parts[1], "base64url");
if (bytes.toString("base64url") !== parts[1]) {
  throw new Error("JWT payload is not valid Base64URL");
}
const decoded = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
const claims = JSON.parse(decoded);
if (claims === null || Array.isArray(claims) || typeof claims !== "object") {
  throw new Error("JWT payload is not a JSON object");
}
console.log(decoded);

此命令会解码 JWT 载荷,但不会验证 Token 签名。对于生产环境的 Token,请使用本地解码器,避免将其粘贴到第三方工具中。

解码后的 Kubernetes 投射服务账户 Token 类似于以下内容:

{
  "iss": "https://kubernetes.example.com",
  "aud": ["https://api.openai.com/v1"],
  "sub": "system:serviceaccount:default:openai-wif",
  "iat": 1716235422,
  "exp": 1716239022,
  "kubernetes.io": {
    "namespace": "default",
    "serviceaccount": {
      "name": "openai-wif",
      "uid": "11111111-2222-3333-4444-555555555555"
    }
  }
}

使用解码后的载荷,将您收到的 Token 与 OpenAI 中配置的签发者、受众和映射值进行比较。在交换 Token 之前,通过 issaudsub 声明即可发现大多数配置问题。

设置工作负载身份联合

在 OpenAI 中为 Kubernetes 签发者创建工作负载身份提供方,然后添加与投射 Token 中的属性相匹配的服务账户映射。

先配置工作负载身份提供方,再创建服务账户映射。

设置工作负载身份提供方

  1. 创建工作负载身份提供方。名称 设为唯一值,例如 kubernetes-prod。填写 描述,例如 Production Kubernetes cluster,以便管理员识别集群。

  2. 设置签发者和受众。OIDC 签发者 URL 设为 kubectl get --raw /.well-known/openid-configuration | jq -r .issuer 返回的签发者。此值必须与投射 Token 中的 iss 声明一致。将 受众 设为投射服务账户 Token 卷中配置的同一个不透明受众字符串。在此示例中,该值为 https://api.openai.com/v1

  3. 上传 Kubernetes JWKS。 启用 使用上传的 JWKS 验证 Token,然后将 JWKS JSON 设为 kubectl get --raw /openid/v1/jwks 的输出。OpenAI 使用此公钥集验证投射的 Kubernetes 服务账户 Token。请上传完整的密钥集,包括外层的 keys

    注意: 对于自行托管的 Kubernetes 集群,OpenAI 仅支持本地 JWKS 模式。请上传集群返回的 JWKS;OpenAI 不会向配置的签发者执行 OIDC 发现。OpenAI 仍会将配置的签发者与 Token 中的 iss 字段进行比较。

    如果您的集群轮换了服务账户签名密钥,请在工作负载身份提供方配置中更新已上传的 JWKS。如果签署 Token 的密钥不在配置的 JWKS 中,该 Token 将被拒绝。如果 JWKS 包含多个有效公钥,请包含完整的 keys 数组。

  4. 仅在需要派生映射属性时添加属性转换。 原始 Token 声明(例如 subaudiss)可直接用于映射断言。如果您打算使用转换后的属性而非原始 Token 声明进行匹配,控制台会自动添加 openai. 前缀;例如,输入 workload_subject 并使用表达式 assertion.sub,即可创建 openai.workload_subject。对于 openai. 映射键,除非配置了相应的转换,否则系统会忽略原本就以 openai. 开头的原始 Token 声明。

设置服务账户映射

  1. 创建服务账户映射。名称 设为该工作负载身份提供方内的唯一值,例如 openai-mapping-kubernetes。填写 描述,例如 Workload Identity Provider Mapping for Kubernetes Workloads,以说明哪些工作负载可以使用此映射。

  2. 匹配 Kubernetes 服务账户主体。 设为 sub,将 设为 system:serviceaccount:default:openai-wif。Kubernetes 服务账户的主体格式为 system:serviceaccount:<namespace>:<service-account-name>

  3. 选择 OpenAI 目标。项目 设为目标服务账户所属的 OpenAI 项目。将 服务账户 设为 Kubernetes 工作负载可使用的 OpenAI 服务账户,例如 kubernetes-prod-openai-wif。如果您希望为此映射创建新的服务账户,而不是复用现有账户,请勾选 Create a new service account in this project

  4. 根据需要缩小 API 权限范围。 选择适当的 权限 ,例如 api.model.requestapi.vector_store.read,以进一步限制通过此映射签发的访问令牌的权限。将权限留空,则不会添加 WIF 特有的作用域限制;Token 仍以映射到的服务账户身份获得授权。

在代码中使用 Token

配置您的 OpenAI SDK 客户端,使其读取投射的 Kubernetes Token,并将其交换为 OpenAI 签发的访问令牌。

将挂载的 Token 路径(例如 /var/run/secrets/tokens/token)用作 SDK 工作负载身份联合提供方的主体 Token 来源。SDK 会将该 Kubernetes Token 交换为 OpenAI 签发的访问令牌,并使用此 OpenAI Token 对 API 请求进行身份验证。

以下示例使用自定义主体 Token 提供方初始化 OpenAI 客户端。该提供方从挂载的文件路径读取投射的 Kubernetes 服务账户 Token,并将其用作工作负载身份联合的主体 Token。

使用 Kubernetes 投射服务账户 Token 进行身份验证
import { readFile } from "node:fs/promises";
import OpenAI from "openai";

const tokenPath = "/var/run/secrets/tokens/token";
const identityProviderId = process.env.OPENAI_IDENTITY_PROVIDER_ID;
const serviceAccountId = process.env.OPENAI_SERVICE_ACCOUNT_ID;

if (!identityProviderId || !serviceAccountId) {
  throw new Error(
    "Set OPENAI_IDENTITY_PROVIDER_ID and OPENAI_SERVICE_ACCOUNT_ID"
  );
}

function mountedServiceAccountTokenProvider(path) {
  return {
    tokenType: "jwt",
    getToken: async () => {
      const token = (await readFile(path, "utf8")).trim();
      if (!token) {
        throw new Error("The mounted service account token file is empty.");
      }
      return token;
    },
  };
}

const client = new OpenAI({
  workloadIdentity: {
    identityProviderId,
    serviceAccountId,
    provider: mountedServiceAccountTokenProvider(tokenPath),
  },
});

const response = await client.responses.create({
  model: "gpt-5.6-terra",
  input: "Say hello from Kubernetes workload identity federation.",
});

console.log(response.output_text);

Kubernetes 最佳实践

  • 使用稳定的 OIDC 签发者。签发者 URL 必须与投射服务账户 Token 的 iss 声明一致,并且应在集群升级和维护操作期间保持稳定。
  • 妥善保护签名密钥。任何能够访问集群服务账户签名密钥的人,都可以签发可能被 OpenAI 接受的 Token。
  • 为 OpenAI 集成使用专用服务账户。避免复用同时用于访问无关基础设施或应用的服务账户。
  • 及时更新已上传的 JWKS。在本地 JWKS 模式下,OpenAI 使用配置的 JWKS 验证工作负载身份 Token,因此请在轮换到新的签名密钥之前更新工作负载身份提供方。
  • 尽量降低自定义声明的复杂度。优先使用 subaud 等标准声明,或直接从这些声明转换而来的属性进行匹配。
  • 将命名空间的归属纳入您的安全模型。如果命名空间管理员可以创建服务账户,请确保适当限定映射范围,以防止非预期的权限提升。
  • 监控签发者和签名密钥的变更。轮换签名密钥而不更新工作负载身份提供方的 JWKS,可能导致 Token 交换失败。