导读:本期聚焦于过客创作的《Kubernetes TokenRequest API 怎么用?Pod 安全访问 API Server 实战教程》,敬请观看详情。Kubernetes 从 1.21 版本开始废弃了自动挂载的长期 ServiceAccount Token,官方推荐改用 TokenRequest API 来按需签发短期令牌。这篇教程围绕 TokenRequest API 展开,先讲清楚传统 Secret 型 Token 存在的安全隐患,再分析 TokenRequest 签发的-bound Token 的工作原理,包括受众、有效期、绑定对象等核心字段。正文给出完整的 kubectl create token 命令用法,以及用 YAML 手动创建 TokenRequest 的示例代码,最后演示如何在应用代码里通过Projected Volume 自动获取和刷新短期 Token,帮助你把集群内的认证机制升级到更安全的方式。

在 Kubernetes 早期的版本中,每个 Pod 创建时都会自动挂载一个基于 Secret 的 ServiceAccount Token,这个 Token 长期有效、不可撤销,一旦泄露就意味着攻击者可以永久访问 API Server。为了解决这个问题,社区从 1.21 版本开始将这种传统 Token 标记为废弃,并引入了 TokenRequest API 作为替代方案。它允许按需签发短期、绑定到特定对象的 Token,从根本上降低了令牌泄露带来的风险。本文将详细讲解 TokenRequest 的原理和具体使用方法。

Kubernetes TokenRequest API 怎么用?Pod 安全访问 API Server 实战教程

一、为什么需要 TokenRequest API:传统 Token 的安全隐患

要理解 TokenRequest 的价值,得先看看老的 Token 机制有什么问题。传统方式下,创建 ServiceAccount 时 Kubernetes 会自动生成一个类型为 kubernetes.io/service-account-token 的 Secret,里面包含 Token、CA 证书和命名空间信息。Pod 启动时这个 Secret 会被自动挂载到 /var/run/secrets/kubernetes.io/serviceaccount/ 目录,应用就能读取 Token 去访问 API Server。

问题在于这种 Token 有三个致命缺陷。第一,它是长期有效的,默认情况下永不过期,即使 Pod 被删除,Token 依然可以继续使用。第二,Token 与具体的使用场景没有绑定,任何一个拿到它的进程都能用它做任何事情,权限完全取决于 ServiceAccount 被赋予的 RBAC 角色。第三,如果怀疑 Token 泄露,唯一的处理办法是删除整个 ServiceAccount 或者轮换 ServiceAccount 的密钥,这会影响所有使用它的 Pod,操作成本很高。

TokenRequest API 针对这些问题给出了系统性方案:签发的 Token 是短期的,有明确的有效期;Token 会绑定到指定的 Pod 或 Secret 对象上,如果绑定的对象被删除,Token 立即失效;Token 还可以指定受众(Audience),只有目标服务会接受它。这样即使 Token 被窃取,攻击窗口和可用范围都被大幅压缩。

二、TokenRequest 的核心概念与工作原理

TokenRequest 是一个资源对象,向 API Server 请求为某个 ServiceAccount 签发一个 Token。签发出来的 Token 实际上是一个 JWT 格式的字符串,签发方是 API Server 自身,验证方也是 API Server。下面先看一个手动创建 TokenRequest 的 YAML 示例:

apiVersion: authentication.k8s.io/v1
kind: TokenRequest
metadata:
  name: my-token-request
  namespace: default
spec:
  # 指定为哪个 ServiceAccount 签发 Token
  serviceAccountName: my-sa
  # Token 有效期,超过后 Token 失效
  expirationSeconds: 3600
  # 受众,指定 Token 的接收方标识
  audiences:
  - my-api-server
  # 可选:绑定到某个 Pod,Pod 删除后 Token 失效
  boundObjectRef:
    kind: Pod
    apiVersion: v1
    name: my-pod
    uid: 9f2c8b7e-xxxx-xxxx-xxxx-e5a1b2c3d4f5

其中几个字段值得重点关注。audiences 定义了 Token 的预期接收方,JWT 的 aud 声明会被设置成这个值,验证方如果发现自己的标识不在 aud 里就会拒绝,这能防止 Token 被跨服务重放。expirationSeconds 设置有效期,最小值是 10 分钟,也就是 600 秒,生产环境建议设置在 1 小时以内。boundObjectRef 是绑定引用,可以绑定到 Pod 或者 Secret,kubelet 会周期性地检查绑定对象是否还存在,一旦对象被删除,对应的 Token 会被立即加入失效列表。

另一个重要机制是Projected ServiceAccount Volume,也就是投射卷。这是 TokenRequest 在 Pod 中最典型的使用方式:Pod 声明一个 projected 类型的 Volume,Kubelet 会调用 TokenRequest API 为该 Pod 的 ServiceAccount 签发一个短期 Token,挂载到容器内,并且在 Token 过期前自动轮换刷新,应用完全不用关心刷新逻辑。这也是新版本集群中默认的 Token 挂载方式。

三、用 kubectl 快速签发和调试 Token

日常调试场景下,不需要写 YAML,直接用 kubectl 的内置命令就能签发 Token。基本用法如下:

# 为 default 命名空间的 my-sa 签发一个默认有效期(1小时)的 Token
kubectl create token my-sa -n default

# 指定 10 分钟有效期
kubectl create token my-sa -n default --duration=10m

# 指定受众
kubectl create token my-sa -n default --audience=my-api-server

# 输出 Token 的 JWT 详情,方便调试
kubectl create token my-sa -n default -o json

拿到 Token 之后,可以用它直接调用 API Server 验证是否可用。把 Token 值存到环境变量里,再用 curl 请求:

export TOKEN=$(kubectl create token my-sa -n default)
curl -s -k -H "Authorization: Bearer $TOKEN" \
  https://192.168.0.1:6443/api/v1/namespaces/default/pods

这里需要注意,如果请求返回 403,说明 Token 认证通过了,但 ServiceAccount 没有 RBAC 权限,这和 Token 本身是否有效是两回事。排查时可以先给 ServiceAccount 绑定一个有权限的 Role,再验证 Token 是否能正常工作。如果返回 401,则要检查 Token 是否已过期或者受众是否匹配。把 JWT 的 payload 部分 Base64 解码一下,可以直接看到 expaudkubernetes.io 等声明字段,是排查认证问题的好办法。

四、在 Pod 中通过 Projected Volume 自动使用短期 Token

生产环境中推荐的做法是让应用通过投射卷自动获取 Token,下面是一个完整的 Pod 定义示例:

apiVersion: v1
kind: Pod
metadata:
  name: token-demo
  namespace: default
spec:
  serviceAccountName: my-sa
  containers:
  - name: app
    image: busybox:1.36
    command: ["sleep", "3600"]
    volumeMounts:
    - name: token-volume
      mountPath: /var/run/secrets/tokens
  volumes:
  - name: token-volume
    projected:
      sources:
      - serviceAccountToken:
          path: my-token
          expirationSeconds: 3600
          audience: my-api-server

这个 Pod 启动后,Kubelet 会在容器的 /var/run/secrets/tokens/my-token 路径放置一个短期 Token。关键优势在于刷新机制:当 Token 有效期过去大约 80% 时,Kubelet 会自动调用 TokenRequest API 签发新 Token 并更新文件内容。应用只需要在每次发请求前重新读取文件即可拿到最新 Token,无需自己实现刷新逻辑,也不需要引入额外的客户端库。

如果是使用 client-go 的 Go 应用,直接用 kubernetes.NewForConfig 配合 rest.InClusterConfig 就能自动读取挂载的 Token 并处理刷新,代码非常简洁:

package main

import (
	"context"
	"fmt"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
)

func main() {
	// 自动读取 Pod 内挂载的 Token 和 CA 证书
	config, err := rest.InClusterConfig()
	if err != nil {
		panic(err)
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err)
	}
	pods, err := clientset.CoreV1().Pods("default").List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		panic(err)
	}
	for _, pod := range pods.Items {
		fmt.Println(pod.Name)
	}
}

五、迁移注意事项与最佳实践

从传统 Token 迁移到 TokenRequest 时,有几点需要留意。首先,如果 Pod 使用了自定义的挂载路径或者关闭了 automountServiceAccountToken,要确认应用读取 Token 的逻辑是否兼容轮换机制,也就是每次请求前重新读文件,而不是启动时读一次缓存到内存里。其次,短期 Token 对时钟敏感,务必保证节点之间的时间同步,否则可能出现 Token 被判定为过期的情况。

其次,从安全角度建议遵循最小权限原则:在 Pod 或 ServiceAccount 层面设置 automountServiceAccountToken: false,只有确实需要访问 API Server 的 Pod 才显式声明投射卷,并且通过 audience 字段限定 Token 的使用范围。对于集群外的客户端,比如 CI 流水线需要访问集群,可以考虑用 TokenRequest 配合短期 Token 替代长期 ServiceAccount 密钥,或者直接使用 OIDC 身份认证,整体安全性都会比传统的静态 Token 高出一个档次。

Kubernetes TokenRequestServiceAccount TokenK8s API Server 认证修改时间:2026-09-06 21:46:44

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260906/51816.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。