第 11 章 认证与授权¶
配套实验手册:《Kubernetes 实验手册》(manual/ 目录)实验 09「认证与授权」(Lab 1-6:证书目录/用户证书/SA/用户授权/SA 授权/dashboard 综合演练)。本章讲安全模型的前两道门:认证(你是谁)与授权(你能干什么)——理解它们,就理解了"为什么能登录但不让操作"这类核心现象。第 12 章讲第三道门(准入控制)。
学习目标¶
学完本章,你应该能够:
- 说出 Kubernetes 安全模型的三道门(认证/授权/准入)与各自回答的问题
- 区分两种身份(User 给人、ServiceAccount 给程序)与两种认证凭据(证书/Token)
- 解释 X.509 证书认证的机制(CA 签发、CN 即用户名、kubeconfig 携带)
- 解释 v1.24+ 的 SA Token 机制(动态签发,无长期 token)
- 完整解释 RBAC 三要素(Subject/Role/ClusterRole/Binding)与两种范围
- 写出自定义 Role 的 rules(apiGroups/resources/verbs)
- 解释"认证 ≠ 授权"(能登录但 Forbidden)并用实例说明
- 应用最小权限原则设计授权方案(含
kubectl auth can-i验证)
11.1 安全模型总览:三道门¶
第 2 章 §2.4.1 讲过 apiserver 的请求处理流程,安全部分展开就是三道门:
flowchart LR
req[/"客户端请求"/] --> auth["① 认证\nAuthentication\n(你是谁?)"]
auth --> authz["② 授权\nAuthorization\n(你能干什么?)"]
authz --> admit["③ 准入控制\nAdmission\n(请求合法吗?)"]
admit --> ok["写入 etcd"]
auth -. "失败" .-> d1["401\nUnauthorized"]
authz -. "失败" .-> d2["403\nForbidden"]
admit -. "失败" .-> d3["拒绝\n(策略不符)"]
style auth fill:#E8F4FD,stroke:#4A90D9
style authz fill:#E8F4FD,stroke:#4A90D9
style admit fill:#E8F4FD,stroke:#4A90D9
style ok fill:#E8F8E8,stroke:#5BA85B
style d1 fill:#FDECEA,stroke:#D94F4F
style d2 fill:#FDECEA,stroke:#D94F4F
style d3 fill:#FDECEA,stroke:#D94F4F
读图要点:三道门依次通过、各自有独立的拒绝出口——认证失败 401、授权失败 403、准入失败策略不符;"能登录但不让操作"就是第一道门过了、第二道门没过。
| 门 | 问题 | 拒绝结果 | 对应实验 |
|---|---|---|---|
| 认证 | 你是谁? | 401 Unauthorized | Lab 1/2 |
| 授权 | 你能干什么? | 403 Forbidden | Lab 3/4/5 |
| 准入 | 请求本身合法吗? | Forbidden/校验错误 | 实验 09 Lab 7/8 |
核心认知:三道门依次通过——认证通过但授权不足 → Forbidden("能登录但不让操作");授权通过但准入拦截 → 也拒绝(第 12 章)。
11.2 认证:你是谁¶
11.2.1 两种身份¶
| 身份 | 给谁用 | 凭据 | 用户名格式 |
|---|---|---|---|
| User | 人(管理员/开发) | 客户端证书 / token | train、train |
| ServiceAccount(SA) | 程序(Pod 内应用) | Token(Bearer) | system:serviceaccount:<ns>:<名字> |
注意:Kubernetes 没有 User 对象(User 是"外部概念",通过证书 CN 识别);SA 是真实对象(存在集群里)。
11.2.2 认证方式(apiserver 支持的)¶
- X.509 客户端证书(最常用):kubeconfig 里带证书,apiserver 用 CA 校验签名
- Bearer Token:SA 的 token(HTTP 头
Authorization: Bearer <token>) - 基础认证(用户名/密码,一般不启用)
- OIDC(企业单点登录,见下)
- 其他(Webhook 认证等)
OIDC 企业集成(生产人员认证的事实标准):
企业环境里"给每个人签发证书"不可行(人进人出、证书管理爆炸)——人员认证几乎 100% 对接 OIDC(Keycloak/Dex/企业 SSO):
用户 → 企业 SSO 登录(Keycloak/AD/Okta)→ 拿 ID Token(JWT)
→ kubectl 用 token 访问 apiserver
→ apiserver 的 OIDC 认证器验证签名 → 提取 username/groups(来自 token 声明)
→ 之后的 RBAC 照常工作(username/groups 参与授权)
- 配置:apiserver 加
--oidc-issuer-url/--oidc-client-id/--oidc-username-claim/--oidc-groups-claim(kubeadm 环境改 manifest) - 好处:统一账号体系(员工离职一个按钮禁用)、支持 MFA、组(groups)随 SSO 自动映射到 RBAC
- 实操:
kubectl oidc-login插件完成登录换 token 流程(进阶)
核心认知:证书认证适合"少量管理员",OIDC 适合"大量企业用户"——考试不考 OIDC 配置,但真实企业环境绕不开。
11.2.3 X.509 证书认证的机制¶
第 3 章安装时生成了集群 CA(第 2 章 §2.6.3 双向 TLS)。用户证书认证的完整链路:
① 管理员用 CA 签发用户证书:openssl 生成密钥 → 用 ca.key 签发
· 证书的 CN(Common Name)= 用户名(如 CN=train → 用户 train)
· O(Organization)= 用户组
② kubeconfig 里配置:cluster(apiserver 地址 + CA)+ user(客户端证书)+ context
③ 请求时:kubectl 出示客户端证书 → apiserver 用 CA 校验签名 → 通过
④ 认证结果:用户名 = 证书 CN(如 train),进入授权环节
核心认知:"签发证书"就是"创建用户"——集群没有用户注册表,信任链就是 CA 签名。证书泄露 = 身份泄露(所以私钥要保管好)。
11.2.4 ServiceAccount 与 Token(v1.24+ 的重要变化)¶
SA 是给 Pod/程序用的身份:Pod 可以指定 serviceAccountName,容器内自动挂载 SA 的 token 文件——应用用它调 apiserver。
v1.24+ 的变化(实验 09 Lab 2 实测):
- 旧机制:SA 创建时自动生成一个长期 token secret(永不过期)——安全风险:泄露就永远有效
- 新机制:不再自动创建 token secret;用
kubectl create token <sa>动态签发短期 token(默认 1 小时,过期重新签发)——安全得多
考试/实操注意:
kubectl describe secret找 token 是旧版做法;v1.36 用kubectl describe secret。
11.2.5 kubeconfig 多身份(第 2 章 §2.8.2 深化)¶
一个 kubeconfig 可以装多个 cluster/user/context——用 context 切换身份:
这就是"同一台机器上,管理员和普通用户身份并存"的实现——实验 09 Lab 1/2 亲手建了多个 context。
11.3 授权:你能干什么(RBAC)¶
11.3.1 RBAC 三要素¶
RBAC(基于角色的访问控制) 的核心是三个对象:
Group(用户组)绑定机制:Subject 不只是单个 User/SA——Group(组)可以整体授权,管理成本大幅下降:
① 来源:证书的 O(Organization)字段 = 组名(如 CN=train, O=devs → 用户 train 属于 devs 组)
OIDC 的 groups claim = 组(第 11.2.2 节)
② 绑定:给组授权,组里所有用户生效
kubectl create clusterrolebinding devs-readonly --clusterrole=view --group=devs
③ 内置特殊组:
- system:masters → 绑定 cluster-admin 的超级管理员组(kubeadm 的 admin.conf 用户在此组)
- system:serviceaccounts:<ns> → 某命名空间的所有 SA
- system:authenticated → 所有认证通过的用户
认知:给"组"授权是生产惯例(人进人出只改 SSO 组成员,不改 K8s 绑定);
system:masters是最高权限组(第 3 章 super-admin.conf 的 O 字段就是它)。
Subject: User train ──┐
▼
ClusterRoleBinding ──► ClusterRole: cluster-admin(全权)
(全集群生效) Role: dev-role(自定义只读 dev 资源)
11.3.2 Role vs ClusterRole(权限的范围)¶
| Role | ClusterRole | |
|---|---|---|
| 作用域 | 命名空间内(如 default 里) | 全集群(所有命名空间 + 集群级资源) |
| 管理什么 | 该命名空间的 Pod/Svc 等 | 全部命名空间 + Node/PV/Namespace 等集群资源 |
| 创建时 | 必须指定命名空间 | 无命名空间 |
注意(易混点):Role 是"权限集合",范围由绑定方式决定——ClusterRole 被 RoleBinding 绑定时,只在那个命名空间生效(实验 09 Lab 4 实测:权限范围被限制在绑定命名空间)。
11.3.3 RoleBinding vs ClusterRoleBinding(生效范围)¶
| RoleBinding | ClusterRoleBinding | |
|---|---|---|
| 生效范围 | 一个命名空间 | 全集群 |
| 授权对象 | 该命名空间内的资源权限 | 所有命名空间 + 集群级资源 |
| 可绑定的角色 | Role 或 ClusterRole | Role(仅本命名空间?不——ClusterRoleBinding 绑 Role 会报错,只能绑 ClusterRole) |
准确规则:RoleBinding 可以绑 Role 或 ClusterRole(绑 ClusterRole 时限制在命名空间内);ClusterRoleBinding 只能绑 ClusterRole(全集群生效)。
11.3.4 rules 写法(自定义权限)¶
Role/ClusterRole 的核心是 rules——"对哪些资源的哪些操作":
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: dev-role
namespace: default
rules:
- apiGroups: [""] # 核心组(Pod/Service/ConfigMap 等)
resources: ["pods", "pods/log"] # 资源(pods/log 是子资源)
verbs: ["get", "list", "watch"] # 操作(读)
- apiGroups: ["apps"] # apps 组(Deployment 等)
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # 读写
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["get", "list", "watch", "create"]
三要素写法(CKA 必考):
- apiGroups:API 组——核心组用
""(空字符串),""、""、""等(第 2 章 §2.7.1;查法:""看 APIGROUP 列) - resources:资源名(复数)——pods/services/deployments/nodes...(子资源如
pods/log) - verbs:get/list/watch/create/update/patch/delete(
*表示全部)
常见错误:写错了 apiGroups(核心组写成 "core"/"v1")→ 权限不生效(返回 Forbidden)——先
kubectl api-resources确认 APIGROUP。
11.3.5 内置角色(现成的权限模板)¶
| 角色 | 范围 | 能力 |
|---|---|---|
cluster-admin |
全集群 | 超级管理员(绑给 admin.conf) |
admin |
命名空间 | 命名空间内全权(含 RBAC 管理) |
edit |
命名空间 | 读写(不含 RBAC) |
view |
命名空间 | 只读 |
常用组合:普通开发 → view/edit;项目负责人 → admin;运维/管理员 → cluster-admin。优先用内置角色,不够再自定义。
11.3.6 认证 vs 授权(核心辨析)¶
证书有效(认证通过)≠ 有权限(授权通过)
实例(实验 09 Lab 1/3):
① 签发用户证书 train → kubectl 能连上 apiserver(认证通过)
② 但 get pods → Forbidden:pods is forbidden: User "train" cannot list resource "pods"
(授权未配置——train 没有任何 Role/Binding)
③ 创建 ClusterRoleBinding(cluster-admin → train)→ 立刻能操作
(授权是即时生效的,不需要重启任何组件)
一句话:认证回答"你是谁",授权回答"你能干啥"——"能登录"和"能操作"是两件独立的事,这是本章最重要的认知。
11.4 最小权限设计¶
11.4.1 原则¶
最小权限(Least Privilege):只给完成工作所需的最小权限。
- 开发只读 → view;要改配置 → edit;不要给所有人 cluster-admin
- 按团队/项目拆分命名空间 + RoleBinding(隔离授权范围)
- SA 只挂自己需要的权限(Pod 不该有集群管理权限)
- 定期审计:谁的权限过期了、谁还挂着 cluster-admin
11.4.2 验证工具:kubectl auth can-i¶
不用真试就能检查"某个身份能不能做某个操作":
kubectl auth can-i get pods # 当前身份
kubectl auth can-i create deployments --as=dev-user # 模拟 dev-user
kubectl auth can-i list secrets --as=system:serviceaccount:default:my-sa
实战价值:给权限之前先验证、给完再验证一次;排障"为什么 Forbidden"时用它确认是授权没配还是规则写错。
11.5 实验演练指引¶
本章机制对应实验 09「认证与授权」 Lab 1-6:
- Lab 1 生成用户证书:openssl 用 CA 签发 train 证书 + kubeconfig 三段式——认证≠授权的 Forbidden 实例(§11.2.3/11.3.6)
- Lab 2 创建 SA:
kubectl create token动态签发——v1.24+ 新机制(§11.2.4) - Lab 3 给用户授权:ClusterRoleBinding + 自定义 Role rules——三要素写法(§11.3.4)
- Lab 4 给 SA 授权:RoleBinding 命名空间级 + 跨命名空间失败——两种 Binding 对比(§11.3.3)
- Lab 5 用户证书 API 方式(补充):CSR API 签发证书(进阶)
- Lab 6 dashboard 综合演练:SA + RBAC + Token 完整链路(§11.2-11.4 的"总装")
教学建议:Lab 1 重点体验"认证通过但 Forbidden";Lab 3/4 对比两种 Binding 的生效范围;Lab 6 是把全章机制串起来的综合演练(浏览器输 Token 登录的背后就是本章全部机制)。
本章小结¶
- 三道门:认证(你是谁)→ 授权(你能干啥)→ 准入(请求合法吗)——依次通过
- 认证:User(人,证书 CN 即用户名)/ SA(程序,动态 token);签发证书 = 创建用户;v1.24+ 用
kubectl create token动态签发 - RBAC 三要素:Subject + Role/ClusterRole + Binding——Role 定权限内容、Binding 定生效范围
- 两种范围:Role(命名空间)/ClusterRole(集群);RoleBinding(命名空间)/ClusterRoleBinding(全集群);RoleBinding 绑 ClusterRole 时限制在命名空间内
- rules 三要素:apiGroups(核心组
"")/resources(复数)/verbs——写错 apiGroups 是最常见错误 - 内置角色:cluster-admin/admin/edit/view——优先内置,不够自定义
- 认证 ≠ 授权:Forbidden 实例(能登录但不让操作);授权即时生效
- 最小权限:够用就行 +
kubectl auth can-i验证
衔接:第 12 章讲第三道门(准入控制与容器安全)——PSA 强制安全标准、SecurityContext 容器加固;第 13 章讲集群级安全(证书续期/etcd 加密)。
思考题¶
- "签发一张用户证书"在 Kubernetes 里相当于"创建一个用户"——为什么?
- v1.24 之前 SA 自动创建长期 token,为什么被改掉?
- Role 与 ClusterRole、RoleBinding 与 ClusterRoleBinding 的交叉组合,生效范围分别是什么?
- 自定义 Role 里
apiGroups: [""]是什么意思?写成apiGroups: [""]会怎样? - 用户 train 证书有效但 get pods 报 Forbidden——问题出在哪道门?怎么修?
- 给一个"只能看 default 命名空间 Pod 和日志"的账号,写出完整的 RBAC 方案(Role + Binding + 验证命令)。
CKA 考点标注(对应域 1/2/3,考试高频): - 必考操作:
kubectl create role/clusterrole/rolebinding/clusterrolebinding、kubectl create role/clusterrole/rolebinding/clusterrolebinding、kubectl create role/clusterrole/rolebinding/clusterrolebinding、kubectl create role/clusterrole/rolebinding/clusterrolebinding- 必考机制:RBAC 三要素与范围规则(Role vs ClusterRole、两种 Binding)、rules 三要素、认证 vs 授权 - 高频场景题:给用户/SA 配权限(场景 → Role/Binding 组合)、跨命名空间访问失败排查 - 排障关联(域 5):Forbidden(授权未配/规则写错)——kubectl auth can-i定位