不能靠go run本地跑通就认为RBAC配置OK,必须在Pod内用实际ServiceAccount身份调用API Server测试;因本地kubectl使用个人证书(~/.kube/config),而Pod使用独立的ServiceAccount token,二者认证鉴权流程完全隔离。

直接结论:不能靠go run本地跑通就认为 RBAC 配置 OK,必须在 Pod 内用实际 ServiceAccount 身份调用 API Server 测试。
为什么本地能跑通,进 K8s 就 403?
因为本地 kubectl 用的是你个人证书或 token(来自 ~/.kube/config),而 Pod 里走的是 ServiceAccount 的 token,二者完全独立。API Server 对它们执行两套不同的认证+鉴权流程。
-
system:serviceaccount:default:my-app这类用户名只在集群内有效,和你本地kubeconfig里的user: alice@company.com没任何关系 - 即使你在本地用
kubectl --as=system:serviceaccount:default:my-app get pods测试成功,也只说明 RoleBinding 存在——但不保证你的 Go 程序用了正确的 client config 或 namespace - 错误信息如
User "system:serviceaccount:default:my-app" cannot list resource "pods"是鉴权失败,不是认证失败,说明 RBAC 规则没覆盖到该操作
怎么用 Go 代码验证权限是否生效?
别依赖日志或“没报错就 OK”,要显式发起一次最小权限请求并检查返回码。
- 在 Pod 启动后,用
client-go构造一个rest.Config,**必须用rest.InClusterConfig()**(不能硬塞本地 kubeconfig) - 调用
clientset.CoreV1().Pods("default").List(),捕获 error 并判断是否为errors.IsForbidden(err) - 关键点:不要只 check
err != nil,要 importk8s.io/apimachinery/pkg/api/errors,用errors.IsForbidden()或errors.IsNotFound()区分是权限问题还是资源不存在 - 示例片段:
_, err := clientset.CoreV1().Pods("default").List(ctx, metav1.ListOptions{Limit: 1}) if errors.IsForbidden(err) { log.Fatal("RBAC missing: no 'list pods' permission") }
Role 和 ClusterRole 到底该选哪个?
看你要访问的资源是否跨 namespace。选错会导致权限永远不生效。
立即学习“go语言免费学习笔记(深入)”;
- 如果只查
Pods在defaultnamespace 下 → 用Role+RoleBinding,且Role的metadata.namespace必须和 Pod 所在 namespace 一致 - 如果要
list nodes或get secrets(集群级资源)→ 必须用ClusterRole+ClusterRoleBinding,RoleBinding绑定ClusterRole是无效的 - 注意
apiGroups字段:核心资源(如 pods、secrets)在""(空字符串)组,CRD 在"apiextensions.k8s.io"等,写错组名等于没授权 - verbs 要精确:只写
["get"]就不能list,["*"]不推荐,生产环境应最小化
最容易被忽略的调试细节
很多问题卡在配置加载环节,而不是权限规则本身。
- 确认 Pod 的
serviceAccountName字段和RoleBinding中的subjects.name完全一致(包括 namespace) - 检查
RoleBinding的namespace是否和 Pod 所在 namespace 相同;ClusterRoleBinding没有 namespace 字段,但subjects中的namespace字段对ServiceAccount类型是必须的 - 用
kubectl auth can-i list pods --as=system:serviceaccount:default:my-app -n default手动验证,比改代码快十倍 - 如果用 Kubebuilder,确保
// +kubebuilder:rbacmarker 注释已生成到config/rbac/下,且make manifests后重新kubectl apply,否则 YAML 没更新


















