每个运维都经历过这个场景:Pod 报 403 Forbidden,日志里没有任何有用信息,最后发现是 ServiceAccount 权限没给够。RBAC 真不复杂,但四个概念一旦搞混,排查直接干到凌晨三点。

本系列共 3 集:上集拆解四个核心概念 → 中集手把手搭建权限体系 → 下集进阶要点 + 排坑指南。建议按顺序阅读。


一、开篇

1. 经典场景:403 Forbidden

$ kubectl get pods

这是 K8s 运维最常见的报错之一。给开发开了集群权限,他随手 kubectl delete pod 干掉了生产数据库——然后你就成了那个"把权限管好"的人。

2. RBAC 三元组:谁 + 什么 + 怎么做

K8s 的权限管理就一个核心问题:谁(Subject)能对什么东西(Resource)做什么操作(Verb)。RBAC 用四个概念把这个三元组组织起来:

  • User / ServiceAccount:谁(主体)
  • Role / ClusterRole:能做啥操作 + 操作哪些资源(权限规则)
  • RoleBinding / ClusterRoleBinding:把主体和权限绑在一起(绑定关系)

3. 概念关系图

一眼看穿全貌——权限就是 Subject 经过 Binding 拿到 Role 的过程:

┌──────────────┐     ┌──────────────────┐     ┌──────────────┐
│    Subject    │────▶│     Binding      │────▶│     Role     │
│   (Who)      │     │    (How)         │     │   (What)     │
├──────────────┤     ├──────────────────┤     ├──────────────┤
│ User         │     │ RoleBinding      │     │ Role         │
│ (自然人)      │     │ (命名空间级绑定)   │     │ (命名空间级)   │
│              │     │                  │     │              │
│ ServiceAccount│    │ ClusterRoleBinding│    │ ClusterRole  │
│ (Pod/程序身份) │     │ (集群级绑定)      │     │ (集群级)      │
└──────────────┘     └──────────────────┘     └──────────────┘

4. 权限校验完整链路

一个 kubectl 请求到达 API Server 后,要过三道关卡——RBAC 在第二关:

 kubectl 请求
      │
      ▼
┌─────────────┐
│  Authentication │ ← 我是谁?(证书/OIDC/Token 验证身份)
│  (认证)        │      X509 证书 → CN=用户, O=组
└──────┬──────┘
       │ 通过,拿到 User/Group 身份
       ▼
┌─────────────┐
│  Authorization  │ ← 我能做什么?(RBAC 检查)
│  (授权)        │      遍历所有 RoleBinding/ClusterRoleBinding
└──────┬──────┘      匹配到规则 → 允许,匹配不到 → 403
       │ 通过
       ▼
┌─────────────┐
│  Admission      │ ← 请求合不合规?(Webhook 校验,可选)
│  (准入控制)     │
└──────┬──────┘
       │ 通过
       ▼
   ┌────────┐
   │  API Server  │ → 执行操作
   └────────┘

RBAC 处于 授权(Authorization) 这一环。认证不归 RBAC 管,但认证产出的 User/Group 身份是 RBAC 的输入。


二、四个核心概念,逐个拆解

1. User:人的身份

1.1 概念

K8s 不管理 User 对象——也就是没有 kubectl create user 这个命令。User 由集群外部的认证系统管理:

认证方式 身份来源 例子
X509 客户端证书 证书 CN = 用户名,O = 组 CN=zhangsan,O=dev-team → User zhangsan,组 dev-team
OIDC / OAuth2 ID Token 中的 sub/email 接入企业 LDAP、GitHub OAuth
Webhook Token 自定义认证服务 自建 Token 验证服务
Static Token File 静态 CSV 文件 --token-auth-file=/etc/kubernetes/tokens.csv

关键认知:User 是给人用的。平时 kubectl 操作集群,身份就是一个 User(通常来自 kubeconfig 里的客户端证书)。

1.2 生产实战:从零给一个用户签发证书并授权

这是最常用的场景——给一个新同事开通集群访问权限。完整流程分 5 步走。


第 1 步:找到集群 CA 证书

签发客户端证书需要集群的 CA 公钥和私钥。如果不记得放在哪了,可以通过下面方式查:

# 方式 1:kubeadm 默认路径(最常用)
ls /etc/kubernetes/pki/
# → ca.crt(公钥)  ca.key(私钥)
# 部分发行版在 /etc/kubernetes/ssl/,文件名为 ca.pem / ca-key.pem

# 方式 2:从 kube-apiserver 进程参数反查(最靠谱)
ps aux | grep kube-apiserver | grep -o '\-\-client-ca-file=[^ ]*'
# 输出示例:
#   --client-ca-file=/etc/kubernetes/pki/ca.crt
#   --client-ca-file=/etc/kubernetes/ssl/ca.pem
# 私钥通常在同目录,命名为 ca.key / ca-key.pem

CA 文件路径和扩展名(.crt / .pem)因发行版而异,以方式 2 查到的为准。私钥是高权限文件(root 只读),签发时需要 root 身份。

第 2 步:编写证书签名请求(CSR)

CSR 里有两个关键字段:CN = 用户名,O = 组名(后面 RBAC 授权就靠这个组)。

cat > zhangsan-csr.json <<EOF
{
  "CN": "zhangsan",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "dev-team",
      "OU": "System"
    }
  ]
}
EOF

第 3 步:用集群 CA 签发客户端证书

签发需要 ca-config.json(cfssl 签发策略配置),集群不自带,自己建一个:

# 3a. 创建签发策略文件(如果还没有)
cat > ca-config.json <<EOF
{
  "signing": {
    "default": { "expiry": "87600h" },
    "profiles": {
      "kubernetes": {
        "usages": ["signing", "key encipherment", "server auth", "client auth"],
        "expiry": "87600h"
      }
    }
  }
}
EOF

# 3b. 用集群 CA 签发客户端证书
# 注意:-ca 和 -ca-key 路径用上一步查到的实际路径
cfssl gencert \
  -ca=/etc/kubernetes/ssl/ca.pem \
  -ca-key=/etc/kubernetes/ssl/ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes zhangsan-csr.json | cfssljson -bare zhangsan
# → 产出三个文件:
#   zhangsan.pem      客户端证书(公钥)
#   zhangsan-key.pem  客户端私钥
#   zhangsan.csr      证书签名请求(可删)

第 4 步:生成 kubeconfig 文件

分四小步:写集群信息 → 写用户凭证 → 创建上下文 → 设为默认。

#查找集群地址
[root@master-1 rbac]# kubectl config view --raw | grep server
    server: https://192.168.91.254:6443
# 4a. 写入集群信息
# ca 路径和 --server 地址替换为你的集群实际值
kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=https://192.168.91.254:6443 \
  --kubeconfig=zhangsan.kubeconfig

# 4b. 写入用户凭证
kubectl config set-credentials zhangsan \
  --client-certificate=zhangsan.pem \
  --client-key=zhangsan-key.pem \
  --embed-certs=true \
  --kubeconfig=zhangsan.kubeconfig

# 4c. 创建上下文(关联用户 + 集群)
kubectl config set-context zhangsan@kubernetes \
  --cluster=kubernetes \
  --user=zhangsan \
  --kubeconfig=zhangsan.kubeconfig

# 4d. 设为默认上下文
kubectl config use-context zhangsan@kubernetes \
  --kubeconfig=zhangsan.kubeconfig

第 5 步:分发 kubeconfig + 验证

# 把 kubeconfig 发给用户
scp zhangsan.kubeconfig zhangsan@192.168.91.21:~/.kube/config

# 用户验证——现在应该是 403(认证过了,但还没授权)
KUBECONFIG=~/.kube/config kubectl get pods
# → Error: Forbidden(属于预期——下一步就是配 RoleBinding)

重点:证书签完之后,用户身份就有了(认证 OK),但还没有任何权限(授权未配)。下一步就是在集群侧创建 RoleBinding 把 dev-team 这个 Group 绑定到对应 Role——这就是下一节要讲的内容。

2. ServiceAccount:Pod 的身份

跟 User 相反,ServiceAccount 是 K8s 原生管理的资源,用于给 Pod 里的程序一个身份:

# 创建一个 ServiceAccount
kubectl create sa my-app-sa -n prod

# 查看
kubectl get sa my-app-sa -n prod -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: prod

每个 namespace 有一个默认的 ServiceAccount default——如果创建 Pod 时不指定 serviceAccountName,用的就是这个。

关键认知:ServiceAccount 是给程序(Pod)用的。当应用需要调用 K8s API(比如读取 ConfigMap、创建 Pod),它用的身份就是 ServiceAccount。

3. Role / ClusterRole:权限规则

3.1 概念:命名空间级 vs 集群级

Role 是命名空间级别的权限集合,ClusterRole 是集群级别的。Role 只在指定 namespace 内生效,ClusterRole 跨所有 namespace。

3.2 Role 示例
# Role:只能操作 prod 命名空间内的 pods 和 configmaps
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: prod
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get"]
3.3 ClusterRole 示例
# ClusterRole:可以操作所有命名空间的 pods
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
3.4 什么时候用哪个?
场景 用 Role 用 ClusterRole
只操作某个 namespace 的资源 ✅(但 overkill)
操作所有 namespace 的资源
操作集群级资源(Node、PV、Namespace 本身)
操作非资源端点(/healthz、/metrics)
3.5 常见 Verb(操作动词)
Verb 含义 典型场景
get 读取单个资源 kubectl get pod xyz
list 列出资源列表 kubectl get pods
watch 监听资源变化 Controller/Operator 必备
create 创建资源 部署应用
update 更新资源 修改配置
patch 部分更新资源 HPA 调整副本数
delete 删除单个资源 清理 Pod
deletecollection 批量删除 kubectl delete pods --all

4. RoleBinding / ClusterRoleBinding:绑定关系

4.1 概念:把 Subject 和 Role 关联起来

Binding 把 Subject(User/ServiceAccount)和 Role/ClusterRole 关联起来。没有 Binding,Role 只是一堆规则,谁也拿不到。

4.2 RoleBinding 示例
# RoleBinding:把 zhangsan 这个 User 绑定到 pod-reader Role
# → zhangsan 在 prod 命名空间里可以 get/list/watch pods
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: zhangsan-can-read-pods
  namespace: prod
subjects:
- kind: User
  name: zhangsan
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
4.3 ClusterRoleBinding 示例
# ClusterRoleBinding:把 my-app-sa 这个 ServiceAccount 绑定到 cluster-pod-reader
# → 这个 SA 在所有命名空间都可以 get/list/watch pods
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: app-sa-can-read-pods
subjects:
- kind: ServiceAccount
  name: my-app-sa
  namespace: prod
roleRef:
  kind: ClusterRole
  name: cluster-pod-reader
  apiGroup: rbac.authorization.k8s.io
4.4 Binding 的四种组合
Binding 类型 绑定的 Role 类型 作用范围 用法
RoleBinding + Role Role(命名空间级) 仅当前 namespace 给开发只读权限
RoleBinding + ClusterRole ClusterRole(集群级) 仅当前 namespace 复用集群级规则但限制在单个 ns
ClusterRoleBinding + ClusterRole ClusterRole(集群级) 整个集群 给监控系统读全集群
ClusterRoleBinding + Role ❌ 不可能 Role 没有跨命名空间的能力

三、总结

1. 四个概念一句话速记

概念 一句话 谁在用
User 人的身份,K8s 不管理,靠外部证书/OIDC 认证 你敲 kubectl 的时候
ServiceAccount 程序的身份证,K8s 原生资源,自动挂载到 Pod 你的应用调 K8s API 的时候
Role / ClusterRole 权限规则(能对哪些资源做什么操作) 没有它,谁也动不了资源
RoleBinding / ClusterRoleBinding 把 Subject 和 Role 绑一起的绳子 不绑 = 有身份也没权限

2. 核心认知总结

  • 权限生效链路:Subject(我是谁)→ Binding(谁和权限绑定了)→ Role(能做什么)。从左到右,缺一环就 403。
  • 请求校验顺序:认证(Authentication)→ 授权(RBAC)→ 准入(Admission)。RBAC 只管第二关,但第一关产出的 User/Group 是它的输入。
  • User vs SA:User 给人、SA 给程序。User 通过证书的 CNO(组)定义;SA 通过 serviceAccountName 挂载到 Pod。
  • Role vs ClusterRole:Role 局限在单个 namespace,ClusterRole 跨所有 ns。用 RoleBinding 引用 ClusterRole 可以实现"复用一个集群级规则但限制在单个 ns"。
  • Group 优于 User:证书的 O 字段就是天然的 RBAC Group。通过 Group 授权,新人入职只需签发证书,RBAC 配置不用动。

3. 还差一步

学完这四个概念,知识结构是:

✅ 知道 User 和 ServiceAccount 分别给谁用
✅ 知道 Role 和 ClusterRole 的作用范围区别
✅ 知道 Binding 的四种组合
✅ 会签发客户端证书生成 kubeconfig
❌ 还不会搭建一套完整的权限体系(开发组只读 + 运维组管理)

别急,这就是中集的内容。

📺 下集预告:「从零搭建 K8s 权限体系:开发组只读 + 运维组管理」——手把手走两个递进案例:先给单个用户授权,再给 Group 授权。每一步都能跟着敲。

更多推荐