在Kubernetes 1.32+集群环境中,ServiceAccount(SA)的令牌生成机制发生了显著变化。传统通过直接读取/var/run/secrets/kubernetes.io/serviceaccount/token的方式在新版本中不再适用,这给需要从集群外部访问Kubernetes API的场景带来了新的挑战。本文将详细解析新版令牌生成机制,并提供一套完整的跨版本兼容方案。
重要提示:从Kubernetes 1.24开始,Secret-based的ServiceAccount令牌已被标记为deprecated,1.32+版本中相关行为变更更为明显
bash复制# 传统方式获取token(已失效)
kubectl get secret $(kubectl get sa default -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 -d
这种机制依赖自动生成的Secret资源,其特点包括:
bash复制# 新版本推荐方式
kubectl create token default --duration=8760h
新机制的核心改进:
bash复制# 确认集群版本
kubectl version --short | grep Server
# 检查TokenRequest API可用性
kubectl get --raw /api/v1 | grep token
bash复制# 生成有效期为1年的token
kubectl create token my-service-account \
--duration=8760h \
--bound-object-kind=Secret \
--bound-object-name=my-static-token
yaml复制apiVersion: v1
kind: Secret
metadata:
name: my-static-token
annotations:
kubernetes.io/service-account.name: my-service-account
type: kubernetes.io/service-account-token
应用后通过常规方式获取:
bash复制kubectl get secret my-static-token -o jsonpath='{.data.token}' | base64 -d
python复制from kubernetes import client, config
token = "YOUR_GENERATED_TOKEN"
configuration = client.Configuration()
configuration.host = "https://k8s-api.example.com:6443"
configuration.ssl_ca_cert = "/path/to/ca.crt"
configuration.api_key = {"authorization": f"Bearer {token}"}
v1 = client.CoreV1Api(client.ApiClient(configuration))
ret = v1.list_pod_for_all_namespaces()
bash复制curl -X GET $APISERVER/api/v1/namespaces \
--header "Authorization: Bearer $TOKEN" \
--cacert /path/to/ca.crt
yaml复制apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: my-namespace
name: limited-access-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: limited-access-binding
namespace: my-namespace
subjects:
- kind: ServiceAccount
name: my-service-account
namespace: my-namespace
roleRef:
kind: Role
name: limited-access-role
apiGroup: rbac.authorization.k8s.io
bash复制kubectl create token my-sa --audience=https://my.external.system
bash复制kubectl get --raw /metrics | grep apiserver_authentication_attempts
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| 401 Unauthorized | Token过期/无效 | 重新生成token并验证有效期 |
| 403 Forbidden | RBAC配置错误 | 检查RoleBinding和ServiceAccount关联 |
| x509证书错误 | CA证书不匹配 | 使用kubectl get cm kube-root-ca.crt -o jsonpath='{.data.ca\.crt}'获取最新CA |
bash复制# 查看token详细信息
kubectl get secret my-static-token -o yaml
# 检查ServiceAccount状态
kubectl get sa my-service-account -o yaml
# API请求调试(需要高级权限)
kubectl get --raw /apis/authentication.k8s.io/v1/tokenreviews -d @- <<EOF
{
"spec": {
"token": "YOUR_TOKEN",
"audience": "optional-audience"
}
}
EOF
bash复制#!/bin/bash
# 获取集群版本
K8S_VERSION=$(kubectl version -o json | jq -r .serverVersion.minor)
if [ ${K8S_VERSION} -ge 24 ]; then
# 1.24+版本使用TokenRequest
TOKEN=$(kubectl create token my-sa --duration=8760h)
else
# 旧版本使用Secret方式
TOKEN=$(kubectl get secret $(kubectl get sa my-sa -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 -d)
fi
echo "Generated Token: ${TOKEN}"
| 特性 | 1.23及之前 | 1.24-1.31 | 1.32+ |
|---|---|---|---|
| 自动Secret生成 | ✔️ | ❌(默认禁用) | ❌ |
| TokenRequest API | ✔️(基础版) | ✔️(增强版) | ✔️(稳定版) |
| 默认token有效期 | 永久 | 1小时 | 1小时 |
| Audience验证 | ❌ | ✔️ | ✔️(强制) |
在实际操作中发现,1.32+版本对边界条件的处理更加严格。特别是在处理跨命名空间的ServiceAccount引用时,需要显式配置authentication.k8s.io/token-audiences注解才能正常工作。建议在升级集群前,先用测试环境验证所有外部集成点的兼容性。