帮你快速理解、总结文档立即下载

tcr-assistant-oidc 同账号动态免密拉取配置

最近更新时间:2026-08-11 16:20:31
我的收藏

操作场景

在同一个腾讯云账号内,TKE 集群应用需要拉取本账号 TCR 企业版实例中的私有镜像时,传统做法是在 TCR 控制台生成长期访问凭证(用户名/密码),并在集群中手工创建 ImagePullSecret 关联到工作负载。这种做法存在以下痛点:
凭证长期有效:密码需要人工定期更换,一旦泄露即长期可用,存在安全风险。
tcr-assistant-oidc 插件基于 OIDC 身份认证机制,通过 CAM 角色与 STS 动态临时凭证实现同账号免密拉取镜像,适用于以下典型业务场景:
免密拉取自动化:TKE 集群工作负载无需在 YAML 中显式配置 ImagePullSecret,插件自动分发和轮转。
临时凭证自动轮转:需要满足合规要求,禁止在集群中长期保存镜像仓库长期凭证的场景。
自定义域名拉取:TCR 实例已绑定企业自定义域名(如 docker.mycompany.com),需要通过自定义域名拉取镜像。
与原有 tcr-assistant 插件相比,tcr-assistant-oidc 在同账号场景下具备以下增强能力:
能力
tcr-assistant
tcr-assistant-oidc
凭证类型
静态长期凭证(用户名+密码)
动态临时密钥,自动轮转
说明:
如需跨账号免密拉取(TKE 集群与 TCR 实例分属不同腾讯云账号),请参见 跨账号免密拉取配置

前提条件

已创建 TKE 集群,且集群版本 ≥ 1.20(Kubernetes 1.20 版本将 ServiceAccountIssuerDiscovery 特性升级为正式可用)。
已创建 TCR 企业版实例,且实例状态为"运行中"。
TKE 集群所在 VPC 与 TCR 实例内网访问链路已互通(同 VPC 或已配置 TCR 内网访问)。

实现原理

同账号场景下,TKE 集群与 TCR 实例属于同一个腾讯云账号 A,信任边界完全在账号内部。端到端调用可抽象为五段协作① OIDC 身份注入 → ② CAM 授权换取临时凭证 → ③ 换取 docker 登录密码 → ④ Secret 分发 → ⑤ 工作负载免密拉取

链路解读
编号
环节
关键动作
OIDC 身份注入
pod-identity-webhook 依据 Controller SA 的注解,将 TKE 集群签发的 OIDC JWT 挂载到 Controller Pod。
CAM 授权
Controller 携 JWT 调用 STS,STS 用同账号 OIDC Provider 验签并匹配 Role 信任策略,返回 2h 临时凭证。
换取 docker 密码
Controller 用临时凭证调用 TCR 获取 docker 登录用户名/密码。
Secret 分发
Controller 渲染 dockerconfigjson Secret(tcr.ips.*),按 CR 中的 namespaces / serviceAccounts 规则分发到目标 ns,并自动挂到目标 SA 的 imagePullSecrets
免密拉取
业务 Pod 通过 SA 上的 imagePullSecrets 完成 docker pull;新建 Pod 时 Pod Webhook 兜底校验 Secret & SA 就绪。
说明:
同账号关键特征:OIDC Provider 由 TKE 开启 OIDC 时自动生成,无需手动登记;JWT 的 iss 是 TKE 集群自身,Role 的信任策略仅信任自身账号的 OIDC Provider。

操作步骤

步骤1:TKE 集群开启 OIDC 功能

1. 登录 容器服务控制台,在左侧导航栏选择集群管理
2. 选择目标集群,进入集群详情页,单击基本信息 > API Server 信息
3. 单击 ServiceAccountIssuerDiscovery 右侧的编辑按钮。如下图所示:

4. 进入修改 ServiceAccountIssuerDiscovery 相关参数页面。若系统提示您无法修改相关参数,请先进行服务授权。如下图所示:

5. 在角色管理页面,查看授权策略 QcloudAccessForTKERoleInOIDCConfig,单击同意授权。如下图所示:

6. 授权完成后,勾选创建 CAM OIDC 提供商创建 webhook 组件,并填写客户端 ID,客户端 ID 的值固定为 sts.cloud.tencent.com,单击确定。如下图所示:

7. 返回基本信息 > API Server 信息页,当 ServiceAccountIssuerDiscovery 可再次编辑时,表明本次开启 OIDC 资源访问控制结束。
说明:
service-account-issuerservice-account-jwks-uri 参数值不允许编辑,采用默认规则。

步骤2:确认 OIDC 身份提供商及 Webhook 组件创建成功

开启 OIDC 功能后,需要确认 CAM OIDC 身份提供商已创建且 pod-identity-webhook 组件已成功部署:
1. 在集群详情页,切换到 API Server 信息选项,单击 ServiceAccountIssuerDiscovery 右侧的编辑按钮。
2. 进入修改 ServiceAccountIssuerDiscovery 相关参数页面,系统将提示"您创建的身份提供商已存在,前往查看"。单击前往查看,确认 CAM OIDC 身份提供商已创建成功。
3. 查看刚创建的 CAM OIDC 身份提供商详细信息,确认客户端 ID 配置正确。如下图所示:

4. 集群信息 > 组件管理中,确认列表中 pod-identity-webhook 组件状态为“成功”,即表示组件安装成功。
5. 集群详情 > 工作负载 > Deployment 页面,确认 kube-system 命名空间下 pod-identity-webhook 的状态为 Running 即表示安装成功。

步骤3:创建 TCR 实例的 CAM 自定义策略

根据业务需求创建自定义策略,控制 TCR 实例的访问权限。策略支持精确到命名空间级别的粒度。
注意:
资源六段式中不能增加 region 和 uin 信息。例如 qcs::tcr:::instance/tcr-5jm4cabc,仅需替换最后的 TCR 实例 ID 部分。
策略示例
{
"version": "2.0",
"statement": [
{
"action": [
"tcr:DescribeInstances"
],
"effect": "allow",
"resource": [
"qcs::tcr:::instance/tcr-5jm4cabc"
]
},
{
"action": [
"tcr:PullRepository",
"tcr:PushRepository",
"tcr:CreateRepository"
],
"effect": "allow",
"resource": [
"qcs::tcr:::repository/tcr-5jm4cabc/production-backend/*"
]
}
]
}
策略说明:
tcr:DescribeInstances:login 时需要的权限。
tcr:PullRepository:拉取镜像时需要的策略权限。
tcr:PushRepository:按需授予,不影响镜像拉取。
tcr:CreateRepository:按需授予,推送时如果 repo 不存在,则需要此权限。
resource 中 production-backend/* 表示仅控制命名空间粒度。

步骤4:创建角色并绑定自定义策略

2. 单击新建角色 > 身份提供商
3. 在新建自定义角色页参考以下信息进行设置:
身份提供商类型:选择 OIDC
身份提供商:选择步骤2中确认的、与当前 TKE 集群对应的 OIDC 提供商(名称形如 cls-xxxxxxxx)。
条件:设置 oidc:aud 值等于该 OIDC 提供商的客户端 ID(即 sts.cloud.tencent.com)。
4. 绑定步骤3中创建的自定义策略,完成角色创建,并记录角色 ARN(格式:qcs::cam::uin/{UIN}:roleName/{ROLE_NAME})。
说明:
同账号场景下,角色信任策略中的身份提供商载体为当前账号自身的 OIDC 身份提供商,无需配置其他账号载体。
oidc:aud 存在多个值时,任选其中之一即可。

步骤5:在 TKE 集群中安装 tcr-assistant-oidc 插件

插件会基于 OIDC 身份动态生成临时 docker login 凭证,用于访问同账号下的 TCR 资源。根据实际场景选择以下安装方式之一:

方式一:通过云 API 安装(最新版本 1.0.2)

通过云 API 调用 InstallAddon 接口安装插件。如下图所示:



字段说明:
角色 RoleArn 可在 CAM 控制台角色详情页 获取。
TCR 实例名称 registries 可在 TCR 控制台实例列表 获取。
如果要通过自定义域名拉取镜像,需要额外配置 customDomains
请注意:Values 参数已弃用。如需使用,请通过 RawValues 传入,参数值为 JSON 进行 base64 编码后的内容。示例如下:
echo -n '{
"roleArn": "qcs::cam::uin/100000000000:roleName/your-role-name",
"registries": ["your-tcr-registry"]
}' | base64
RawValues JSON 完整示例:
{
"roleArn": "qcs::cam::uin/100000000000:roleName/tcr-assistant-oidc-read-role",
"registries": ["your-tcr-registry"],
"customDomains": ["docker.mycompany.com"],
"tokenExpiration": 3600,
"namespaces": "*",
"serviceAccounts": "*"
}

方式二:通过 Terraform 安装

resource "tencentcloud_kubernetes_addon" "tcr_assistant_oidc" {
cluster_id = "cls-xxxxxxxx" # 替换为您的 TKE 集群 ID
addon_name = "tcr-assistant-oidc"

raw_values = jsonencode({
# CAM 角色 ARN(必填)
# 格式: qcs::cam::uin/{UIN}:roleName/{ROLE_NAME}
roleArn = "qcs::cam::uin/100000000000:roleName/your-role-name"

# TCR 镜像仓库名称列表(必填)
registries = ["your-tcr-registry"]

# 目标 namespace("*" 表示所有,或 "ns1,ns2,ns3")
namespaces = "*"

# 目标 ServiceAccount("*" 表示所有,或 "sa1,sa2")
serviceAccounts = "*"

# 自定义域名(选填)
customDomains = ["docker.mycompany.com"]
})
}

验证插件安装状态

安装完成后,在 TKE 集群中执行以下命令确认插件正常运行:
# 确认 Controller Pod 正常运行
kubectl get pods -n tcr-assistant-system
# 预期:Pod 为 Running 状态

# 检查 CR 状态,确认已成功获取临时密钥
kubectl get oips tcr-oidc-public -o yaml
# 关注 status.credentialStatus 应为 Ready

# 确认 imagePullSecret 已分发到目标命名空间
kubectl get secret tcr.ips.tcr-oidc-public -n default \\
-o jsonpath='{.data.\\.dockerconfigjson}' | base64 -d | jq '.auths | keys'
预期输出包含 TCR 实例的所有域名:
[
"your-tcr-registry.tencentcloudcr.com",
"docker.mycompany.com"
]

典型使用场景

场景一:通过自定义域名拉取镜像

TCR 实例绑定了自定义域名 docker.mycompany.com,安装组件时指定 customDomains=["docker.mycompany.com"],集群即可通过自定义域名拉取镜像:
kubectl run nginx --image=docker.mycompany.com/my-namespace/nginx:latest

场景二:限定生效范围(指定命名空间和 ServiceAccount)

只在特定命名空间和 ServiceAccount 中生效,避免全局注入 ImagePullSecret,设置 namespaces="production,staging", serviceAccounts="default,app-sa"

升级与变更

升级组件版本

使用 UpdateAddon 升级 tcr-assistant-oidc 组件版本。升级时的参数无需重复指定,只需要更新组件版本和预期要更新的参数配置。tcr-assistant-oidc 组件目标版本列表参考 组件版本维护说明
说明:
升级过程中已有 Secret 不会中断,Controller 重启后自动恢复 reconcile。

验证升级结果

升级完成后,确认 Controller Pod 已更新并正常运行:
# 检查 Pod 状态和镜像版本
kubectl get pods -n tcr-assistant-system -o wide

# 检查 CR 状态
kubectl get oips tcr-oidc-public -o jsonpath='{.status.credentialStatus}'
# 预期输出:Ready

故障排查

Pod 拉取镜像失败(ImagePullBackOff)

排查步骤
1. 检查 Secret 是否存在:
kubectl get secret tcr.ips.tcr-oidc-public -n <pod-namespace>
2. 检查 ServiceAccount 是否注入了 imagePullSecrets:
kubectl get sa default -n <pod-namespace> -o jsonpath='{.imagePullSecrets}'
3. 检查 Controller 日志:
kubectl logs -n tcr-assistant-system deployment/tcr-assistant-oidc-controller

临时密钥过期

动态生成的临时密钥有效期固定为 2 小时(7200 秒),tokenExpiration 控制轮转间隔。如果设置过大(>5400),可能导致密钥过期。
解决方案:确保 tokenExpiration 在 3600~5400 范围内。

OIDC 环境变量未注入

如果 Controller Pod 缺少 OIDC 相关环境变量(TKE_WEB_IDENTITY_TOKEN_FILE 等),说明集群的 pod-identity-webhook 未正常工作。
解决方案
1. 确认 TKE 集群已开启 OIDC。
2. 确认 pod-identity-webhook Pod 正常运行。
3. 重建 Controller Pod。

AssumeRole 失败(权限不足)

如果 Controller 日志中出现 AssumeRoleWithWebIdentity 失败,说明角色信任策略或绑定的自定义策略配置有误。
排查步骤
1. 确认角色的信任策略中身份提供商为当前 TKE 集群对应的 OIDC Provider。
2. 确认角色已关联具备 TCR 访问权限的自定义策略。
3. 确认策略 resource 六段式中的 TCR 实例 ID 正确。

手动验证临时密钥

从 Secret 中提取凭证手动登录验证:
# 获取凭证
SECRET_JSON=$(kubectl get secret tcr.ips.tcr-oidc-public -n default \\
-o jsonpath='{.data.\\.dockerconfigjson}' | base64 -d)

# 提取用户名和密码,your-tcr-registry.tencentcloudcr.com 要替换成实际的访问域名
USERNAME=$(echo $SECRET_JSON | jq -r '.auths["your-tcr-registry.tencentcloudcr.com"].username')
PASSWORD=$(echo $SECRET_JSON | jq -r '.auths["your-tcr-registry.tencentcloudcr.com"].password')

# 手动登录 TCR 实例,注意访问的客户端机器需要能够正常访问 TCR 域名
docker login your-tcr-registry.tencentcloudcr.com --username "$USERNAME" --password "$PASSWORD"