最近在学习CKS时,修改kubelet认证模式这道题,ai说mode改为Webhook会直接造成死锁,后对这个参数进行学习,总结如下:
k8s的三种认证模式
1、AlwaysAllow
行为:全部请求直接放行,不做任何授权校验,kubelet 收到请求,不去调用 apiserver,本地直接允许访问kubelet API (10250)
2、Webhook(一般为云厂商托管场景,且cacheAuthorizedTTL不为0)
行为:kubelet 自己不做权限判断,发 SubjectAccessReview 请求给 apiserver,由 RBAC 做授权判决
- 请求会 HTTP 回调 apiserver 做鉴权;可以配置鉴权缓存
cacheAuthorizedTTL - ⚠️ 风险点:control‑plane 节点 + cacheAuthorizedTTL:0s + exec/logs/top‑node,高并发存在 goroutine 耗尽竞争死锁
- worker 节点使用 Webhook 完全无死锁风险。
3、AlwaysDeny
行为:全部访问 kubelet 的请求全部拒绝,一律 403.
一般为测试调试,几乎不会生产使用。 开启后:exec/logs/top node 全部失效,kubelet 拒绝所有外部调用。
配置文件
配置文件:/var/lib/kubernetes/config.conf
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous:
enabled: false
webhook:
cacheTTL: 0s
enabled: true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 0s
cacheUnauthorizedTTL: 0s
命令是否调用apiserver
| 命令 | 是否 apiserver 代理 kubelet | 是否会触发 master 上 Webhook+TTL=0 死锁风险 |
|---|---|---|
| get pod / get node / apply/delete | ❌不访问 kubelet | ❌无风险 |
| exec / logs / attach / cp / port‑forward / top node | ✅apiserver 代理到 kubelet | ✅操作 master 本机 pod 时存在竞争死锁风险;worker pod 无风险 |
| top pod | ❌metrics‑server 直连 kubelet | ❌无风险 |
触发死锁完整流程(master,Webhook,TTL=0)
kubectl exec→ 发给 apiserver。- apiserver 需要执行容器 exec,发起网络请求访问本机 kubelet:10250。
- apiserver 的一个 goroutine(工人 A) 发起这个调用,然后阻塞等待 kubelet 返回 exec 结果。👉 工人 A 被占住,不干别的,就等 kubelet。
- kubelet 收到 apiserver 过来的请求;因为
mode:Webhook+TTL=0无缓存。 kubelet 必须向外发SubjectAccessReview请求,问 apiserver:这个调用者有权访问我 kubelet 吗? - kubelet 把鉴权请求又打回同一台机器的 apiserver。
- apiserver 收到这个鉴权请求,需要拿另一个空闲 goroutine(工人 B)来处理鉴权、查 RBAC、返回 yes/no。
✅ 如果此时还有空闲工人 B:鉴权完成,kubelet 放行 exec,整个流程全部成功,就是你刚才测试正常的现象。
🚨 如果所有 apiserver goroutine 全部用光了:包括工人 A 在内,全部都在等待各类外部 IO(等待 kubelet、等待 etcd 等)。 新来的鉴权请求没有空闲 goroutine 去执行处理。
- kubelet 就在那里傻傻等待鉴权响应,收不到回复。
- apiserver 的工人 A 还在傻傻等待 kubelet 返回 exec。 两边都在等对方,没有工人干活,就卡死。