简介
组件介绍
tcr-assistant-oidc(TCR 动态免密拉取插件)是容器镜像服务 TCR 推出的基于 OIDC 身份认证的容器镜像动态免密拉取官方组件。在容器服务 TKE 集群中安装该组件后,集群可自动动态生成并轮转 TCR 企业版实例的临时访问凭证,无需在集群资源 YAML 中显式配置 ImagePullSecret,即可拉取本账号或其他账号下的 TCR 企业版实例镜像,同时支持配置自定义域名。
与原有 tcr-assistant 插件相比,tcr-assistant-oidc 具备以下增强能力:
能力 | tcr-assistant | tcr-assistant-oidc |
凭证类型 | 静态长期凭证(用户名+密码) | 动态临时密钥,自动轮转 |
跨账号拉取 | 仅支持同账号 | 支持同账号和跨账号 |
安全性 | 长期密钥泄露风险 | 临时密钥定时轮转,自动失效 |
部署在集群内的 Kubernetes 对象
名称 | 类型 | 资源量 | Namespace |
tcr-assistant-system | Namespace | 1 | - |
tcr-assistant-oidc-manager-role | ClusterRole | 1 | - |
tcr-assistant-oidc-manager-rolebinding | ClusterRoleBinding | 1 | - |
tcr-assistant-oidc-leader-election-role | Role | 1 | tcr-assistant-system |
tcr-assistant-oidc-leader-election-rolebinding | RoleBinding | 1 | tcr-assistant-system |
tcr-assistant-oidc-controller-manager | ServiceAccount | 1 | tcr-assistant-system |
tcr-assistant-oidc-webhook-server-cert | Secret | 1 | tcr-assistant-system |
tcr-assistant-oidc-webhook-service | Service | 1 | tcr-assistant-system |
tcr-assistant-oidc-mutating-webhook-configuration | MutatingWebhookConfiguration | 1 | - |
oidcimagepullsecrets.tcr.tencentcloudcr.com | CustomResourceDefinition | 1 | - |
tcr-oidc-* | OIDCImagePullSecret CRD | (1-N) | tcr-assistant-system |
tcr.ips.* | Secret | (1-N)*{Namespace No.} | 目标 Namespace |
tcr-assistant-oidc-controller-manager | Deployment | 1 | tcr-assistant-system |
组件资源用量
组件 | 资源用量 | 实例数量 |
tcr-assistant-oidc-controller-manager | CPU:600m memory:512Mi | 2(多副本高可用) |
使用场景
免密拉取镜像
Kubernetes 集群拉取私有镜像需要创建访问凭证 Secret 资源,并配置资源 YAML 中的 ImagePullSecret 属性,显式指定已创建的 Secret。整体配置流程较为繁琐,且会因未配置 ImagePullSecret 或指定错误 Secret 而造成镜像拉取失败。
为解决以上问题,可在集群中安装 tcr-assistant-oidc 组件,组件基于 OIDC 身份动态生成指定 TCR 企业版实例的临时访问凭证,并按配置下发至 TKE 集群指定命名空间内,同时自动关联到目标 ServiceAccount 的
imagePullSecrets 字段。在使用 YAML 创建或更新资源时,无需显式配置 ImagePullSecret,集群将会自动使用已下发的动态凭证拉取镜像。跨账号拉取镜像
集群管理员可通过配置 CAM OIDC 身份提供商与角色信任策略,允许 B 账号(TKE 集群所在账号)扮演 A 账号(TCR 实例所在账号)的 CAM 角色,从而免密拉取 A 账号 TCR 企业版实例中的镜像,无需在两个账号间同步长期凭证。同账号也可以使用该组件进行凭证动态更新。
自定义域名拉取镜像
若 TCR 企业版实例绑定了自定义域名(如
docker.mycompany.com),组件支持将自定义域名同步写入生成的 dockerconfigjson,工作负载可直接通过自定义域名拉取镜像。动态凭证轮转
组件基于 STS
AssumeRoleWithWebIdentity 换取的临时密钥(有效期固定为 2 小时)访问 TCR,Controller 内部按 tokenExpiration 周期性触发凭证轮转,避免长期凭证泄露风险。限制条件
基础环境要求:
仅支持 Kubernetes 1.20 及以上版本的 TKE 集群(Kubernetes 1.20 将
ServiceAccountIssuerDiscovery 特性升级为正式可用)。目标 TKE 集群需已开启 OIDC 功能,且
pod-identity-webhook 组件安装成功。已开通 容器镜像服务 TCR 并完成服务授权,且已创建企业版实例(状态为“运行中”)。
针对免密拉取镜像使用场景:
用户需在 CAM 中配置相应的自定义策略(含
tcr:DescribeInstances、tcr:PullRepository 等),并授予对应角色。建议由具有 TCR 管理员及 CAM 管理员权限的用户完成组件初始化配置。组件安装并生效后,请避免在资源 YAML 中重复指定 ImagePullSecret,以免节点使用错误的镜像拉取访问凭证导致镜像拉取失败。
namespaces 与 serviceAccounts 匹配规则不支持通配符表达式,需明确填写资源名称或使用 * 表示全部。Secret 轮转间隔
tokenExpiration 建议在 3600~5400 秒 之间,避免临时密钥(有效期 7200 秒)过期后未及时轮转。针对跨账号拉取场景:
B 账号 TKE 集群 VPC 与 A 账号 TCR 实例 VPC 需通过对等连接/云联网互通,且已完成 TCR 实例 Private DNS 解析配置。
A 账号需在 CAM OIDC 身份提供商中登记 B 账号 TKE 集群的 OIDC Issuer 与 JWKS。
组件权限说明
说明:
权限场景章节仅列举组件核心功能涉及的相关权限,完整权限列表请参见权限定义章节。
权限说明
该组件权限是当前功能实现的最小权限依赖。
权限场景
功能 | 涉及对象 | 涉及操作权限 |
需要免密拉取镜像功能,即主动帮客户管理镜像凭证(secret)。 | Secret | watch、create、update、patch、delete |
通过创建、更新 ConfigMap/Lease 来进行主控制器选举,保证组件高可用。 | ConfigMap、Lease | get、list、watch、create、update、patch、delete |
监听命名空间的创建和更新,在需要时自动注入镜像凭证。 | Namespace | get、list、watch |
查询和更新服务账号。 | ServiceAccount | get、list、watch、patch、update |
管理自定义资源(CRD)实现凭证动态编排。 | OIDCImagePullSecret | get、list、watch、create、update、patch、delete |
Pod 创建时的准入兜底,检查并注入 ImagePullSecrets。 | Pod(准入) | MutatingWebhook 拦截 CREATE 事件 |
权限定义
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:name: tcr-assistant-oidc-leader-election-rolenamespace: tcr-assistant-systemrules:- apiGroups: [""]resources: ["configmaps"]verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]- apiGroups: ["coordination.k8s.io"]resources: ["leases"]verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]- apiGroups: [""]resources: ["events"]verbs: ["create", "patch"]---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:name: tcr-assistant-oidc-manager-rolerules:- apiGroups: [""]resources: ["secrets"]verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]- apiGroups: [""]resources: ["namespaces"]verbs: ["get", "list", "watch"]- apiGroups: [""]resources: ["serviceaccounts"]verbs: ["get", "list", "patch", "update", "watch"]- apiGroups: [""]resources: ["serviceaccounts/status"]verbs: ["get", "patch", "update"]- apiGroups: ["admissionregistration.k8s.io"]resources: ["mutatingwebhookconfigurations"]verbs: ["create", "get", "patch", "update"]- apiGroups: ["tcr.tencentcloudcr.com"]resources: ["oidcimagepullsecrets"]verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]- apiGroups: ["tcr.tencentcloudcr.com"]resources: ["oidcimagepullsecrets/status"]verbs: ["get", "patch", "update"]
原理说明
概述
tcr-assistant-oidc 用于帮助用户基于 OIDC 身份自动、动态地部署 Kubernetes
imagePullSecret 到任意 Namespace,并关联到该空间下的 ServiceAccount。在用户创建的工作负载当中没有明确指定 imagePullSecret 和 serviceAccount 的情况下,Kubernetes 会尝试从当前命名空间下名为 default 的 ServiceAccount 资源中查找、匹配合适的 imagePullSecret。与传统方案不同,本组件的 Secret 内容由 STS 临时凭证动态生成,并按
tokenExpiration 周期性轮转,避免了长期凭证泄露的风险。术语表
Name | 别名 | 描述 |
OIDCImagePullSecret | oips | tcr-assistant-oidc 定义的 CRD,声明凭证来源(roleArn / registries)与分发规则(namespaces / serviceAccounts / customDomains)。 |
OIDC Token | - | pod-identity-webhook 注入到 Controller Pod 中的 JWT,由 TKE 集群 API Server 签发,作为跨账号身份互信的凭据。 |
STS AssumeRoleWithWebIdentity | - | 腾讯云 STS 接口,凭 OIDC Token 换取指定角色的临时 SecretId / SecretKey / Token。 |
A 账号 / B 账号 | - | A 账号:TCR 实例所在账号(镜像提供方);B 账号:TKE 集群所在账号(镜像消费方)。同账号场景下 A = B。 |
实现原理
tcr-assistant-oidc 作为典型的 Kubernetes Operator,在部署时会在目标 Kubernetes 集群中创建 CRD 对象:
oidcimagepullsecrets.tcr.tencentcloudcr.com。该 CRD 的 kind 为 OIDCImagePullSecret,版本是 tcr.tencentcloudcr.com/v1,缩写为 oips。tcr-assistant-oidc 通过持续观察(watch) Kubernetes 集群的
Namespace 和 ServiceAccount 资源,并在这些资源发生变更的时候,检查资源变化是否匹配 OIDCImagePullSecret 中设定的规则来自动为用户部署拉取私有镜像仓库所需要的 Secret 资源。程序部署在 Kubernetes 集群内,使用 in cluster 模式访问 Kubernetes master API;同时依赖 TKE 官方 pod-identity-webhook 为 Controller Pod 注入 OIDC Token,通过腾讯云 STS 获取动态临时凭证。创建 CRD 资源
您需要在 TCR 实例所在账号完成如下 CAM 配置:
1. 在 CAM 控制台-身份提供商 中创建 OIDC 身份提供商,登记 TKE 集群的 OIDC Issuer 与 JWKS。
2. 在 CAM 控制台-策略 中创建自定义策略,授予
tcr:DescribeInstances、tcr:PullRepository 等最小权限。3. 在 CAM 控制台-角色 中创建角色,信任策略绑定 OIDC 身份提供商,并关联上述自定义策略,记录角色 ARN。
说明:
roleArn:控制台获取的 A 账号 CAM 角色 ARN,格式
qcs::cam::uin/{UIN}:roleName/{ROLE_NAME},Controller 通过它调用 STS 获取临时凭证。registries:TCR 实例名称(不含域名后缀),组件根据它自动组合公网、VPC、自定义域名。
域名(server):动态生成,包含
{registry}.tencentcloudcr.com、{registry}-vpc.tencentcloudcr.com 以及用户配置的 customDomains。组件部署完成后,会自动创建对应的
OIDCImagePullSecret 资源。也可通过 kubectl 或 Client Go 手工创建:# 新建 OIDCImagePullSecret 资源$ kubectl create -f oidcimagepullsecret-sample.yamloidcimagepullsecret.tcr.tencentcloudcr.com/tcr-oidc-sample created
OIDCImagePullSecret 资源示例文件:apiVersion: tcr.tencentcloudcr.com/v1kind: OIDCImagePullSecretmetadata:name: tcr-oidc-samplespec:namespaces: "*"serviceAccounts: "*"roleArn: "qcs::cam::uin/100001113387:roleName/tcr-cross-account-role"registries:- "your-tcr-registry"customDomains:- "docker.mycompany.com"tokenExpiration: 3600
OIDCImagePullSecret spec 字段解释如下表:字段 | 作用 | 注释 |
namespaces | Namespace 匹配规则 | * 或空字符串表示匹配任意;多个 Namespace 使用 , 分隔。注意:不支持任何表达式,需明确填写资源名称。 |
serviceAccounts | ServiceAccount 匹配规则 | * 或空字符串表示匹配任意;多个 ServiceAccount 使用 , 分隔。注意:不支持任何表达式,需明确填写资源名称。 |
roleArn | A 账号 CAM 角色 ARN | 用于 STS AssumeRoleWithWebIdentity,格式 qcs::cam::uin/{UIN}:roleName/{ROLE_NAME}。 |
registries | TCR 实例名称列表 | 仅填写实例名称,不含域名后缀,组件自动组合公网/VPC 域名。 |
customDomains | TCR 实例自定义域名列表 | 可选,用于自定义域名拉取场景,会额外写入 dockerconfigjson 的 auths 中。 |
tokenExpiration | Secret 轮转间隔(秒) | 建议 3600~5400,默认 3600;不可超过 STS 临时凭证有效期(7200s)。 |
创建完成后,可以通过以下命令观察 tcr-assistant-oidc 执行结果:
# 列出 OIDCImagePullSecret 信息$ kubectl get oipsNAME NAMESPACES SERVICE-ACCOUNTS REGISTRIES CREDENTIAL-STATUStcr-oidc-sample * * [your-tcr-registry] Ready# 查看详细信息$ kubectl describe oips tcr-oidc-sampleName: tcr-oidc-sampleNamespace:API Version: tcr.tencentcloudcr.com/v1Kind: OIDCImagePullSecretSpec:Namespaces: *Service Accounts: *Role Arn: qcs::cam::uin/100001113387:roleName/tcr-cross-account-roleRegistries: [your-tcr-registry]Custom Domains: [docker.mycompany.com]Token Expiration: 3600Status:Credential Status: ReadyLast Refresh Time: 2026-08-05T10:00:00ZNext Refresh Time: 2026-08-05T11:00:00ZSecrets Desired: 10Secrets Success: 10Events: <none>
注意:
如需更新 tcr-assistant-oidc 部署的
Secret 资源,无需删除重建 OIDCImagePullSecret 资源。修改 spec.roleArn、spec.registries、spec.customDomains 等字段后 Controller 会自动 reconcile,Secret 内容将在下一个轮转周期刷新。Namespace 变更
tcr-assistant-oidc 在观察到有新的 Kubernetes
Namespace 资源创建后,会首先校验名称是否与 OIDCImagePullSecret 资源中的 namespaces 字段匹配。如果资源名称不匹配,跳过后续流程;若资源名称匹配,则会调用 STS 换取临时凭证、渲染 dockerconfigjson,调用 Kubernetes API 创建 Secret 资源,并添加 Secret 资源名称到该命名空间下 ServiceAccount 资源的 imagePullSecrets 字段中。示例如下:# 查看 newns 下自动部署的 Secret$ kubectl get secrets -n newnsNAME TYPE DATA AGEtcr.ips.tcr-oidc-sample kubernetes.io/dockerconfigjson 1 7m2s# 查看 dockerconfigjson 中包含的镜像仓库域名$ kubectl get secret tcr.ips.tcr-oidc-sample -n newns \\-o jsonpath='{.data.\\.dockerconfigjson}' | base64 -d | jq '.auths | keys'["your-tcr-registry.tencentcloudcr.com","your-tcr-registry-vpc.tencentcloudcr.com","docker.mycompany.com"]# 查看 newns 下自动关联到 ServiceAccount 资源 default 中的 Secret$ kubectl get serviceaccounts default -o yaml -n newnsapiVersion: v1imagePullSecrets:- name: tcr.ips.tcr-oidc-samplekind: ServiceAccountmetadata:name: defaultnamespace: newns
ServiceAccount 变更
tcr-assistant-oidc 在观察到有新的 Kubernetes
ServiceAccount 资源创建后,会首先校验名称是否与 OIDCImagePullSecret 资源中的 serviceAccounts 字段匹配。如果资源名称不匹配,跳过后续流程;若资源名称匹配,则会调用 Kubernetes API 创建或更新 Secret 资源,并添加 Secret 资源名称到 ServiceAccount 资源的 imagePullSecrets 字段当中。示例如下:# 在 newns 新建 ServiceAccount 资源$ kubectl create sa kung -n newnsserviceaccount/kung created# 查看 newns 下自动关联到新建 ServiceAccount 资源 kung 中的 Secret$ kubectl get serviceaccounts kung -o yaml -n newnsapiVersion: v1imagePullSecrets:- name: tcr.ips.tcr-oidc-samplekind: ServiceAccountmetadata:name: kungnamespace: newns
凭证轮转
Controller 内部 Reconciler 按
tokenExpiration 周期性触发。每次轮转会重新调用 STS AssumeRoleWithWebIdentity 获取新的临时凭证,并更新已分发的 Secret 内容。已运行的 Pod 无需重启,下一次镜像拉取即使用新凭证;升级 Controller 版本时,已生成的 Secret 不会中断,Controller 重启后自动恢复 reconcile。Pod 创建准入兜底
新建 Namespace / Pod 时,Controller 可能尚未完成 Secret 创建与 SA 注入。组件通过 Pod Mutating Webhook 拦截 Pod Create 请求:检查目标 SA 是否已挂载 ImagePullSecret,未就绪时按
CheckIntervalMs 主动等待重试,避免 Pod 因时序问题拉取失败。使用场景与操作指引
tcr-assistant-oidc 支持同账号与跨账号两种免密拉取场景,两种场景的 CAM 配置流程差异较大。具体安装步骤(包括开启 TKE OIDC、创建 CAM OIDC 身份提供商 / 策略 / 角色、打通 VPC 网络、通过控制台 / 云 API / Terraform 安装插件、验证与故障排查等)请参考对应场景的实操文档:
使用场景 | 适用条件 | 操作文档 |
同账号免密拉取 | TKE 集群与 TCR 企业版实例属于同一个腾讯云账号 | |
跨账号免密拉取 | TKE 集群与 TCR 企业版实例分属不同的腾讯云账号 |
说明:
两种场景使用的组件参数(
roleArn / registries / namespaces / serviceAccounts / customDomains / tokenExpiration)完全一致,差异仅在于 CAM 侧的 OIDC 身份提供商与角色信任策略的配置方。若需要通过 Terraform / 云 API 自动化安装 tcr-assistant-oidc 组件,Terraform 示例与 API 调用示例均已包含在上述两篇操作文档中。