RBAC 权限管理
概述#
Kubernetes 的安全体系中有两个核心概念:认证(Authentication) 和 授权(Authorization)。认证回答"你是谁",授权回答"你能做什么"。本章聚焦于 RBAC(Role-Based Access Control),这是 K8s 最常用的授权模式。我们将从概念讲起,逐步深入到实战配置,帮助你建立清晰的权限管理思维。
一、认证 vs 授权#
在理解 RBAC 之前,首先要搞清楚认证和授权的职责分界线。
1.1 认证(Authentication):你是谁#
认证是请求进入 K8s 集群的第一道门。API Server 接收到请求后,首先要确认"这个请求是谁发起的"。K8s 支持多种认证方式:
| 认证方式 | 说明 | 适用场景 |
|---|---|---|
| X.509 客户端证书 | TLS 双向认证,证书中嵌入用户/组信息 | kubelet 与 apiserver 通信、集群管理员 |
| Bearer Token | 静态 Token(较少用)、ServiceAccount Token | ServiceAccount 的 Pod 内访问 |
| OpenID Connect (OIDC) | 对接外部身份提供商(如 Keycloak、Azure AD) | 企业多团队统一身份认证 |
| Webhook Token | 自定义 Token 验证服务 | 对接自建认证系统 |
当你执行 kubectl get pods 时,kubectl 会读取 ~/.kube/config 中的证书或 Token,将其发送给 API Server 完成认证。
1.2 授权(Authorization):你能做什么#
认证通过后,API Server 进入授权阶段:检查"这个用户/身份是否有权执行这个操作"。K8s 支持多种授权模式,可以组合使用:
| 授权模式 | 说明 |
|---|---|
| RBAC | 基于角色的访问控制,本章重点 |
| Node | 专门授权 kubelet 的操作(自动管理) |
| ABAC | 基于属性的访问控制(基于 JSON 策略文件,已不推荐) |
| Webhook | 调用外部服务做授权决策 |
RBAC 是 K8s 中最主流、最推荐的授权模式。它的核心思想是:不直接给用户授权,而是将权限绑定到"角色"上,再将角色绑定到用户或 ServiceAccount 上。
用户/ServiceAccount → (RoleBinding/ClusterRoleBinding) → Role/ClusterRole → 具体权限二、ServiceAccount / Role / ClusterRole 四层结构#
RBAC 的核心由四个资源类型组成。理解它们各自的职责和关系是正确配置权限的关键。
2.1 ServiceAccount(SA)—— 身份#
ServiceAccount 是 Pod 在集群内的"身份证"。每个 Namespace 下都有一个默认的 default SA,但强烈建议不要使用它,而是为每个应用创建独立的 SA。
Namespace: my-app
├── default ServiceAccount ← ⚠️ 默认 SA,权限模糊,不要用
├── ci-robot ServiceAccount ← 给 CI 机器人
└── my-service ServiceAccount ← 给业务应用关键点:
- SA 本身不携带任何权限,它只是一个"身份标识"
- SA 的权限完全由 RoleBinding/ClusterRoleBinding 赋予
automountServiceAccountToken: false可以禁止 Pod 自动挂载 SA Token(不需要访问 K8s API 的应用应该禁用)
2.2 Role —— Namespace 内的权限规则#
Role 定义了一组在特定 Namespace 内的权限规则。每条规则包含三要素:
| 要素 | 说明 | 示例 |
|---|---|---|
apiGroups | 资源所属的 API 组 | ""(核心组)、apps、batch |
resources | 资源类型 | pods、deployments、configmaps |
verbs | 允许的操作 | get、list、watch、create、update、delete |
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: my-app
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]2.3 ClusterRole —— 集群级权限规则#
ClusterRole 与 Role 的结构完全相同,但作用范围是整个集群。两种使用场景:
- 集群级资源:Node、PV、StorageClass、Namespace 这类不属于任何 Namespace 的资源,只能用 ClusterRole 授权
- 跨 Namespace 复用:定义一个 ClusterRole 后,可以分别在多个 Namespace 中用 RoleBinding 绑定,避免重复定义
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-reader
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]2.4 四层关系总结#
┌─────────────────────────────────────────────────────┐
│ ClusterRole │ ← 集群范围权限规则
│ (或 Role,仅限一个 Namespace) │
└────────────────────┬────────────────────────────────┘
│
┌──────────┴──────────┐
│ │
┌──────▼──────────┐ ┌──────▼───────────────┐
│ ClusterRoleBinding │ │ RoleBinding │ ← 胶水:把身份绑定到权限
│ (全集群生效) │ │ (单 Namespace 生效) │
└──────┬──────────┘ └──────┬───────────────┘
│ │
┌──────▼──────────────────────▼──┐
│ ServiceAccount │ ← 身份
│ (或 User / Group) │
└────────────────────────────────┘记忆口诀:
- SA = 身份证(你是谁)
- Role = 通行证模板(允许进哪些门)
- ClusterRole = 全院通行证模板(全院通用)
- Binding = 贴照片(把身份证和通行证绑定在一起)
三、RoleBinding / ClusterRoleBinding#
Binding 是 RBAC 中的"胶水层",把身份(SA/User/Group)和权限(Role/ClusterRole)绑定在一起。
3.1 RoleBinding#
RoleBinding 的作用是:将 Role(或 ClusterRole)授权给某个 Namespace 内的指定身份。
重点:RoleBinding 可以引用 ClusterRole,但绑定的效果仍然被限制在 RoleBinding 所在的 Namespace。这是一个非常实用的模式——定义一套 ClusterRole 模板,在各 Namespace 中用 RoleBinding 引用。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ci-robot-binding
namespace: my-app # 权限生效的 Namespace
subjects:
- kind: ServiceAccount
name: ci-robot # 授予谁
namespace: my-app
roleRef:
kind: ClusterRole # 可以引用 ClusterRole
name: deploy-role # 引用哪个角色
apiGroup: rbac.authorization.k8s.io3.2 ClusterRoleBinding#
ClusterRoleBinding 将 ClusterRole 在全集群范围授予指定身份。权限不受 Namespace 限制。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus-scraper-binding
subjects:
- kind: ServiceAccount
name: prometheus
namespace: monitoring
roleRef:
kind: ClusterRole
name: prometheus-scraper
apiGroup: rbac.authorization.k8s.io3.3 RoleBinding vs ClusterRoleBinding 速查#
| 绑定类型 | 引用角色类型 | 生效范围 | 典型场景 |
|---|---|---|---|
| RoleBinding + Role | Role | 单 Namespace | 应用自身权限 |
| RoleBinding + ClusterRole | ClusterRole | 单 Namespace(被限定) | 跨 Namespace 复用权限模板 |
| ClusterRoleBinding + ClusterRole | ClusterRole | 全集群 | 监控组件、日志采集、集群管理员 |
3.4 常见踩坑#
坑1:混淆 RoleBinding 和 ClusterRoleBinding 的作用范围
# 错误意图:只想给 my-sa 在 dev namespace 的只读权限
# 实际效果:给了 my-sa 全集群所有 namespace 的 Pod 读取权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding # ← 用了 ClusterRoleBinding!
metadata:
name: pod-reader
subjects:
- kind: ServiceAccount
name: my-sa
namespace: dev
roleRef:
kind: ClusterRole
name: view
# 正确:改用 RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader
namespace: dev # ← 范围限定!
subjects:
- kind: ServiceAccount
name: my-sa
namespace: dev
roleRef:
kind: ClusterRole
name: view
apiGroup: rbac.authorization.k8s.io坑2:通配符权限"方便测试"
# 绝对不要在生产环境出现
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]3.5 验证权限#
# 检查某个 SA 能否执行特定操作
kubectl auth can-i get pods \
--as=system:serviceaccount:my-app:my-sa \
-n my-app
# 列出某个 SA 的所有权限
kubectl auth can-i --list \
--as=system:serviceaccount:my-app:my-sa \
-n my-app
# 查看谁能 delete pods
kubectl who-can delete pods -n my-app # 需要 krew 插件四、实战:给 CI 机器人最小权限#
4.1 场景#
CI 流水线(GitLab CI / GitHub Actions)需要部署应用到 Namespace production,但只需要以下权限:
- 查看已有的 Deployment、Service、ConfigMap(
get/list/watch,用于判断是否需要更新) - 创建/更新/删除 Deployment 和 Service(
create/update/patch/delete,用于部署) - 不需要访问 Secret(敏感凭证不应暴露给 CI)
- 不需要跨 Namespace 操作
4.2 完整 YAML#
# 1. 创建专用 ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: ci-deployer
namespace: production
automountServiceAccountToken: false # CI 不需要在 Pod 内访问 API
---
# 2. 定义 CI 所需的最小权限 Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ci-deployer-role
namespace: production
rules:
# 只读权限:上线前查看当前状态
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch"]
# 写权限:实际部署操作
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["create", "update", "patch"]
- apiGroups: [""]
resources: ["services"]
verbs: ["create", "update", "patch"]
# 注:没有 Secret 的任何权限!
# 注:没有 delete 权限(防止误删)
---
# 3. RoleBinding 绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ci-deployer-binding
namespace: production
subjects:
- kind: ServiceAccount
name: ci-deployer
namespace: production
roleRef:
kind: Role
name: ci-deployer-role
apiGroup: rbac.authorization.k8s.io4.3 获取 Token 供 CI 使用#
# 创建长期有效的 Token(K8s v1.24+)
kubectl create token ci-deployer -n production --duration=8760h
# 或者创建 Secret 类型的 Token(兼容旧版)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: ci-deployer-token
namespace: production
annotations:
kubernetes.io/service-account.name: ci-deployer
type: kubernetes.io/service-account-token
EOF
# 提取 Token
kubectl get secret ci-deployer-token -n production \
-o jsonpath='{.data.token}' | base64 -d4.4 权限验证#
# 确认 CI SA 能创建 Deployment
kubectl auth can-i create deployments \
--as=system:serviceaccount:production:ci-deployer \
-n production
# expected: yes
# 确认 CI SA 不能读取 Secret
kubectl auth can-i get secrets \
--as=system:serviceaccount:production:ci-deployer \
-n production
# expected: no
# 确认 CI SA 不能跨 Namespace 操作
kubectl auth can-i get pods \
--as=system:serviceaccount:production:ci-deployer \
-n kube-system
# expected: no4.5 实战要点#
- 按需添加 verbs:如果后续 CI 需要
delete旧 ReplicaSet,再单独加上,不要一开始给全套 - 限定 resourceNames:如果 CI 只操作几个固定服务,用
resourceNames: ["my-app", "my-worker"]进一步缩小范围 - Token 定期轮换:CI Token 不要永久有效,建议每季度轮换
- 不挂载 SA Token 到 Pod:
automountServiceAccountToken: false防止 CI Pod 被攻破后获取集群权限
小结#
RBAC 的核心是四个资源的组合关系:
- ServiceAccount 提供身份,本身没有权限
- Role / ClusterRole 定义权限规则集
- RoleBinding / ClusterRoleBinding 将身份和权限绑定
配置时的思考顺序应该是:先想清楚"谁"需要在"哪个范围"做"什么操作",再从这三个维度推导出需要哪些 RBAC 资源。最小权限原则意味着:能用 Role 就不用 ClusterRole,能用 RoleBinding 就不用 ClusterRoleBinding,能给具体资源名就尽量限定。
日常运维中,kubectl auth can-i --as=... 是验证权限是否符合预期的第一工具,建议每次配置 RBAC 后都立刻验证。