RBAC 权限管理
权限决定谁能对什么资源做什么操作。Kubernetes 的安全体系由认证、授权、准入控制三部分组成,RBAC 是其中最核心的授权模型。本章讲透身份与授权,并落到最小权限实践。
本篇目标:理解认证/授权/准入控制的分工,掌握 Role/ClusterRole 与 Binding 的模型,能为 Pod 配置最小权限 ServiceAccount,并会用 kubectl auth can-i 验证权限。
1. K8s 安全三步曲:认证 / 授权 / 准入控制
请求到达 kube-apiserver
→ ① 认证(你是谁) :客户端证书 / token / OIDC
→ ② 授权(你能做什么) :RBAC(本章)
→ ③ 准入控制(是否符合策略):PodSecurity、ResourceQuota、自定义 Webhook
| 环节 | 回答的问题 | 主要机制 |
|---|---|---|
| 认证(Authentication) | 你是谁 | kubeconfig 凭据、ServiceAccount token、OIDC |
| 授权(Authorization) | 你能做什么 | RBAC(本章) |
| 准入控制(Admission) | 是否符合集群策略 | PodSecurity、ResourceQuota、OPA/Gatekeeper |
1.1 两种身份
| 身份 | 谁使用 | 说明 |
|---|---|---|
| 人类用户 | 管理员、开发者 | 客户端证书或 OIDC;Kubernetes 没有 user 对象 |
| ServiceAccount | Pod 内应用 | 挂载到容器的 token 认证,由 kubelet 管理 |
2. RBAC 核心模型:Role / ClusterRole 与 Binding
2.1 四个对象
| 对象 | 作用域 | 说明 |
|---|---|---|
Role | Namespace | 授权某 Namespace 内的资源 |
ClusterRole | 集群 | 授权集群级资源(Node、PV)或跨 Namespace |
RoleBinding | Namespace | 把 Role 绑定到主体(SA/User/Group) |
ClusterRoleBinding | 集群 | 把 ClusterRole 绑定到主体 |
2.2 最小权限示例
# 1. 创建专属 ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: api
namespace: learning
---
# 2. 定义只能读 ConfigMap 的 Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: config-reader
namespace: learning
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
# 也可以限定资源名称:
# resourceNames: ["api-config"]
---
# 3. 把 Role 绑定到 ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: api-config-reader
namespace: learning
subjects:
- kind: ServiceAccount
name: api
roleRef:
kind: Role
name: config-reader
apiGroup: rbac.authorization.k8s.io
2.3 常用 verbs 与资源
- verbs:
get、list、watch、create、update、patch、delete; - 资源:
pods、deployments、services、configmaps、secrets等;子资源用/表示,如pods/log、pods/exec; - 资源不必存在:授权时按名称字符串匹配,未来新建的资源也适用。
# ClusterRole:授权集群级资源
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-reader
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
2.4 常见模式:Role + ClusterRoleBinding
把 ClusterRole 绑定到 Namespace 内的 ServiceAccount,实现"读全集群 Node,但只限本 Namespace 的 SA":
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: node-reader-api
subjects:
- kind: ServiceAccount
name: api
namespace: learning
roleRef:
kind: ClusterRole
name: node-reader
apiGroup: rbac.authorization.k8s.io
3. ServiceAccount 与 Pod 身份凭证挂载
3.1 默认行为
每个 Namespace 有默认的 default ServiceAccount。未显式指定的 Pod 会使用它,并自动挂载 API token(用于访问 API Server)。
kubectl get serviceaccount -n learning
kubectl get pod <pod> -n learning -o jsonpath='{.spec.serviceAccountName}'
3.2 最小权限挂载
apiVersion: v1
kind: Pod
metadata:
name: api
namespace: learning
spec:
serviceAccountName: api
# 如果不需要访问 API Server,关闭默认 token 挂载
automountServiceAccountToken: false
containers:
- name: api
image: registry.example.com/api:1.4.2
3.3 projected ServiceAccount token(推荐)
生产环境更推荐 projected service account token:在 Pod 级指定 audience 与过期时间,令牌定期自动轮换,避免长期 token 泄漏后被滥用:
spec:
containers:
- name: api
volumeMounts:
- name: token
mountPath: /var/run/secrets/tokens
readOnly: true
volumes:
- name: token
projected:
sources:
- serviceAccountToken:
audience: api
expirationSeconds: 3600
path: api-token
4. 最小权限原则(PoLP)实战演练
4.1 验证权限
# 验证 ServiceAccount 能否执行某个操作
kubectl auth can-i list configmaps -n learning \
--as=system:serviceaccount:learning:api
# 验证当前用户自己能不能做某操作
kubectl auth can-i delete namespaces
# 查看某个 Role 的权限详情
kubectl describe role config-reader -n learning
4.2 实践要点
- 优先使用 Namespace 范围的
Role,除非资源确实属于集群级别(如 Node、PV、StorageClass); - 不要因为一项权限不足就授予
cluster-admin——那是集群 root; - 定期审计高权限 Binding:
kubectl get clusterrolebinding -o wide | grep cluster-admin; - 为 CI/CD、监控、GitOps 工具各自创建独立 ServiceAccount,不混用;
- 不需要访问 API Server 的应用关闭
automountServiceAccountToken; - Secret 读取权限要单独最小化,并审计读取日志。
4.3 常见误区
| 误区 | 正确做法 |
|---|---|
直接给应用用 default SA | 每个应用创建专属 SA |
用 cluster-admin 图省事 | 按最小权限拆分 Role |
| 权限不足就加宽范围 | 先 kubectl auth can-i --as=... 验证到底是什么操作被拒 |
忽略 pods/exec、secrets 子资源 | 这些是高危权限,单独审计 |
5. Pod 安全标准(PSS)与 NetworkPolicy
RBAC 管"谁能做什么",本节的安全基线管"工作负载以什么方式运行、与谁能通信"。这两类约束不冲突,应叠加使用。
5.1 Pod 安全标准(Pod Security Standards)
从 Kubernetes 1.25 起,PodSecurityPolicy 被移除,改用内置的 Pod Security Standards(PSS):
| 级别 | 含义 | 适合 |
|---|---|---|
privileged | 无限制 | 系统组件(CNI、CSI、kube-proxy) |
baseline | 禁止已知提权手段(hostPath、hostNetwork、privileged 等) | 大多数业务应用 |
restricted | 最严格,强制 runAsNonRoot、readOnlyRootFilesystem、drop ALL capabilities | 安全要求最高的应用 |
# 为 Namespace 设置安全策略标签
kubectl label ns learning \
pod-security.kubernetes.io/enforce=baseline \
pod-security.kubernetes.io/warn=restricted
enforce:违反策略的 Pod 会被拒绝创建;warn:违反时仅发出警告,不拒绝;audit:违反时记录审计日志。
生产上从 warn 开始观察,再逐步切到 enforce。
5.2 NetworkPolicy:Pod 间通信白名单
NetworkPolicy 可以限制 Pod 的入站和出站流量,但是否生效取决于 CNI 是否支持(Calico、Cilium 支持;Flannel 默认不支持)。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-policy
namespace: learning
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: api
policyTypes:
- Ingress
- Egress
# 入站:允许同 Namespace 中带 frontend 标签的 Pod 访问 8080 端口
ingress:
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: frontend
ports:
- protocol: TCP
port: 8080
# 出站:只允许 DNS 和同 Namespace 内通信
egress:
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- to:
- podSelector:
matchLabels:
app.kubernetes.io/name: database
ports:
- protocol: TCP
port: 5432
5.3 生产基线汇总
- 为每个 Namespace 启用
pod-security.kubernetes.io/enforce=baseline; - 通过准入策略限制特权容器、hostPath、未签名镜像和
latest(可借助 OPA/Gatekeeper 或 kube-linter,见第 21 章); - 网络策略从可观察、灰度启用开始——不要直接全局拒绝;
- 权限、Pod 安全、网络策略三者组合,才是完整的 Namespace 安全边界(呼应第 3 章的"Namespace 不是安全边界")。
6. 练习
练习 A
- 创建一个 ServiceAccount + Role(只读 Pod)+ RoleBinding
- 验证权限:
kubectl auth can-i get pods --as=system:serviceaccount:learning:<sa-name> -n learning - 尝试
kubectl auth can-i delete pods --as=...,确认被拒绝
练习 B
- 创建 ClusterRole 允许读 nodes,用 ClusterRoleBinding 绑定到某 Namespace 的 ServiceAccount,验证跨 Namespace 权限
- 给 Pod 配置专属 SA +
automountServiceAccountToken: false,确认默认 token 不再挂载 - 审计集群中的
cluster-admin绑定:kubectl get clusterrolebinding -o wide | grep cluster-admin,思考哪些可以收敛