首页 / Kubernetes (k8s) 入门教程 / 认证与鉴权概览

Kubernetes (k8s) 入门教程

认证与鉴权概览

本教程共 65 篇 · 第 43 篇 · 更新于 2026-08-14 · 约 13 分钟阅读

Kubernetes认证鉴权访问控制RBAC准入控制安全

本节目标:搞懂你敲下 kubectl get pods 之后,这个请求在 API 服务器里到底过了几道安检,以及每道安检各管什么。

前面几十章我们一直在”造东西”——建 Pod、发 Service、挂存储。这些操作能成功,是因为你手里那份 ~/.kube/config 权限很大。但生产集群不是这样的:开发只能看自己命名空间,CI 只能改 Deployment,监控组件只能读不能写。

这套”谁能干什么”的规则,就是本章要讲的访问控制。

43-1 一个请求要过四道关

先记住一张流程图。任何访问 Kubernetes API 的请求,都要依次经过:

  1. 传输安全——TLS 加密通道,先确认你连的是真的 API 服务器。
  2. 认证(Authentication)——你是谁?拿不出身份就 401。
  3. 鉴权(Authorization)——你有权做这件事吗?没权限就 403。
  4. 准入控制(Admission Control)——请求内容本身合规吗?不合规直接打回。

四关全过,对象才会被校验并写进 etcd。

用一个生活比方:进公司大楼。刷门禁卡证明”我是员工”,这是认证;卡的权限决定你能不能刷开机房门,这是鉴权;进机房还要签保密协议、换防静电鞋,这是准入控制。三件事完全不同,别混着记。

Note

顺序不能颠倒。鉴权一定发生在认证之后——系统得先知道你是谁,才能判断你能干什么。准入控制又在鉴权之后,只有被允许的请求才会走到那一步。

43-2 传输安全:先建起加密通道

API 服务器默认在第一个非 localhost 网络接口的 6443 端口监听,全程 TLS 保护。典型生产集群会对外暴露 443 端口。

服务端出示证书,证书可以由集群内的私有 CA 签发,也可以来自公认的 CA。启动参数 --tls-cert-file--tls-private-key-file 指定证书和私钥,--secure-port 改端口,--bind-address 改监听地址。

如果集群用的是私有 CA(kubeadm 装出来的集群就是这样),你的 ~/.kube/config 里必须带一份该 CA 证书的副本。否则 kubectl 无法验证服务端身份,会直接报证书不受信任。

集群内部组件之间——apiserver、controller-manager、scheduler、kubelet、etcd——走的是双向 TLS(mTLS)。双方都要出示证书,不是只验证服务端。这套证书体系依赖那个自签名 CA,所以 CA 私钥泄露等于整个集群通信全线失守

Warning

CA 证书只在集群内部使用,别把它设置成系统级可信 CA。如果 API 服务器还要和集群外组件通信(比如外部 Webhook),推荐用两套独立的信任根:内部组件一套,外部组件一套。

43-3 认证:证明你是谁

TLS 建好以后,请求进入认证阶段。

认证组件的输入是整个 HTTP 请求,但实际上通常只看请求头和客户端证书。Kubernetes 支持的认证方式主要有这几类:

  • 客户端证书——最常见,kubeadm 给管理员发的就是这个。
  • Bearer Token——放在 Authorization: Bearer <token> 请求头里。
  • ServiceAccount 的 JWT 令牌——工作负载(Pod)访问 API 用的就是它,详见第 45 章。
  • 引导令牌(Bootstrap Token)——节点加入集群时临时用。
  • 静态密码文件——已不推荐,只在很老的集群里见得到。

可以同时配置多个认证组件。API 服务器会一个个试,直到有一个成功。全都失败就返回 HTTP 401

认证成功后,你会被识别为一个具体的 username,部分认证器还会同时给出你所属的组(Group)。这个用户名和组名会传给后面的鉴权阶段用。

这里有个反直觉的点,很多人第一次学会懵:

Tip

Kubernetes 里没有 User 这种资源对象。 你不能 kubectl create user zhangsan。用户名只是认证阶段产出的一个字符串,Kubernetes 既不存储用户,也不管用户从哪来。真正被 Kubernetes 当作对象管理的身份只有 ServiceAccount

也就是说,人类用户的身份由外部系统提供——证书、OIDC 提供商、LDAP 网关等等。Kubernetes 只负责认这个结果。

43-4 鉴权:判断你能干什么

请求被确认来自某个用户后,进入鉴权。

鉴权的第一原则是默认拒绝。请求的每一部分都必须被某个鉴权机制放行,才能继续往下走。

鉴权看哪些属性

Kubernetes 只审查这些请求属性,不多也不少:

属性含义
用户(user)认证阶段得到的用户名
组(group)用户所属的组名列表
额外信息(extra)认证层附加的键值对
API 组被访问的 API 组,空字符串代表核心组
资源(resource)资源类型或名称,如 pods
子资源(subresource)statusscalelog
名字空间(namespace)仅命名空间级资源有
请求动词(verb)get/list/create/update
请求路径非资源端点,如 /api/healthz

注意”动词”不是 HTTP 方法本身。Kubernetes 会做一层映射:

HTTP 方法请求动词
POSTcreate
GETHEADget(单个)、list(集合)、watch(监听)
PUTupdate
PATCHpatch
DELETEdelete(单个)、deletecollection(集合)
Warning

getlistwatch 都能拿到资源的完整内容,就返回数据来说它们是等价的。对 secrets 授予 list 权限,等于把所有 Secret 的 data 字段都给出去了。这个坑我见过不少人踩——以为”只是列个清单,应该没事”。

六种鉴权模式

API 服务器通过 --authorization-mode 参数配置启用哪些模式:

  • RBAC——基于角色的访问控制。用 rbac.authorization.k8s.io API 组驱动决策,可以通过 API 动态配置策略。这是现在的绝对主流,第 44 章专门讲。
  • Node——专用模式,根据 kubelet 上实际调度了哪些 Pod,来决定放行它的哪些请求。生产集群一般和 RBAC 一起开。
  • Webhook——把鉴权决策同步 HTTP 外调给远端服务,阻塞等待响应。灵活但有单点故障风险,外部引擎挂了 API 服务器就没法完成鉴权。
  • ABAC——基于属性的访问控制,策略写在文件里,改了要重启 API 服务器。基本被 RBAC 取代了。
  • AlwaysAllow——放行一切。
  • AlwaysDeny——拒绝一切,只用于测试。
Warning

绝对不要在 API 服务器能从公网访问的集群上启用 AlwaysAllow。而且它有传染性:--authorization-mode=AlwaysAllow,RBAC 的效果等同于只写 AlwaysAllow,因为 RBAC 不提供”拒绝”规则,只会返回”批准”或”无意见”,而 AlwaysAllow 会把所有”无意见”变成放行。

多个模块怎么协同

配置了多个鉴权模块时,按顺序逐个检查:

  • 任何一个模块批准拒绝,立即返回该结论,不再问后面的模块。
  • 所有模块都无意见,请求被拒绝,返回 HTTP 403 Forbidden

生产集群最常见的组合是 Node,RBAC

43-5 准入控制:请求还得再过一遍筛子

鉴权通过了,不代表请求内容没问题。

准入控制器能做两件鉴权做不到的事:它能看到正在创建或修改的对象的完整内容,而且它能改这个对象

举几个实际例子:

  • 给没写 resources 的容器自动补上默认的 CPU/内存限额(LimitRanger)。
  • 拒绝以 root 身份运行的 Pod(Pod 安全准入,第 46 章)。
  • 给每个新命名空间自动注入 Sidecar 或标签(自定义 Webhook,第 57 章)。

几个要点:

  • 准入控制器只对 createupdatedeleteconnect(代理)这类请求起作用,纯读取请求不经过它
  • 配置了多个控制器时按顺序调用。
  • 和认证、鉴权不同:任何一个准入控制器拒绝,请求立即失败,不存在”某一个放行就通过”。

请求过完所有准入控制器,才会走对象校验例程,然后写入 etcd。

43-6 审计:留下证据

前面四关管的是”拦住不该做的事”。审计(Audit)管的是”记下已经做过的事”。

Kubernetes 审计功能会按时间顺序记录集群里的操作序列——谁、什么时候、对什么对象、做了什么、结果如何。用户操作、通过 API 访问的应用、控制平面自身的活动,都在记录范围内。

这个功能默认不开,需要手动配置审计策略文件和后端。真出了安全事件,没有审计日志基本就是两眼一抹黑。

除了 API 服务器,容器运行时、kubelet 也各有自己的日志。要串起来分析,通常的做法是每个节点跑一个 DaemonSet 日志代理,统一送到中心化的日志库。

43-7 自查权限:kubectl auth can-i

理论讲完,给你一个每天都能用上的命令。

# 我能在 default 命名空间创建 Pod 吗?
kubectl auth can-i create pods --namespace default

# 我能删除节点吗?
kubectl auth can-i delete nodes

# 列出我在当前命名空间的全部权限
kubectl auth can-i --list

输出就是 yesno,干脆利落。

管理员还能用 --as 模拟别人来查——排查”为什么他报 Forbidden”时特别好用:

# 以 dev 命名空间的 ci-bot 服务账号的身份检查
kubectl auth can-i update deployments \
  --namespace dev \
  --as system:serviceaccount:dev:ci-bot

注意那个身份格式:system:serviceaccount:<命名空间>:<名称>。ServiceAccount 在认证层就是这么一个用户名,前缀 system: 是 Kubernetes 内部保留的。

想看当前 kubeconfig 用的是谁,可以查:

kubectl config view --minify -o jsonpath='{.contexts[0].context.user}'

43-8 新手常踩的三个坑

第一,把 401 和 403 搞混。 401 是认证失败——证书过期、Token 无效,系统不知道你是谁。403 是鉴权失败——知道你是谁,但你没这个权限。看到 401 去查凭据,看到 403 去查 RBAC 规则,方向完全不同。

第二,以为 cluster-admin 是”临时方便一下”。 遇到 403 就把 cluster-admin 绑上去,问题当然立刻消失,然后就再也没人回来收紧。正确做法是用 kubectl auth can-i 定位到缺的那一条动词,只补那一条。

第三,忘了 Pod 也是 API 的客户端。 集群里每个 Pod 默认都挂载着 ServiceAccount 令牌,能访问 API 服务器。虽然默认权限很小,但大多数应用根本不需要访问 API。对这类 Pod,把 automountServiceAccountToken 设为 false 是白捡的安全收益:

apiVersion: v1
kind: Pod
metadata:
  name: no-api-access
spec:
  automountServiceAccountToken: false
  containers:
    - name: app
      image: nginx:1.27

小结

这一章没有太多要动手配的东西,主要是把地图铺开:

  • 传输安全解决”连的对不对”,认证解决”你是谁”,鉴权解决”你能干什么”,准入控制解决”这个请求内容行不行”。
  • 认证失败 401,鉴权失败 403,两者排查方向不同。
  • 鉴权默认拒绝,多模块中任一批准即通过;准入控制反过来,任一拒绝即失败。
  • Kubernetes 不存储人类用户,只管理 ServiceAccount

接下来第 44 章进入 RBAC——把”谁能干什么”真正落成 YAML。