在 Kubernetes 中,无法创建真正“永久有效”的 Token,这是出于安全考虑的设计。但从 Kubernetes v1.24+ 开始,虽然默认的 ServiceAccount Token 不再自动生成 Secret,但你可以通过手动创建一个 不带自动过期时间的 Secret 来实现一个“长期可用”(可视为“永久”,直到你主动删除或轮换)的 Token。
⚠️ 注意:这违反了零信任和最小权限原则,仅建议用于测试、CI/CD 或受控环境。
✅ 目标
创建一个 ServiceAccount
手动为其创建一个 长期有效的 Secret Token(不使用 TokenRequest API,避免自动过期)
获取该 Token 和 CA 证书
实现“永久有效期”(除非手动删除或集群 CA 轮换)
🔧 步骤:创建永久 Token(基于 Secret)
- 创建 ServiceAccount
kubectl create serviceaccount git-runner -n default
- 手动创建 Secret(绑定到 SA,不设置过期时间)
创建文件 sa-token-secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: git-runner-token
namespace: default
annotations:
kubernetes.io/service-account.name: git-runner
type: kubernetes.io/service-account-token
注意:不要设置 expirationSeconds 字段,就不会自动过期
应用:
kubectl apply -f sa-token-secret.yaml
这个 Secret 将由 kube-controller-manager 自动填充 Token 内容。
- 等待 Token 被填充
kubectl get secret git-runner-token -n default -o jsonpath='{.data.token}’ | base64 –decode
如果输出为空,说明 Token 还未生成,等待几秒再试。
- 绑定权限(例如 cluster-admin)
kubectl create clusterrolebinding git-runner-admin \
–clusterrole=cluster-admin \
–serviceaccount=default:my-permanent-user
📦 获取你需要的信息
✅ 获取 Bearer Token
TOKEN=$(kubectl get secret git-runner-token -n default -o jsonpath='{.data.token}’ | base64 –decode)
echo $TOKEN
✅ 获取 Kubernetes CA 证书(Base64 编码)
CA_CERT=$(kubectl config view –raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}’)
echo $CA_CERT
✅ 验证 Token 是否“永久”
使用以下命令查看 Secret 的 Token 是否包含过期时间:
kubectl get secret git-runner-token -n default -o yaml
你会看到:
没有 expirationSeconds 字段 → 表示不会自动过期
只要 Secret 存在,Token 就有效
只有当 Secret 被删除、ServiceAccount 被删除、或集群 CA 证书轮换时,Token 才失效
✅ 因此,在实际使用中可视为“永久”。
🔄 自动化脚本(支持“永久 Token”)
#!/bin/bash
SA_NAME=”${1:-my-permanent-user}”
NAMESPACE=”${2:-default}”
echo “🚀 创建永久 Token 的 ServiceAccount: $SA_NAME”
1. 创建 SA
kubectl create serviceaccount “$SA_NAME” -n “$NAMESPACE” –dry-run=client -o yaml | kubectl apply -f –
2. 创建永久 Secret
cat <<EOF | kubectl apply -f –
apiVersion: v1
kind: Secret
metadata:
name: ${SA_NAME}-token namespace: $NAMESPACE
annotations:
kubernetes.io/service-account.name: $SA_NAME
type: kubernetes.io/service-account-token
EOF
3. 等待 Secret 就绪
echo “⏳ 等待 Token 生成…”
while ! kubectl get secret “${SA_NAME}-token” -n “$NAMESPACE” -o jsonpath='{.data.token}’ | base64 –decode &> /dev/null; do
sleep 1
done
4. 绑定权限
kubectl create clusterrolebinding “${SA_NAME}-admin” –clusterrole=cluster-admin –serviceaccount=”$NAMESPACE:$SA_NAME” –dry-run=client -o yaml | kubectl apply -f –
5. 输出结果
TOKEN=$(kubectl get secret “${SA_NAME}-token” -n “$NAMESPACE” -o jsonpath='{.data.token}’ | base64 –decode)
CA_CERT=$(kubectl config view –raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}’)
echo
echo “========================================”
echo “✅ 永久 Token 已创建”
echo “========================================”
echo “🔹 Bearer Token: $TOKEN”
echo “🔹 CA 证书 (Base64): $CA_CERT”
echo “💡 提示:此 Token 不会自动过期,除非 Secret 被删除或集群 CA 轮换”
echo “========================================”
⚠️ 安全警告
❌ 不要在生产环境使用,违背了安全最佳实践。
🔒 建议使用短生命周期 Token + 刷新机制(如 OIDC)。
🛑 如果泄露,必须手动删除 Secret 或 SA 来撤销访问。
重点:
这个获取的Kubernetes CA 证书(Base64 编码)和 kubectl get secret my-permanent-user-token -n default -o yaml查看的CA不一样
详细解释
- 你看到的两个 CA 证书分别来自哪里?

- 为什么 git-runner-token Secret 中的 ca.crt 可能不一样或为空?
Kubernetes 不保证 所有 kubernetes.io/service-account-token 类型的 Secret 都包含 ca.crt。
ca.crt 字段是 可选的,它的作用是:让 Pod 内的容器知道如何验证 API Server 的证书。
如果 Pod 运行在集群内部,kubelet 通常会通过其他方式提供 CA(如挂载 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt),所以 Secret 中的 ca.crt 可能被省略。
某些集群(如 kubeadm、EKS、k3s)行为不同,有的填充,有的不填充。
📌 重点:ca.crt 在 Secret 中的存在与否,不影响 Token 的有效性。