全部产品
Search
文档中心

容器计算服务 ACS:通过 CredentialProvider 配置使用 KMS 凭据管家中的 API Key 凭据

更新时间:Aug 19, 2026

通过 CredentialProvider 将存放在阿里云 KMS 凭据管家中的 API Key 统一纳管,由 ack-agent-identity 组件经 OIDC 从 KMS 专属实例代取,按 Agent 身份为 AI Agent 工作负载按需下发凭据,应用侧与业务 Pod 均无需内置明文密钥,也无需直连 KMS。

功能介绍

在 AI Agent 场景中,Agent 常需调用第三方服务(如 OpenAI、通义千问等 LLM 服务)的 API Key。若将真实 API Key 直接写入应用代码、镜像或环境变量,存在凭据泄露与难以轮转的风险。

CredentialProvider 是 ack-agent-identity 提供的凭据来源自定义资源(CRD)。当类型为 APIKey 且来源为 KMS 时,它从阿里云 KMS 凭据管家读取指定凭据的值作为 API Key,并具备以下能力:

  • 真实 API Key 托管在 KMS 凭据管家中,由 KMS 统一管理、轮转与审计。应用与业务 Pod 都不接触明文密钥,也不直连 KMS,而是由 ack-agent-identity 组件经 OIDC 代取。

  • 通过 AgentRole / AgentRoleBinding 授权机制,精细控制每个 Agent 身份可获取哪些 CredentialProvider 的凭据。

  • secretName 支持模板变量,可按 Agent 身份等上下文动态引用不同的 KMS 凭据,实现“一份配置、按身份取不同凭据”。

与 Kubernetes 来源相比,KMS 来源把密钥托管从集群内 Secret 上移到了云端 KMS 凭据管家,适合需要集中托管、轮转与审计密钥的场景。

CredentialProvider 除 APIKey 外还支持 RAM 等类型。本文仅介绍 type: APIKey + KMS 专属实例 OIDC(ACK)来源,其余类型与来源请参见对应文档。

涉及的资源对象

配置一次可用的 KMS 凭据下发,通常涉及以下 CR,下文操作步骤将分别创建:

资源对象

说明

ExternalSecretService

承载 KMS 实例的接入信息(实例 Endpoint、认证 AAP、实例 CA 证书),与”取哪个凭据”解耦。

AgentIdentity

定义 Agent 身份标识,是授权与凭据下发的主体。

CredentialProvider

定义凭据来源。本文中 type: APIKey,通过 serviceRef 引用 ExternalSecretService,从 KMS 读取指定凭据。

AgentRole

定义权限规则,声明允许获取哪个 CredentialProvider 的凭据。

AgentRoleBinding

将 AgentRole 绑定到指定 AgentIdentity,完成授权。

适用范围

  • 集群版本 >= 1.28。

  • 在集群组件管理页面,确认 ack-agent-identity 组件版本 >= 0.5.0。

  • 集群内已安装 coredns 组件。

  • 已购买并启用 KMS 专属实例,且实例镜像版本 >= dkms-4.0.0。低于该版本请先升级,具体操作请参见升级KMS实例的镜像版本。

  • 已在集群集群信息页的基本信息页签中开启 RRSA OIDC(OIDC(ACK) 认证依赖此特性)。

  • 集群与 KMS 专属实例在同一地域但所在 VPC 不一致时,需在 KMS 侧为集群 VPC 配置 VPC 共享(绑定),否则集群内无法通过实例 Endpoint 访问 KMS。具体操作请参见同地域多VPC访问KMS实例。

  • 集群与 KMS 专属实例不在同一地域时,需配置跨地域访问 KMS。具体操作请参见应用跨地域访问KMS实例。

准备 KMS 专属实例接入

在集群内创建资源前,需先在 KMS 侧完成专属实例的 OIDC(ACK) 接入配置,得到组件访问 KMS 所需的应用接入点、实例 Endpoint 和实例 CA 证书。

应用接入点(Application Access Point,简称 AAP)是 KMS 用于云原生接入的访问身份:它绑定一种认证方式(本文为 OIDC(ACK),即信任指定集群 ServiceAccount 的 JWT)与一组 RBAC 权限,组件持集群 ServiceAccount 的 Token 向 KMS 换取临时凭据后,即以该 AAP 的身份和权限访问实例中的凭据。
  1. 登录密钥管理服务控制台,左侧导航栏选择应用接入 > 云原生接入,然后切换到容器 > ACK。

  2. 在集群列表中找到目标集群,并单击其右侧的配置ACK接入。认证方式选择 OIDC(ACK),按下表配置并生成应用接入点:

    OIDC(ACK) 接入的完整控制台操作(含开启 RRSA OIDC、创建 AAP 等)请参见ACK 快速接入。

    配置项

    取值

    Namespace

    固定填 ack-agent-identity。

    ServiceAccount

    固定填 credential-provider。

    作用域

    选择指定的 KMS 实例(即本专属实例)。

    RBAC权限

    选择 CryptoServiceSecretUser(允许读取实例中的凭据)。

    允许访问的资源

    勾选应用需要访问的凭据和密钥(用于凭据加解密)。

    Namespace 与 ServiceAccount 必须填上述固定值,因为向 KMS 证明身份的是 ack-agent-identity 组件(其 ServiceAccount 为 ack-agent-identity 命名空间下的 credential-provider),而不是业务 Pod 的 ServiceAccount。业务 Pod 全程不直连 KMS。
  3. 配置完成后,记录以下信息,供下文创建 ExternalSecretService 使用:

    • 应用接入点(AAP):可用其短名(name,如 my-aap)或完整 ARN(如 acs:kms:cn-hangzhou:123456789012:applicationaccesspoint/my-aap)。

    • 实例 Endpoint:专属实例网关域名,形如 kst-hzz00example.cryptoservice.kms.aliyuncs.com。

    • 实例 CA 证书:专属实例网关的 CA 证书(PEM,公开信息),用于校验实例网关的 TLS 证书。

  4. 在 KMS 凭据管家中创建或确认存放 API Key 的凭据,记录其凭据名称(secretName)。

配置 KMS 凭据下发

以下集群内资源(AgentIdentity、ExternalSecretService、CredentialProvider、AgentRole、AgentRoleBinding)需创建在同一命名空间下。

  1. 通过kubectl快速使用ACS。

  2. 将以下内容保存为 kms-external-secret-service.yaml 并执行 kubectl apply -f kms-external-secret-service.yaml 命令,创建 ExternalSecretService,承载 KMS 专属实例的接入信息。将 endpoint、aap.name、caBundle 替换为上一步记录的实际值。

    apiVersion: agentidentity.alibabacloud.com/v1alpha1
    kind: ExternalSecretService
    metadata:
      name: kms-dedicated-instance
      namespace: <YOUR-NAMESPACE>
    spec:
      provider: KMS
      kms:
        endpoint: kst-hzz00example.cryptoservice.kms.aliyuncs.com   # 专属实例网关 Endpoint
        auth:
          type: AAP                                                 # AAP OIDC 认证
          aap:
            name: my-aap                                            # AAP 短名
        # 专属实例网关的 CA 证书,必填。接受 base64 编码的 PEM(如 `base64 -w0 ca.pem`)或裸 PEM
        caBundle: REPLACE_WITH_BASE64_ENCODED_PEM_OF_YOUR_DEDICATED_KMS_INSTANCE_CA
    ExternalSecretService 在创建时会同步校验 caBundle 是否为合法 PEM,并对 endpoint 进行网络探活。若 caBundle 非法或实例 Endpoint 不可达,apply 会被直接拒绝。请确认集群到 KMS 专属实例的网络连通(参见适用范围中的 VPC 共享说明)。
  3. 将以下内容保存为 agent-identity.yaml 并执行 kubectl apply -f agent-identity.yaml 命令,创建 AgentIdentity 定义 Agent 身份标识。

    apiVersion: agentidentity.alibabacloud.com/v1alpha1
    kind: AgentIdentity
    metadata:
      name: my-agent          # Agent 身份名称,后续授权中引用
      namespace: <YOUR-NAMESPACE>
    spec:
      description: "示例 AI Agent 身份"
  4. 将以下内容保存为 credential-provider-kms.yaml 并执行 kubectl apply -f credential-provider-kms.yaml 命令,创建 CredentialProvider,引用上述 ExternalSecretService 并指定要读取的 KMS 凭据。

    apiVersion: agentidentity.alibabacloud.com/v1alpha1
    kind: CredentialProvider
    metadata:
      name: llm-api-key
      namespace: <YOUR-NAMESPACE>
    spec:
      type: APIKey
      apiKey:
        source:
          provider: KMS
          kms:
            secretName: my-kms-secret-name        # KMS 凭据管家中的凭据名称
            serviceRef:
              name: kms-dedicated-instance        # 上一步创建的 ExternalSecretService 名称
            # versionStage: ACSCurrent            # 可选,凭据版本阶段,默认 ACSCurrent
            # versionId: ""                        # 可选,指定凭据版本 ID
            # maxCacheValidity: 15m                # 可选,凭据值缓存上限,默认 15m
    secretName 支持使用模板变量按上下文动态引用不同的 KMS 凭据,详见secretName 模板变量。
  5. 将以下内容保存为 agent-role-kms.yaml 并执行 kubectl apply -f agent-role-kms.yaml 命令,创建 AgentRole 和 AgentRoleBinding,授权 Agent 身份获取该 CredentialProvider 的凭据。

    apiVersion: agentidentity.alibabacloud.com/v1alpha1
    kind: AgentRole
    metadata:
      name: get-llm-key
      namespace: <YOUR-NAMESPACE>
    spec:
      rules:
      - effect: Allow
        action: "GetResourceCredential"
        resource: "CredentialProvider/llm-api-key"   # 上一步创建的 CredentialProvider 名称
    ---
    apiVersion: agentidentity.alibabacloud.com/v1alpha1
    kind: AgentRoleBinding
    metadata:
      name: my-agent-get-llm-key
      namespace: <YOUR-NAMESPACE>
    spec:
      agentRoleRef:
        apiGroup: agentidentity.alibabacloud.com
        kind: AgentRole
        name: get-llm-key
      subjects:
      - authorizationType: "Agent"
        agentAuthorizationConfiguration:
          agentName: my-agent                        # 与 AgentIdentity name 一致
  6. 确认资源已就绪。ExternalSecretService 的 Available 表示 spec 合法且已通过网络探活;CredentialProvider 的 Available 表示其 serviceRef 已解析到存在的 ExternalSecretService。

    kubectl get externalsecretservice kms-dedicated-instance -n <YOUR-NAMESPACE>
    kubectl get credentialprovider llm-api-key -n <YOUR-NAMESPACE>

    预期输出:

    NAME                     PROVIDER   AVAILABLE   AGE
    kms-dedicated-instance   KMS        True        30s
    
    NAME          AVAILABLE   AGE
    llm-api-key   True        30s

    CredentialProvider 的 Available=True 仅表示 serviceRef 已解析,并不代表已成功从 KMS 取到凭据。AAP 权限不足、实例 CA 不匹配、凭据不存在、VPC 网络不通等问题会在实际获取凭据时才暴露,详见状态与排查。

消费凭据

创建并授权好的 API Key 凭据,通常由 Agent Sandbox 出口流量凭据注入消费:在 SecurityProfile 的 tokenTransformation 规则中引用本 CredentialProvider,Sandbox 应用使用占位符 Token 发起请求,出口网关在转发时自动替换为从 KMS 取到的真实 API Key。完整的端到端配置(SecurityProfile、SandboxSet、SandboxClaim 及验证)请参见为Agent Sandbox出口流量配置凭据注入。

secretName 模板变量

secretName 除填写固定的凭据名称外,还可嵌入 ${ack:agent-identity/...} 模板变量。系统在获取凭据时按当前请求身份上下文渲染出实际凭据名称,从而按身份读取不同的 KMS 凭据。例如 llm-api-key-${ack:agent-identity/agent-name} 会按 Agent 名称解析为 llm-api-key-my-agent。

支持的模板变量如下:

模板变量

说明

${ack:agent-identity/agent-name}

当前 Agent 身份关联的 AgentIdentity 名称。

${ack:agent-identity/metadata/<key>}

身份 Token 签发时写入的自定义 metadata 中指定 Key 的值,<key> 替换为实际 Key 名称。

以下示例演示按租户动态引用不同的 KMS 凭据:不同租户的 API Key 分别存放在以 llm-api-key-<租户标识> 命名的 KMS 凭据中,CredentialProvider 通过 ${ack:agent-identity/metadata/tenant-id} 在获取凭据时解析出对应的凭据名称。

metadata 的值来自身份 Token 签发时写入的自定义 metadata;在 Agent Sandbox 场景中,可通过 SandboxClaim 的 security.agents.kruise.io/<key> 注解传入(注解去掉前缀后即为 metadata 的 Key):

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
  name: my-claim
  namespace: <YOUR-NAMESPACE>
spec:
  templateName: my-sandbox-set
  replicas: 1
  annotations:
    # 以下 annotation 去掉前缀后可在模板中通过 ${ack:agent-identity/metadata/tenant-id} 引用
    security.agents.kruise.io/tenant-id: acme
  labels:
    security.agents.kruise.io/agent-name: my-agent

对应的 CredentialProvider:

apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: CredentialProvider
metadata:
  name: llm-api-key
  namespace: <YOUR-NAMESPACE>
spec:
  type: APIKey
  apiKey:
    source:
      provider: KMS
      kms:
        secretName: 'llm-api-key-${ack:agent-identity/metadata/tenant-id}'   # 解析为 llm-api-key-acme
        serviceRef:
          name: kms-dedicated-instance

上述配置下,当请求身份的 metadata tenant-id 为 acme 时,secretName 解析为 llm-api-key-acme,即读取该租户专属的 KMS 凭据。

若模板变量在当前请求上下文中无法解析(例如引用的 metadata Key 不存在),凭据获取请求会失败并返回明确的错误信息,而非静默返回空值。

字段说明

ExternalSecretService

provider: KMS 的 spec 结构如下:

spec:
  provider: KMS                      # 必填,外部凭据服务类型;创建后不可变更
  kms:
    endpoint: <instance-endpoint>    # 必填,KMS 实例访问域名
    auth:
      type: AAP                      # 必填,认证方式,本文取 AAP(OIDC)
      aap:
        arn: <aap-arn>               # 与 name 二选一,AAP 完整 ARN
        # name: <aap-name>           # 与 arn 二选一,AAP 短名
    caBundle: <ca-pem-or-base64>     # 必填,专属实例网关 CA 证书

关键字段说明如下:

字段

是否必填

说明

spec.provider

是

外部凭据服务类型,本文取 KMS。创建后不可变更。

spec.kms.endpoint

是

KMS 实例访问域名。专属实例网关形如 <实例ID>.cryptoservice.kms.aliyuncs.com。

spec.kms.auth.type

是

KMS 认证方式,本文取 AAP(基于 AAP 的 OIDC 认证)。

spec.kms.auth.aap.arn

二选一

AAP 完整 ARN,形如 acs:kms:<region>:<uid>:applicationaccesspoint/<name>。与 aap.name 恰好二选一。

spec.kms.auth.aap.name

二选一

AAP 短名,组件按地域与账号 ID 拼成完整 ARN。与 aap.arn 恰好二选一。

spec.kms.caBundle

是

专属实例网关的 CA 证书(公开信息)。接受 base64 编码的 PEM 或裸 PEM。

CredentialProvider

type: APIKey + KMS 来源的 spec 结构如下:

spec:
  type: APIKey                       # 必填,凭据类型;创建后不可变更
  apiKey:
    source:
      provider: KMS                  # 必填,凭据来源
      kms:
        secretName: <secret-name>    # 必填,KMS 凭据名称,支持模板变量
        serviceRef:
          name: <ess-name>           # 必填,同命名空间 ExternalSecretService 名称
        versionStage: ACSCurrent     # 可选,凭据版本阶段,默认 ACSCurrent
        versionId: <version-id>      # 可选,指定凭据版本 ID
        maxCacheValidity: 15m        # 可选,凭据值缓存上限,默认 15m

关键字段说明如下:

字段

是否必填

说明

spec.type

是

凭据类型,本文取 APIKey。创建后不可变更(修改会被校验拒绝)。

spec.apiKey.source.provider

是

凭据来源,本文取 KMS。

spec.apiKey.source.kms.secretName

是

KMS 凭据管家中的凭据名称,其值即作为 API Key 下发。支持模板变量。

spec.apiKey.source.kms.serviceRef.name

是

引用的 ExternalSecretService 名称,须与 CredentialProvider 同命名空间。不支持跨命名空间引用。

spec.apiKey.source.kms.versionStage

否

读取的凭据版本阶段,默认 ACSCurrent。

spec.apiKey.source.kms.versionId

否

读取指定版本 ID 的凭据值;与 versionStage 配合使用。

spec.apiKey.source.kms.maxCacheValidity

否

凭据值缓存上限,默认 15m,用于及时感知 KMS 侧的轮转/吊销。

状态与排查

两个 CR 的运行状态均记录在各自的 status.conditions 中,可通过 kubectl describe 查看。

ExternalSecretService 常见 Condition 与 Reason:

Condition / Reason

说明

Available = True,Reason=SpecValid

spec 合法且通过了实例 Endpoint 的网络探活。

Degraded,Reason=EndpointUnreachable

实例 Endpoint 无法连通(检查 VPC 共享/网络连通、Endpoint 与 CA 是否正确)。

CredentialProvider(KMS 来源)常见 Condition 与 Reason:

Condition / Reason

说明

Available = True,Reason=AllRefsResolved

serviceRef 已解析到存在的 ExternalSecretService。

Degraded,Reason=RefNotFound

serviceRef.name 指向的 ExternalSecretService 不存在(检查名称与命名空间是否一致)。

CredentialProvider 的协调阶段只校验 serviceRef 是否存在,不校验能否成功从 KMS 取到凭据。因此与 KMS 访问相关的错误不会体现在 CredentialProvider 状态上,而是在实际获取凭据时才暴露。常见运行时错误及排查方向如下:

现象

排查方向

获取凭据报权限/认证错误

核对 KMS 侧 OIDC(ACK) 的 AAP 配置:Namespace 为 ack-agent-identity、ServiceAccount 为 credential-provider、作用域为本专属实例、RBAC 含 CryptoServiceSecretUser、目标凭据在允许访问的资源范围内。

获取凭据报 TLS/证书错误

ExternalSecretService 的 caBundle 与专属实例网关 CA 不一致,或 endpoint 填错。

获取凭据报凭据不存在

secretName(或模板变量渲染出的名称)在 KMS 凭据管家中不存在,或 versionStage/versionId 指向的版本不存在。

获取凭据报网络不通/超时

集群 VPC 与 KMS 实例 VPC 不一致但未配置 VPC 共享,或安全组/网络策略拦截。参见适用范围中的 VPC 共享说明。

使用限制

限制项

说明

同命名空间引用

CredentialProvider 只能引用同命名空间下的 ExternalSecretService,不支持跨命名空间。

仅专属实例 OIDC 范围

本文仅覆盖 KMS 专属实例 + OIDC(ACK) 接入。

实例镜像版本

KMS 专属实例镜像版本需 >= dkms-4.0.0。

凭据值缓存

KMS 源对凭据值有缓存,maxCacheValidity 默认 15m;KMS 侧轮转/吊销后最长需一个缓存周期才被感知。

常见问题

CredentialProvider 已 Available,但 Sandbox 获取不到 KMS 凭据?

CredentialProvider 的 Available 仅代表 serviceRef 已解析,不代表能成功从 KMS 取到凭据。请按以下方向排查:

  1. 核对 KMS 侧 OIDC(ACK) 的 AAP:Namespace 为 ack-agent-identity、ServiceAccount 为 credential-provider(这是组件的 ServiceAccount,不是业务 Pod 的),作用域为目标专属实例,RBAC 含 CryptoServiceSecretUser,且目标凭据在允许访问的资源内。

  2. 确认 ExternalSecretService 的 endpoint 与 caBundle 与专属实例网关一致,且 kubectl describe externalsecretservice 的 status.conditions 中未出现 Reason 为 EndpointUnreachable 的记录。

  3. 确认 secretName(或渲染后的名称)在 KMS 凭据管家中存在。

  4. 若集群 VPC 与 KMS 实例 VPC 不一致,确认已在 KMS 侧配置 VPC 共享(绑定集群 VPC)。

ExternalSecretService 创建失败提示 no such host?

组件无法解析实例 Endpoint。确认集群 VPC 与 KMS 实例 VPC 一致,或已在 KMS 侧为集群 VPC 配置 VPC 共享/绑定;同时确认 endpoint 填写正确。

ExternalSecretService 一直是 EndpointUnreachable?

组件无法连通实例 Endpoint。确认集群 VPC 与 KMS 实例 VPC 一致,或已在 KMS 侧为集群 VPC 配置 VPC 共享/绑定;同时确认 endpoint 填写正确、caBundle 为该实例网关的 CA。

Agent 获取凭据时被拒绝(无权限)?

确认已创建 AgentRole(action: GetResourceCredential、resource: CredentialProvider/<name>)及 AgentRoleBinding,且 AgentRoleBinding 的 agentName 与目标 AgentIdentity 名称一致,相关资源位于同一命名空间。

相关文档