DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

Kubernetes ServiceAccount 仍报 cannot list pods:RoleBinding 可能绑错主体

Kubernetes Role 已允许 list pods,ServiceAccount 仍被拒绝时,核对 RoleBinding 主体类型、完整身份和授权空间,避免无依据扩大权限。

Pod 已指定 ServiceAccount,Role 中也有 pods 的 list 权限,执行 kubectl get pods 仍提示 cannot list resource "pods"。如果错误里的身份是 system:serviceaccount:team-app:app-reader,而 RoleBinding 写的是 kind: User、name: app-reader,两者没有指向同一个主体。

这条路径针对启用了 RBAC、请求已被识别为 ServiceAccount 的 Kubernetes 集群。Forbidden 还可能来自缺少动词、资源或命名空间不符;要把错误里的身份和目标资源逐项对应,不能直接给应用加 cluster-admin。

从报错确认身份与动作

下面是简化的报错示例,名称需换成实际对象:

User "system:serviceaccount:team-app:app-reader" cannot list resource "pods" in API group "" in the namespace "team-app"

其中 team-app:app-reader 是 ServiceAccount 的命名空间和名称;最后的 namespace 是请求访问的目标空间,两者可能不同。错误中的 User 是身份描述,不要求 RoleBinding 的 kind 也写成 User。

kubectl get pods 列出一组 Pod,通常对应 API 的 list 动词。读取某个指定 Pod 是 get,观察持续变化还可能需要 watch。核对报错所拒绝的动作,不能用允许 get 来证明 list 也允许。

由有权限的管理员在正确集群查看实际配置:

kubectl config current-context
kubectl get pod example-app-abc123 -n team-app \
  -o jsonpath='{.spec.serviceAccountName}{"\n"}'
kubectl get role pod-reader -n team-app -o yaml
kubectl get rolebinding app-read-pods -n team-app -o yaml

以上对象名称均为示例。Pod 的实际 serviceAccountName 应与报错身份对应;没有指定时一般使用该空间的 default。只修改本地 Deployment 清单,还不能证明现有 Pod 已经换用了新账户。

ServiceAccount 主体与 roleRef 使用不同字段

以下是供核对的最小授权示例,仅允许该账户列出目标空间的 Pod,不包含日志读取、exec、修改或删除:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: team-app
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-read-pods
  namespace: team-app
subjects:
  - kind: ServiceAccount
    name: app-reader
    namespace: team-app
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

subjects 指定获得权限的账户。ServiceAccount 的 API group 为空,可像示例一样省略,不能把 User 示例中的 apiGroup: rbac.authorization.k8s.io 一并留在这个主体下。roleRef 引用 RBAC Role,仍要保留它自己的 apiGroup;二者不要一起删除。

Role 中的 apiGroups: [""] 又是另一处含义,表示 Pod 所属的核心 API 组。访问 deployments 等资源时应按其实际组配置,不能把空组作为所有 Kubernetes 资源的通配符。

RoleBinding 的 metadata.namespace 决定这份授权覆盖哪个空间;引用 Role 时,该 Role 要在同一空间。subjects[].namespace 指定账户来自哪里,即使跨空间授予权限,也不能因此把它改成目标空间的账户。跨空间授权应由管理员确认必要性及范围。

若确实绑定普通用户,kind: User 的 name 必须匹配认证后完整用户名。这里修正的是 ServiceAccount 被误写成短名称用户的情况,不表示所有 User 绑定都无效。

修改前保留现有授权,修改后检查实际请求

修改授权前保存原 RoleBinding 和 Role,确认没有其他主体依赖它们。若仅主体写错,应在原绑定中修正相应主体并保留其他获准字段;不要用这个最小示例直接覆盖业务原有权限或其他账户。

新增授权会立即扩大该账户可执行的 API 操作。只授予应用实际需要的动词与资源。RoleBinding 的 roleRef 不可原地修改;若同时需要换 Role,须按单独的授权变更流程处理,不把删绑定重建当成无影响操作。

具备模拟身份权限的管理员可以检查目标动作:

kubectl auth can-i list pods -n team-app \
  --as=system:serviceaccount:team-app:app-reader

预期结果是 yes。若命令自身报不能 impersonate,说明检查者没有模拟该身份的权限,不能把它解释成目标 ServiceAccount 仍缺 list。应换用获准的检查身份,或在应用实际凭据下验证同一个 API 请求,不向应用临时授予模拟权限。

最终还要让原来失败的调用使用相同账户、目标空间和动词成功执行。若授权检查已允许,应用仍报另一个账户被拒绝,继续核对它实际加载的 kubeconfig、令牌及 Pod 身份。恢复原绑定可撤回此次授权,但 RBAC 权限是叠加的,其他绑定授予的权限不会因此消失。