深色模式
RBAC 权限与最小授权
摘要:本文讲清 K8s RBAC 的四个对象与两组绑定关系,演示为运维人员和 CI 系统创建最小权限账号、用
kubectl auth can-i验证权限边界,并列出危险的过度授权写法。
适用环境
- 可用 K8s 集群 +
kubectl(需要有创建 Role/ClusterRole 的权限) - 示例在一个测试命名空间
dev中操作
操作步骤
一、RBAC 四个对象
| 对象 | 作用范围 | 说明 |
|---|---|---|
Role | 单个命名空间 | 定义一组权限规则 |
ClusterRole | 全集群 | 同上,另可用于集群级资源(nodes、pv) |
RoleBinding | 单个命名空间 | 把 Role 授予主体 |
ClusterRoleBinding | 全集群 | 把 ClusterRole 授予主体 |
主体(subject)有三种:User(人)、Group(组)、ServiceAccount(应用)。
关键认知:权限只在 Role 里定义,绑定决定谁获得。 只有 Role 没有 Binding 等于没授权。
二、为运维人员创建只读权限
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: dev
name: dev-readonly
rules:
- apiGroups: ["", "apps", "networking.k8s.io"]
resources: ["pods", "services", "deployments", "ingresses", "configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-readonly-binding
namespace: dev
subjects:
- kind: User
name: zhangsan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: dev-readonly
apiGroup: rbac.authorization.k8s.io1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
verbs 取值:get、list、watch、create、update、patch、delete、deletecollection。
三、为 CI 系统创建 ServiceAccount
bash
kubectl create serviceaccount ci-deployer -n dev1
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: dev
name: ci-deployer
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "create", "update", "patch"]
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ci-deployer-binding
namespace: dev
subjects:
- kind: ServiceAccount
name: ci-deployer
namespace: dev
roleRef:
kind: Role
name: ci-deployer
apiGroup: rbac.authorization.k8s.io1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
四、生成 kubeconfig 给外部系统用
bash
kubectl -n dev create token ci-deployer --duration=8760h1
拿到 token 后填入 kubeconfig 的 users[].user.token 字段即可。注意 token 默认有时效,长期凭证要考虑轮换。
五、验证权限(最重要的习惯)
bash
kubectl auth can-i list pods -n dev --as=zhangsan
kubectl auth can-i delete pods -n dev --as=zhangsan
kubectl auth can-i get secrets -n dev --as=system:serviceaccount:dev:ci-deployer
kubectl auth can-i '*' '*' # 我是不是集群管理员
kubectl auth can-i list pods -n dev --as=zhangsan --list # 列出全部权限1
2
3
4
5
2
3
4
5
六、让 Pod 内应用调用 API
yaml
spec:
serviceAccountName: ci-deployer
containers:
- name: app
image: nginx:alpine1
2
3
4
5
2
3
4
5
不指定时会用命名空间下的 default ServiceAccount。
危险
以下写法等于把集群完全交出去,生产严禁使用:
yaml
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]1
2
3
4
2
3
4
尤其不要把 cluster-admin 绑定到应用用的 ServiceAccount——容器一旦被入侵,攻击者直接控制整个集群(可借此拉到所有 Secret、创建特权 Pod 提权到宿主机)。
七、审计现有过度授权
bash
kubectl get clusterrolebindings -o wide
kubectl get clusterrolebinding -o json \
| jq -r '.items[] | select(.roleRef.name=="cluster-admin") | .metadata.name + " -> " + (.subjects[]?.name // "")'
kubectl get rolebinding,clusterrolebinding -A -o custom-columns=KIND:.kind,NS:.metadata.namespace,NAME:.metadata.name,ROLE:.roleRef.name1
2
3
4
2
3
4
八、用内置 ClusterRole
bash
kubectl get clusterroles | head -20
kubectl create rolebinding dev-admin --clusterrole=admin --user=zhangsan -n dev
kubectl create rolebinding dev-view --clusterrole=view --user=lisi -n dev1
2
3
2
3
内置的有 view(只读)、edit(读写,不含权限和配额)、admin(命名空间内几乎全部)、cluster-admin(全集群)。
验证
- [ ]
kubectl auth can-i对授权项返回 yes、对未授权项返回 no - [ ] 用受限 kubeconfig 删除 Pod 时被
forbidden拒绝 - [ ] CI 账号能更新 Deployment 但不能读 Secret
常见坑
- RoleBinding 引用了 ClusterRole 却能跨命名空间:这是设计特性——ClusterRole 可被 RoleBinding 引用并降级到单个命名空间生效,用于复用规则模板。
- 改了 Role 但权限没变:RoleBinding 的
roleRef不可修改,必须删掉重建绑定。 kubectl auth can-i和实际行为不一致:can-i 只做静态检查,不考虑准入控制 webhook 的额外拦截。- Pod 报
Forbidden: User system:serviceaccount:default:default cannot get:没配 ServiceAccount 或没绑 Role。 - 忘记给
pods/log单独授权:有 pods 的 get 权限不代表能看日志,日志是独立子资源。