Appearance
RBAC 与安全
Kubernetes 的权限控制核心是 RBAC。生产里客户端 kubeconfig 上的 admin.conf 到处复制、所有组件默认拿 cluster-admin,这两种做法会把权限面打得很开。RBAC 的对象模型本身不复杂,但和 ServiceAccount、Pod 安全上下文、审计日志放在一起,才能覆盖一条完整的 API 请求链路——谁、用什么身份、访问什么资源、做了什么操作、事后能不能追溯到。
RBAC 四类对象
| 对象 | 作用范围 | 说明 |
|---|---|---|
| Role | namespace 内 | 定义在某 namespace 里能做什么 |
| ClusterRole | 集群级 | 定义集群范围资源(nodes、PV、namespaces)或跨 namespace 操作 |
| RoleBinding | namespace 内 | 把 Role 或 ClusterRole 授权给 namespace 内的主体 |
| ClusterRoleBinding | 集群级 | 把 ClusterRole 授权到全集群 |
| ServiceAccount | namespace 内 | Pod 访问 API Server 时用的身份 |
RoleBinding 可以引用 ClusterRole 但只在一个 namespace 内生效。这个设计允许定义一个只读 Pod 的 ClusterRole,然后在每个 namespace 里分别绑给不同的人——不用在每个 namespace 都建一份 Role。
只读示例
给某个用户在 demo namespace 里只读 Pod 和 Pod 日志:
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: demo
rules:
- apiGroups: [""] # 核心 API 组的 apiGroup 是空字符串
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader
namespace: demo
subjects:
- kind: User
name: ops-readonly # 用户名,来自 kubeconfig 的证书 CN 或 OIDC claim
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io验证权限:
bash
kubectl auth can-i list pods -n demo --as=ops-readonly
kubectl auth can-i delete pods -n demo --as=ops-readonlykubectl auth can-i 不消耗真实 API 调用——它走的是 SubjectAccessReview API,直接问 apiserver"这个身份能不能做这个操作",适合权限配置后快速验证。
ServiceAccount
Pod 访问 API Server 默认用的是所在 namespace 的 default ServiceAccount。生产里通常给不同组件单独建 SA 并绑定最小权限:
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-reader
namespace: demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
namespace: demo
spec:
template:
spec:
serviceAccountName: app-reader # 这个 Pod 用 app-reader 的身份访问 API给控制器、采集组件、CI Runner 分配 SA 时,先想清楚它到底需要读什么(get/list/watch),是否需要写(create/update/patch/delete),是否需要删(delete/deletecollection)。只读场景给读写权限是多余的。
Secret 权限
能 get secret 的人基本上能拿到 Secret 里的所有敏感内容。Secret 保护要从多个层面看:
| 防护层 | 解决的问题 |
|---|---|
| RBAC | 谁能通过 API 读取 Secret |
| etcd 加密 | Secret 在 etcd 存储层是否明文 |
| 审计日志 | 事后能否追溯谁读了 Secret |
| CI/CD | CI 流程是否把 Secret 打印到日志里 |
| Git | 明文 Secret 是否被提交到了仓库 |
bash
kubectl auth can-i get secrets -n demo --as=ops-readonlyPod 安全上下文
Pod 和容器级别的安全配置通过 securityContext 设置:
yaml
securityContext: # Pod 级别
runAsNonRoot: true # 禁止以 root 运行
runAsUser: 10001 # 指定运行 UID
fsGroup: 10001 # 挂载卷的文件系统 group
containers:
- name: app
image: harbor.example.com/demo/app:v1.0.0
securityContext: # 容器级别
allowPrivilegeEscalation: false # 禁止通过 setuid 提权
readOnlyRootFilesystem: true # 根文件系统只读
capabilities:
drop:
- ALL # 移除所有 Linux capabilities高风险配置值得单独列出并定期审计:
| 配置 | 暴露的风险 |
|---|---|
privileged: true | 容器几乎等同宿主机 root |
hostPath 挂载敏感目录 | 直接读写宿主机文件系统 |
hostNetwork: true | 使用宿主机网络命名空间,能看到宿主机网络流量 |
hostPID: true | 能看到宿主机所有进程 |
| 挂载 Docker/containerd socket | 可以在容器内控制宿主机上的所有容器 |
capabilities.add: ["SYS_ADMIN", "NET_ADMIN"] | 接近 privileged 的权限面 |
审计日志
审计策略决定了 API Server 记录什么请求:
yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata # 只记录请求元数据(谁、操作、资源、结果)
verbs: ["get", "list", "watch"]
- level: RequestResponse # 记录完整请求体和响应体
verbs: ["create", "update", "patch", "delete"]
resources:
- group: ""
resources: ["secrets"]API Server 参数:
yaml
- --audit-policy-file=/etc/kubernetes/audit-policy.yaml
- --audit-log-path=/var/log/kubernetes/audit.log
- --audit-log-maxage=30
- --audit-log-maxbackup=10
- --audit-log-maxsize=100RequestResponse 级别会记录请求和响应的具体内容。如果请求或响应里包含 Secret、token 等敏感数据,审计日志本身就成了敏感数据源。对 Secret 的读写用 RequestResponse,对普通 Pod 的 get/list 用 Metadata——策略要根据资源敏感度分层。
权限排查
查权限时先确认身份是什么,再查这个身份有哪些绑定:
bash
kubectl auth can-i create pods -n demo --as=alice
kubectl auth can-i get secrets -A --as=system:serviceaccount:demo:app-reader
kubectl describe rolebinding -n demo
kubectl describe clusterrolebinding权限问题是多对多的关系,不容易一眼看出某个人拥有哪些权限。可以按这个顺序排查:
- 确认身份(User、Group、ServiceAccount)
- 查 RoleBinding/ClusterRoleBinding 指向哪些 Role/ClusterRole
- 看 Role/ClusterRole 里的具体 rules
- 用
kubectl auth can-i验证单项操作
生产里至少把人为操作、系统组件和 CI/CD 的身份分开。共用 admin.conf 的问题不只是权限过大,而是误操作和删改之后难以追溯到人。