Skip to content

RBAC 与安全

Kubernetes 的权限控制核心是 RBAC。生产里客户端 kubeconfig 上的 admin.conf 到处复制、所有组件默认拿 cluster-admin,这两种做法会把权限面打得很开。RBAC 的对象模型本身不复杂,但和 ServiceAccount、Pod 安全上下文、审计日志放在一起,才能覆盖一条完整的 API 请求链路——谁、用什么身份、访问什么资源、做了什么操作、事后能不能追溯到。

RBAC 四类对象

对象作用范围说明
Rolenamespace 内定义在某 namespace 里能做什么
ClusterRole集群级定义集群范围资源(nodes、PV、namespaces)或跨 namespace 操作
RoleBindingnamespace 内把 Role 或 ClusterRole 授权给 namespace 内的主体
ClusterRoleBinding集群级把 ClusterRole 授权到全集群
ServiceAccountnamespace 内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-readonly

kubectl 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/CDCI 流程是否把 Secret 打印到日志里
Git明文 Secret 是否被提交到了仓库
bash
kubectl auth can-i get secrets -n demo --as=ops-readonly

Pod 安全上下文

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=100

RequestResponse 级别会记录请求和响应的具体内容。如果请求或响应里包含 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

权限问题是多对多的关系,不容易一眼看出某个人拥有哪些权限。可以按这个顺序排查:

  1. 确认身份(User、Group、ServiceAccount)
  2. 查 RoleBinding/ClusterRoleBinding 指向哪些 Role/ClusterRole
  3. 看 Role/ClusterRole 里的具体 rules
  4. kubectl auth can-i 验证单项操作

生产里至少把人为操作、系统组件和 CI/CD 的身份分开。共用 admin.conf 的问题不只是权限过大,而是误操作和删改之后难以追溯到人。