路线图

RBAC 权限管理

星辉 2026-07-02 阅读 5 min 906 字 路线图
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 TokenServiceAccount 的 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 上。

text
用户/ServiceAccount  →  (RoleBinding/ClusterRoleBinding)  →  Role/ClusterRole  →  具体权限

二、ServiceAccount / Role / ClusterRole 四层结构#

RBAC 的核心由四个资源类型组成。理解它们各自的职责和关系是正确配置权限的关键。

2.1 ServiceAccount(SA)—— 身份#

ServiceAccount 是 Pod 在集群内的"身份证"。每个 Namespace 下都有一个默认的 default SA,但强烈建议不要使用它,而是为每个应用创建独立的 SA。

text
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 组""(核心组)、appsbatch
resources资源类型podsdeploymentsconfigmaps
verbs允许的操作getlistwatchcreateupdatedelete
yaml
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 的结构完全相同,但作用范围是整个集群。两种使用场景:

  1. 集群级资源:Node、PV、StorageClass、Namespace 这类不属于任何 Namespace 的资源,只能用 ClusterRole 授权
  2. 跨 Namespace 复用:定义一个 ClusterRole 后,可以分别在多个 Namespace 中用 RoleBinding 绑定,避免重复定义
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-reader
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list", "watch"]

2.4 四层关系总结#

text
┌─────────────────────────────────────────────────────┐
│                    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 引用。

yaml
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.io

3.2 ClusterRoleBinding#

ClusterRoleBinding 将 ClusterRole 在全集群范围授予指定身份。权限不受 Namespace 限制。

yaml
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.io

3.3 RoleBinding vs ClusterRoleBinding 速查#

绑定类型引用角色类型生效范围典型场景
RoleBinding + RoleRole单 Namespace应用自身权限
RoleBinding + ClusterRoleClusterRole单 Namespace(被限定)跨 Namespace 复用权限模板
ClusterRoleBinding + ClusterRoleClusterRole全集群监控组件、日志采集、集群管理员

3.4 常见踩坑#

坑1:混淆 RoleBinding 和 ClusterRoleBinding 的作用范围

yaml
# 错误意图:只想给 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:通配符权限"方便测试"

yaml
# 绝对不要在生产环境出现
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]

3.5 验证权限#

bash
# 检查某个 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#

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.io

4.3 获取 Token 供 CI 使用#

bash
# 创建长期有效的 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 -d

4.4 权限验证#

bash
# 确认 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: no

4.5 实战要点#

  1. 按需添加 verbs:如果后续 CI 需要 delete 旧 ReplicaSet,再单独加上,不要一开始给全套
  2. 限定 resourceNames:如果 CI 只操作几个固定服务,用 resourceNames: ["my-app", "my-worker"] 进一步缩小范围
  3. Token 定期轮换:CI Token 不要永久有效,建议每季度轮换
  4. 不挂载 SA Token 到 PodautomountServiceAccountToken: false 防止 CI Pod 被攻破后获取集群权限

小结#

RBAC 的核心是四个资源的组合关系:

  • ServiceAccount 提供身份,本身没有权限
  • Role / ClusterRole 定义权限规则集
  • RoleBinding / ClusterRoleBinding 将身份和权限绑定

配置时的思考顺序应该是:先想清楚"谁"需要在"哪个范围"做"什么操作",再从这三个维度推导出需要哪些 RBAC 资源。最小权限原则意味着:能用 Role 就不用 ClusterRole,能用 RoleBinding 就不用 ClusterRoleBinding,能给具体资源名就尽量限定。

日常运维中,kubectl auth can-i --as=... 是验证权限是否符合预期的第一工具,建议每次配置 RBAC 后都立刻验证。