固定 AK/SK→ 保存到 Secret 或外部配置系统→ 注入 Pod→ SDK 读取 AK/SK→ 直接访问云 API
Pod 使用的 ServiceAccount→ TKE 签发短时效 OIDC Token→ STS 验证 Token 和角色信任关系→ 返回 CAM 角色临时凭证→ SDK 访问云 API
TmpSecretId、TmpSecretKey、Token)。对比项 | 固定 AK/SK | Pod OIDC |
Pod 中持有的凭证 | 长期 AK/SK | 短时效 OIDC Token 和按需获取的 CAM 临时凭证 |
身份来源 | AK/SK 对应的云用户或云身份 | Kubernetes 命名空间 + ServiceAccount |
权限绑定 | 权限绑定在 AK/SK 对应身份上 | ServiceAccount 通过 OIDC 身份映射到 CAM 角色 |
权限隔离 | 多个 Pod 可能共用同一组凭证 | 可按业务或 ServiceAccount 绑定不同角色 |
凭证存储 | 需要保存和分发 AK/SK | Pod 中不保存长期 AK/SK;Token 通过投影 Volume 挂载 |
生命周期 | 通常长期有效,需要主动轮换 | Token 和临时凭证短时有效,可自动刷新 |
凭证泄露影响 | 在 AK/SK 被禁用或轮换前可能持续有效 | 受 Token 有效期、临时凭证有效期和角色权限约束 |
轮换成本 | 需要更新存储并通知使用方重新加载 | 集群和 SDK 自动刷新,应用无需感知 |
审计定位 | 需先定位 AK/SK 所属身份,再关联具体工作负载 | 可结合角色会话、ServiceAccount 和命名空间定位工作负载 |
组件 | 主要职责 |
TKE OIDC Provider | 为 ServiceAccount 签发 OIDC Token,并提供 Discovery 和 JWKS 端点。 |
CAM OIDC 身份提供商与 CAM 角色 | 验证 OIDC 身份,将 ServiceAccount 映射到 CAM 角色,并依据角色策略授权。 |
pod-identity-webhook | 根据 ServiceAccount 注解向 Pod 注入投影 Token、角色 ARN 和相关环境变量。 |
pod-identity-webhook 不签发 CAM 临时凭证,也不代理应用访问云资源。ServiceAccountIssuerDiscovery 后,TKE 集群可作为 OIDC Provider,并提供以下能力:jwks_uri,再从 JWKS 端点获取公钥并验证 JWT 签名。serviceAccountName 指定 ServiceAccount。集群签发 Token 时,会将 ServiceAccount 身份写入 JWT 的标准声明。以下示例仅列出与身份验证相关的主要字段:{"iss": "<TKE 集群的 OIDC Issuer URL>","sub": "system:serviceaccount:prod:cos-reader","aud": ["sts.cloud.tencent.com"],"iat": 1720000000,"exp": 1720003600}
字段 | 含义 | 作用 |
iss | Token 签发方 | 标识 TKE 集群对应的 OIDC Provider |
sub | Token 主体 | 格式为 system:serviceaccount:<namespace>:<serviceaccount> |
aud | Token 接收方 | 必须与云端身份提供商及角色信任策略中的 Audience 一致 |
iat / exp | 签发时间和过期时间 | 限定 Token 的有效时间范围 |
sub 加以区分。例如:system:serviceaccount:prod:cos-readersystem:serviceaccount:prod:log-writersystem:serviceaccount:test:cos-readeriss 找到 /.well-known/openid-configuration。jwks_uri。kid 选择对应公钥。iss 和 aud。策略 | 用途 | 典型内容 |
角色信任策略 | 哪些身份可以扮演该角色 | OIDC Provider、 oidc:aud、oidc:sub、sts:AssumeRoleWithWebIdentity |
角色权限策略 | 该角色可以执行哪些操作 | 云产品 API、资源范围和访问条件 |
oidc:sub 将指定 ServiceAccount 映射到 CAM 角色。例如:TKE OIDC Provider+ aud = sts.cloud.tencent.com+ sub = system:serviceaccount:prod:cos-reader└──> CAM 角色 cos-reader-role└──> 只读指定 COS Bucket
prod 命名空间中的 cos-reader ServiceAccount 可以扮演 cos-reader-role。其他命名空间中的同名 ServiceAccount 不满足该条件。AssumeRoleWithWebIdentity 时,CAM 和 STS 将执行以下检查:iss 是否对应已注册的 CAM OIDC Provider。aud 是否与配置一致。aud 和 sub。pod-identity-webhook 是一个突变准入 Webhook。创建 Pod 时,该组件读取 Pod 所使用 ServiceAccount 的注解,并注入以下内容:TKE_ROLE_ARN:目标云角色 ARN。TKE_WEB_IDENTITY_TOKEN_FILE:投影 Token 文件路径。TKE_REGION、TKE_PROVIDER_ID 等辅助环境变量。动作 | 实际执行者 |
决定是否为 Pod 注入身份配置 | pod-identity-webhook |
签发 ServiceAccount Token | Kubernetes API Server |
将 Token 投射到 Pod 并在到期前刷新 | kubelet |
验证 Token 并签发 CAM 临时凭证 | CAM / STS |
缓存并刷新 CAM 临时凭证 | 应用使用的云 SDK |
凭证 | 如何获得 | 用途 |
OIDC ServiceAccount Token | TKE 集群根据 Pod 使用的 ServiceAccount 签发,并挂载到 Pod 中 | 向 CAM 证明 Pod 的 Kubernetes 身份 |
CAM 临时凭证 | 应用或云 SDK 使用 OIDC Token 和目标角色信息向 STS 申请 | 调用角色权限范围内的腾讯云 API |
业务凭据(可选) | 应用使用 CAM 临时凭证从 SSM 等服务读取 | 连接数据库等需要独立业务凭据的服务 |
SecretId、SecretKey 和 Token。应用随后使用这组临时凭证访问角色已授权的云资源。ServiceAccountIssuerDiscovery,选择以下选项:pod-identity-webhook 组件。sts.cloud.tencent.com。
QcloudAccessForTKERoleInOIDCConfig 的授权。

service-account-issuer 和 service-account-jwks-uri 由 TKE 托管,用户不能修改。pod-identity-webhook 由 TKE 托管面安装和维护。可在集群的 组件管理 页面查看组件状态。

oidc:aud = 步骤 1 中的客户端 ID。oidc:sub = system:serviceaccount:<namespace>:<serviceaccount-name>,限定到具体的 ServiceAccount。
*ReadOnlyAccess 策略。qcs::cam::uin/xxx:roleName/xxx)。prod 命名空间中的 cos-reader ServiceAccount 扮演该角色:{"version": "2.0","statement": [{"effect": "allow","principal": {"federated": ["qcs::cam::uin/xxx:oidcProvider/tke-<cluster-id>"]},"action": ["sts:AssumeRoleWithWebIdentity"],"condition": {"string_equal": {"oidc:aud": ["sts.cloud.tencent.com"],"oidc:sub": ["system:serviceaccount:prod:cos-reader"]}}}]}
{"version": "2.0","statement": [{"effect": "allow","action": ["cos:GetObject", "cos:HeadObject", "cos:ListBucket"],"resource": ["qcs::cos:ap-guangzhou:uid/xxx:my-bucket-xxx/*"]}]}
apiVersion: v1kind: ServiceAccountmetadata:name: cos-readernamespace: prodannotations:tke.cloud.tencent.com/role-arn: qcs::cam::uin/xxx:roleName/cos-reader-roletke.cloud.tencent.com/audience: sts.cloud.tencent.comtke.cloud.tencent.com/token-expiration: "3600"
serviceAccountName 引用该 ServiceAccount:apiVersion: apps/v1kind: Deploymentmetadata:name: my-appnamespace: prodspec:template:spec:serviceAccountName: cos-readercontainers:- name: appimage: my-app:latest
AssumeRoleWithWebIdentity,再使用返回的临时凭证初始化云产品客户端。tke.cloud.tencent.com/role-arn 注解的 ServiceAccount 后,Webhook 会向 Pod 注入以下内容:类型 | 键 / 路径 | 说明 |
环境变量 | TKE_ROLE_ARN | 目标 CAM 角色 ARN |
环境变量 | TKE_WEB_IDENTITY_TOKEN_FILE | 投影 Token 文件路径,默认 /var/run/secrets/cloud.tencent.com/serviceaccount/token |
环境变量 | TKE_REGION(如已配置) | 默认地域 |
Volume | tke-oidc-token | 投影 ServiceAccount Token 卷 |
VolumeMount | 上述 Token 文件路径 | 只读挂载 |
env | grep TKE_,并检查 /var/run/secrets/cloud.tencent.com/serviceaccount/ 目录,确认环境变量和 Token 文件是否已正确注入。common.DefaultTkeOIDCRoleArnProvider() 或自定义凭证提供器。AssumeRoleWithWebIdentity,并使用返回的临时凭证初始化客户端。DefaultTkeOIDCRoleArnProvider() 显式启用 TKE OIDC 凭证:显式传入 SecretId/Key→ 环境变量 TENCENTCLOUD_SECRET_ID/KEY→ OIDC Web Identity Token(Pod OIDC 场景)→ CVM 实例角色(节点角色)→ 抛错
provider, err := common.DefaultTkeOIDCRoleArnProvider()if err != nil { /* ... */ }cred, err := provider.GetCredential()if err != nil { /* ... */ }client, _ := cos.NewClient(&cos.BaseURL{...}, &http.Client{Transport: &cos.AuthorizationTransport{SecretID: cred.GetSecretId(),SecretKey: cred.GetSecretKey(),SessionToken: cred.GetToken(),},})
注解 | 必填 | 默认值 | 说明 |
tke.cloud.tencent.com/role-arn | 是 | 无 | 目标 CAM 角色 ARN。 |
tke.cloud.tencent.com/audience | 否 | sts.cloud.tencent.com | JWT Audience,必须与 CAM 角色信任策略中的 oidc:aud 一致;如果信任策略配置了多个 Audience,可填写其中任意一个。 |
tke.cloud.tencent.com/token-expiration | 否 | 3600 | 投影 Token 有效期,单位为秒;取值范围为 600~86400。 |
项 | 限制 |
支持集群类型 | TKE 托管集群;独立集群 / Serverless 集群 / 边缘集群支持情况请查看控制台或提工单确认。 |
集群版本要求 | ≥ v1.20.6-tke.27 或 ≥ v1.22.5-tke.1,更高版本默认支持。 |
Pod 网络要求 | 需能访问腾讯云 STS 端点。VPC 无出网集群请使用内网 STS 端点或配置 PrivateLink。 |
Token 有效期 | 600 ~ 86400 秒。 |
单个 ServiceAccount 可绑定的角色数量 | 1;如需使用多个角色,建议创建多个 ServiceAccount。 |
AssumeRoleWithWebIdentity 频控 | 遵循 CAM 全局配额,建议 SDK 缓存临时凭证,接近过期再刷新。 |
超级节点 / 虚拟节点 | 支持,注解使用方式一致。 |
私有集群 / 无公网出口 | 需要配置 Pod 到 STS 内网端点的网络路径。 |
kubectl describe pod,检查是否存在 TKE_ROLE_ARN 等环境变量。serviceAccountName,以及 pod-identity-webhook 组件状态。kubectl exec 进入 Pod,再执行 cat $TKE_WEB_IDENTITY_TOKEN_FILE。AssumeRoleWithWebIdentity 返回 401 或无权限oidc:aud 与 ServiceAccount 注解中的 Audience 一致。oidc:sub 与 Pod 使用的 ServiceAccount 完全匹配,格式为 system:serviceaccount:<namespace>:<serviceaccount>。ServiceAccountIssuerDiscovery 提示身份提供商不存在,需要重新创建 Provider。ServiceAccountIssuerDiscovery 无法编辑QcloudAccessForTKERoleInOIDCConfig 的授权。role-arn 注解并重新创建 Pod,使新 Pod 不再注入身份配置。oidc:sub 限定可扮演角色的身份。tke.cloud.tencent.com/role-arn 注解的 ServiceAccount 的 Pod,该组件会注入投影 ServiceAccount Token、环境变量和 Volume。组件由 TKE 托管面安装和维护,可在集群的 组件管理 页面查看运行状态。rules:- apiGroups: [""]resources: ["serviceaccounts"]verbs: ["get", "watch", "list"]- apiGroups: [""]resources: ["events"]verbs: ["patch", "update"]- apiGroups: ["admissionregistration.k8s.io"]resources: ["mutatingwebhookconfigurations"]verbs: ["get"]
mutatingwebhookconfigurations 增加 update 权限,用于注入自签名证书。实际权限以组件版本为准。TKE ServiceAccount└──> TKE OIDC Token└──> AWS STS AssumeRoleWithWebIdentity└──> AWS IAM Role 临时凭证└──> S3 / DynamoDB / SQS / 其他 AWS 服务
AWS 对象 | 作用 | 需要配置的关键内容 |
IAM OIDC Provider | 注册并验证 TKE 集群签发的 Token | TKE Issuer URL、Discovery/JWKS、Audience,以及必要时使用的证书指纹 |
IAM Role 信任策略 | 定义允许扮演角色的 OIDC 身份 | Provider ARN、 sts:AssumeRoleWithWebIdentity、aud、sub |
IAM Role 权限策略 | 定义角色可以调用的 AWS API | Action、Resource、Condition |
ServiceAccountIssuerDiscovery,获取集群的 OIDC Issuer URL。<Issuer URL>/.well-known/openid-configurationjwks_uri 指向的 JWKS 端点Provider URL 填写 TKE 集群的 Issuer URL。Audience 中填写 sts.amazonaws.com。ServiceAccount 投影 Token 的 aud 必须与该值一致。issuer 和 jwks_uri 获取验证信息。如果 OIDC 端点使用的根 CA 不受 AWS 信任,或 AWS 无法验证 TLS 证书链,还需要按照 AWS 要求配置证书指纹。具体要求参见 AWS:创建 IAM OIDC 身份提供商。{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": ["s3:ListBucket"],"Resource": ["arn:aws:s3:::example-bucket"]},{"Effect": "Allow","Action": ["s3:GetObject"],"Resource": ["arn:aws:s3:::example-bucket/*"]}]}
prod 命名空间中的 s3-reader ServiceAccount 绑定到该角色:{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/<ISSUER_HOST_AND_PATH>"},"Action": "sts:AssumeRoleWithWebIdentity","Condition": {"StringEquals": {"<ISSUER_HOST_AND_PATH>:aud": "sts.amazonaws.com","<ISSUER_HOST_AND_PATH>:sub": "system:serviceaccount:prod:s3-reader"}}}]}
<AWS_ACCOUNT_ID>:AWS 账号 ID。<ISSUER_HOST_AND_PATH>:去掉 https:// 的完整 Issuer 主机名与路径,必须与 IAM OIDC Provider ARN 中的值一致。sub:允许扮演角色的 TKE 命名空间和 ServiceAccount。本例仅允许 prod/s3-reader。aud:必须与 IAM OIDC Provider 的 Audience 和 ServiceAccount 注解一致。sub 通配符,否则同一集群中的其他 ServiceAccount 也可能扮演该角色。Web Identity 角色的信任策略要求请参见 AWS:为 OIDC 联合身份创建角色。pod-identity-webhook 会将 role-arn 注解的值写入 TKE_ROLE_ARN。对接 AWS 时,可在该注解中填写 AWS IAM Role ARN:apiVersion: v1kind: ServiceAccountmetadata:name: s3-readernamespace: prodannotations:tke.cloud.tencent.com/role-arn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/tke-s3-readertke.cloud.tencent.com/audience: sts.amazonaws.comtke.cloud.tencent.com/token-expiration: "3600"
serviceAccountName: s3-reader 使用该 ServiceAccount。Webhook 将注入以下环境变量:TKE_ROLE_ARN=arn:aws:iam::<AWS_ACCOUNT_ID>:role/tke-s3-readerTKE_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/cloud.tencent.com/serviceaccount/token
AWS_ROLE_ARNAWS_WEB_IDENTITY_TOKEN_FILEAWS_ROLE_SESSION_NAME(可选)TKE_ROLE_ARN 和 TKE_WEB_IDENTITY_TOKEN_FILE,AWS SDK 默认凭证链不会读取这两个变量。可采用以下方式进行适配。以下示例通过 AWS SDK for Go v2 显式读取 TKE 环境变量并初始化 S3 客户端:package awsauthimport ("context""fmt""os""github.com/aws/aws-sdk-go-v2/config""github.com/aws/aws-sdk-go-v2/credentials/stscreds""github.com/aws/aws-sdk-go-v2/service/s3""github.com/aws/aws-sdk-go-v2/service/sts")func NewS3Client(ctx context.Context, awsRegion string) (*s3.Client, error) {roleARN := os.Getenv("TKE_ROLE_ARN")tokenFile := os.Getenv("TKE_WEB_IDENTITY_TOKEN_FILE")if roleARN == "" || tokenFile == "" {return nil, fmt.Errorf("missing TKE_ROLE_ARN or TKE_WEB_IDENTITY_TOKEN_FILE")}baseCfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(awsRegion))if err != nil {return nil, fmt.Errorf("load AWS base config: %w", err)}stsClient := sts.NewFromConfig(baseCfg)roleSessionName := os.Getenv("HOSTNAME")if roleSessionName == "" {roleSessionName = "tke-pod"}provider := stscreds.NewWebIdentityRoleProvider(stsClient,roleARN,stscreds.IdentityTokenFile(tokenFile),func(options *stscreds.WebIdentityRoleOptions) {options.RoleSessionName = roleSessionName},)cfg, err := config.LoadDefaultConfig(ctx,config.WithRegion(awsRegion),config.WithCredentialsProvider(provider),)if err != nil {return nil, fmt.Errorf("load AWS config with web identity: %w", err)}return s3.NewFromConfig(cfg), nil}
TKE_ROLE_ARN 与 TKE_WEB_IDENTITY_TOKEN_FILE 分别作为角色 ARN 和 Token 文件路径传入。AWS 标准配置项参见 AWS SDK:Assume role credential provider,Go v2 Provider 用法参见 AWS SDK for Go v2:AssumeRoleWithWebIdentity。TKE_REGION 表示腾讯云地域,不能用作 AWS Region。初始化 AWS 客户端时,需要单独配置 ap-southeast-1 等 AWS Region。InvalidIdentityToken:确认 AWS 可以访问 TKE Discovery 和 JWKS 端点,并检查 Issuer URL 与 TLS 证书链。sts.amazonaws.com。AccessDenied(无法扮演角色):确认 Provider ARN、sub 和目标 Role ARN 完全匹配。TKE_* 环境变量,或已将其映射为 AWS SDK 默认读取的 AWS_* 环境变量。pod-identity-webhook 相关问题。文档反馈