面向初级运维,使用 Linux 节点和稳定 Kubernetes API。命令按 Bash 编写。本文为教学故障场景,日志及结果为示意,不冒充生产实测;执行前确认 context、命名空间和权限。
一、遭遇情况:get pods 正常,logs 却被拒绝
部署账号能查看 Pod 列表,执行 kubectl logs 却收到 Forbidden。错误大意是某个身份不能在指定命名空间读取 pods/log。
这不是“集群连接不上”,也不是应用没有日志。请求已经到达授权判断阶段,当前权限没有允许这项操作。本篇场景是一份 Role 只授予 pods 的读取,没有授予日志子资源。
二、原因分析:身份正确,不代表能做所有操作
RBAC 根据身份、API 组、资源、动词和范围授权。pods 与 pods/log 是不同的授权目标;允许列出 Pod,不自动允许读取日志,更不自动允许 exec 进入容器。

Role 定义命名空间内规则,RoleBinding 把身份与规则关联。ClusterRole 可以被 RoleBinding 用于命名空间范围,也可以通过 ClusterRoleBinding 绑定为集群范围;选择哪一种应取决于任务范围,而不是哪种更省事。
三、排查思路:把错误拆成可验证的字段
kubectl auth can-i get pods -n 目标命名空间
kubectl auth can-i get pods --subresource=log -n 目标命名空间
kubectl get role,rolebinding -n 目标命名空间
命名空间是占位符,先替换为实际值。can-i 判断指定操作是否获准,不验证某个 Pod 是否存在或日志是否正常。某些账号也无权读取 Role;此时把错误中的必要字段交给负责授权的人,而不是要求开放全部管理权限。
检查 RoleBinding 的 subject 类型、名称与 namespace,ServiceAccount 身份通常对应 system:serviceaccount:命名空间:账号名。绑定错命名空间,是“规则看起来对但还是不生效”的常见原因。
四、实践:只在专用命名空间授权一个演示账号
以下需要具备创建这些实验 RBAC 对象的权限。实验通过 --as 模拟 ServiceAccount,执行者还需有相应 impersonate 权限;没有该权限时,应使用已有受控测试身份,不要临时提升为集群管理员。
保存为 kt02-rbac.yaml:
apiVersion: v1
kind: Namespace
metadata:
name: kt02
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: observer
namespace: kt02
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: kt02
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: observer-pod-reader
namespace: kt02
subjects:
- kind: ServiceAccount
name: observer
namespace: kt02
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-reader
应用并比较两项权限:
kubectl apply -f kt02-rbac.yaml
kubectl auth can-i list pods -n kt02 --as=system:serviceaccount:kt02:observer
kubectl auth can-i get pods --subresource=log -n kt02 --as=system:serviceaccount:kt02:observer
预期分别为 yes 与 no,前提是没有其他现有绑定额外授予该身份权限。RBAC 许可会叠加,不能只看这一份 Role 就认定账号的全部能力。
五、修复实践:补日志权限,不补集群管理员
编辑实验 Role,将原来的读取规则保留,再增加日志子资源的 get 权限。以下是完整的 Role 更新文件 kt02-role-fixed.yaml:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: kt02
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
kubectl apply -f kt02-role-fixed.yaml
kubectl auth can-i get pods --subresource=log -n kt02 --as=system:serviceaccount:kt02:observer
预期变为 yes。该修改并没有授予写 Pod、读取 Secret 或 exec 权限。真实环境应先确认日志是否属于该账号的任务范围,再做对应授权。
六、验证与总结
最后用真实目标身份读取一个确实存在、允许访问的 Pod 日志。再测试一项明确不应允许的操作,例如 can-i delete pods;仅看日志读取成功,还不能证明授权没有过宽。
不要把长效管理员 token 复制给应用来绕过 Forbidden。ServiceAccount 凭据管理与 Role 规则是两件事,日志内容本身也可能含业务敏感信息。
这类故障的排查顺序是:读身份 → 读动词和资源 → 读命名空间 → 核对绑定 → 最小修复 → 正反两面验证。认证成功是起点,授权始终需要精确到操作。