Skip to content

使用 kubectl 创建只读 kubeconfig

本文档介绍如何通过 RBAC(ServiceAccount + ClusterRole + ClusterRoleBinding) 创建一个 只允许读操作get / list / watch)、禁止一切增删改create / update / patch / delete)的 kubeconfig 文件。

已验证兼容的集群版本:1.16.3 / 1.26.1 / 1.33.4(脚本自动识别版本并选择 Token 获取方式)。

原理

用户(kubeconfig) --> Token --> ServiceAccount --(ClusterRoleBinding)--> ClusterRole(只读规则)
  1. ServiceAccount:集群内的身份,kubeconfig 用它的 Token 认证。
  2. ClusterRole:定义权限规则,对所有资源只授予 getlistwatch 三个动词。
  3. ClusterRoleBinding:把只读规则绑定到 ServiceAccount 上(集群范围生效)。
  4. kubeconfig:写入集群地址、CA 证书和 ServiceAccount 的 Token。

版本兼容性(重要)

不同 K8s 版本获取 ServiceAccount Token 的方式不同,脚本会自动判断:

集群版本Token 获取方式Token 有效期
1.24 及以上(如 1.26.1、1.33.4)TokenRequest API:kubectl create token有过期时间(TOKEN_DURATION,默认 1 年)
1.24 以下(如 1.16.3)创建 kubernetes.io/service-account-token 类型的 Secret,从 Secret 中读取长期有效,不过期

说明:K8s 1.24 起 ServiceAccount 不再自动生成 Token Secret,改用 TokenRequest API; 而 1.16 等老版本没有该 API,只能用 Secret 方式。脚本通过解析集群 minor 版本号自动选择。

快速开始

前置条件:已安装 kubectl,且当前 kubeconfig 具备集群管理员权限(能创建 RBAC 资源)。

bash
chmod +x create-readonly-kubeconfig.sh
./create-readonly-kubeconfig.sh

执行完成后会在当前目录生成 readonly.kubeconfig

自定义参数(环境变量)

变量默认值说明
SA_NAMEreadonly-userServiceAccount 名称
NAMESPACEkube-systemServiceAccount 所在命名空间
OUTPUT./readonly.kubeconfig输出文件路径
CONTEXT_NAMEreadonly-contextkubeconfig 中 context 名称
TOKEN_DURATION8760h(1 年)Token 有效期,最长受集群配置限制

示例:

bash
SA_NAME=viewer OUTPUT=./viewer.kubeconfig TOKEN_DURATION=720h ./create-readonly-kubeconfig.sh

验证权限

bash
# 读操作 —— 应成功
kubectl --kubeconfig=readonly.kubeconfig get pods -A
kubectl --kubeconfig=readonly.kubeconfig get nodes

# 写操作 —— 应被拒绝(Forbidden)
kubectl --kubeconfig=readonly.kubeconfig delete pod xxx -n default
kubectl --kubeconfig=readonly.kubeconfig apply -f xxx.yaml

# 用 auth can-i 直接检查
kubectl --kubeconfig=readonly.kubeconfig auth can-i list pods     # yes
kubectl --kubeconfig=readonly.kubeconfig auth can-i create pods   # no
kubectl --kubeconfig=readonly.kubeconfig auth can-i delete pods   # no
kubectl --kubeconfig=readonly.kubeconfig auth can-i '*' '*'       # no

手动执行(等价命令)

如果不想用脚本,也可以逐条执行:

bash
# 1. 创建 ServiceAccount
kubectl create serviceaccount readonly-user -n kube-system

# 2. 创建只读 ClusterRole
kubectl create clusterrole readonly-user-readonly \
  --verb=get,list,watch --resource='*.*'

# 3. 绑定
kubectl create clusterrolebinding readonly-user-readonly-binding \
  --clusterrole=readonly-user-readonly \
  --serviceaccount=kube-system:readonly-user

# 4. 获取 Token(按集群版本二选一)
# 4a. K8s >= 1.24(如 1.26.1 / 1.33.4):TokenRequest API
TOKEN=$(kubectl create token readonly-user -n kube-system --duration=8760h)

# 4b. K8s < 1.24(如 1.16.3):Secret 方式(Token 长期有效)
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: readonly-user-token
  namespace: kube-system
  annotations:
    kubernetes.io/service-account.name: readonly-user
type: kubernetes.io/service-account-token
EOF
sleep 3   # 等待 controller 填充 token
TOKEN=$(kubectl get secret readonly-user-token -n kube-system -o jsonpath='{.data.token}' | base64 -d)

# 5. 组装 kubeconfig(SERVER/CA 从当前配置中提取)
kubectl config set-cluster  <集群> --server=<API地址> --certificate-authority-data=<CA> --embed-certs=true --kubeconfig=readonly.kubeconfig
kubectl config set-credentials readonly-user --token=$TOKEN --kubeconfig=readonly.kubeconfig
kubectl config set-context readonly-context --cluster=<集群名> --user=readonly-user --kubeconfig=readonly.kubeconfig
kubectl config use-context readonly-context --kubeconfig=readonly.kubeconfig
chmod 600 readonly.kubeconfig

注意事项

  • Secrets 可读resources: ["*"] 包含 secrets,即该账号可以读取集群中所有 Secret 内容。如需禁止读取 Secret,请从规则中排除它,例如把 resources 拆成两条规则, 或显式列出允许的资源类型。
  • Token 有效期(K8s >= 1.24,如 1.26.1 / 1.33.4)kubectl create token 申请的是 带过期时间的 Token(由 TokenRequest API 签发),过期后需重新运行脚本生成。有效期上限受 apiserver 的 --service-account-max-token-expiration 限制。
  • Token 有效期(K8s < 1.24,如 1.16.3):Secret 方式签发的 Token 长期有效、不过期, 但泄露风险更高;如需吊销,删除对应的 Secret 即可。保存好 kubeconfig 文件。
  • 文件权限:kubeconfig 内含凭据,脚本已设置 chmod 600,请勿提交到 Git 仓库。

清理(删除只读账号)

bash
kubectl delete clusterrolebinding readonly-user-readonly-binding
kubectl delete clusterrole readonly-user-readonly
kubectl delete secret readonly-user-token -n kube-system  # 仅 K8s < 1.24(如 1.16.3)存在
kubectl delete serviceaccount readonly-user -n kube-system
rm -f readonly.kubeconfig