kube-apiserver 请求处理流程
kube-apiserver 请求处理流程
概述
kube-apiserver 是 Kubernetes 控制平面的核心组件,负责处理所有 API 请求。每个请求都需要经过认证(Authentication)、授权(Authorization)、准入控制(Admission Control) 才能被持久化到 etcd。
核心处理流程
1 | ┌──────────────────────────────────────────────────────────────────────────────┐ |
关键代码路径
1. 请求入口
- 文件:
staging/src/k8s.io/apiserver/pkg/server/config.go - 函数:
DefaultBuildHandler.ServeHTTP() - 位置: 约 145 行
2. 认证流程
- 文件:
staging/src/k8s.io/apiserver/pkg/authentication/authenticator.go - 接口:
RequestAuthenticator - 实现类:
X509Authenticator- 客户端证书认证BearerAuthenticator- Token 认证BootstrapAuthenticator- Bootstrap Token 认证OIDCAuthenticator- OIDC 认证
3. 授权流程
- 文件:
staging/src/k8s.io/apiserver/pkg/authorization/authorizer/interfaces.go - 接口:
Authorizer.Authorize(ctx, Attributes) - 实现类:
RBACAuthorizer- RBAC 授权ABACAuthorizer- ABAC 授权NodeAuthorizer- Node 授权WebhookAuthorizer- Webhook 授权
4. 准入控制
- 文件:
staging/src/k8s.io/apiserver/pkg/admission/chain.go - 阶段:
- Mutating 阶段: 修改请求内容
- Validating 阶段: 验证请求有效性
- 内置插件:
NamespaceLifecycle- 命名空间生命周期LimitRanger- 资源限制ServiceAccount- 服务账号DefaultStorageClass- 默认存储类ResourceQuota- 资源配额PodSecurity- Pod 安全策略
5. etcd 存储
- 文件:
staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go - 核心方法:
Create()- 创建对象Get()- 获取对象Update()- 更新对象Delete()- 删除对象Watch()- 监听变更
请求处理详细流程
认证流程
1 | 1. 从请求中提取认证信息 |
授权流程
1 | 1. 构建 authorizer.Attributes |
准入控制流程
1 | 1. Mutating 阶段 (按顺序执行) |
etcd 交互
1 | 1. 序列化对象 |
关键配置参数
| 参数 | 说明 | 默认值 |
|---|---|---|
--anonymous-auth |
是否允许匿名请求 | true |
--client-ca-file |
客户端 CA 证书文件 | - |
--enable-admission-plugins |
启用的准入插件 | - |
--authorization-mode |
授权模式 | AlwaysAllow |
--etcd-servers |
etcd 服务器地址 | http://127.0.0.1:2379 |
--encryption-provider-config |
加密配置 | - |
常见问题排查
1. 认证失败
- 检查证书是否有效
- 检查 Token 是否过期
- 检查 ServiceAccount 是否存在
2. 授权失败
- 检查 RoleBinding/ClusterRoleBinding
- 检查 Role 的规则定义
- 检查用户是否在正确的 Group 中
3. 准入控制被拒绝
- 检查准入插件日志
- 检查 ResourceQuota 是否足够
- 检查 LimitRange 是否满足
4. etcd 写入失败
- 检查 etcd 匇标
- 检查磁盘空间
- 检查网络连接
面试题
基础题
1. kube-apiserver 请求处理的完整流程是什么?
参考答案:
1 | 请求 -> 认证(Authentication) -> 授权(Authorization) -> 准入控制(Admission Control) -> etcd 存储 |
详细步骤:
- 认证:验证请求者身份(证书、Token、OIDC等)
- 授权:检查请求者是否有权限执行该操作(RBAC、ABAC、Node等)
- 准入控制:
- Mutating 阶段:修改请求内容
- Validating 阶段:验证请求有效性
- 存储:持久化到 etcd
2. kube-apiserver 支持哪些认证方式?
参考答案:
- X509 客户端证书:最常用的方式
- Bearer Token:静态 Token 或 ServiceAccount JWT
- Bootstrap Token:用于集群引导
- OIDC:OpenID Connect 集成
- Webhook:外部认证服务
- Anonymous:匿名请求(默认开启)
- Request Header:前端代理认证
3. 准入控制的两个阶段分别是什么?有什么区别?
参考答案:
| 阶段 | 作用 | 示例插件 |
|---|---|---|
| Mutating | 修改请求内容 | DefaultStorageClass、LimitRanger、ServiceAccount |
| Validating | 验证请求有效性 | ResourceQuota、PodSecurity、NamespaceLifecycle |
执行顺序:先执行所有 Mutating 插件,再执行 Validating 插件。
中级题
4. RBAC 授权的检查流程是怎样的?
参考答案:
- 从请求中提取用户信息和操作属性(verb、resource、namespace等)
- 遍历所有 ClusterRoleBinding 和 RoleBinding
- 匹配 Subject(User/Group/ServiceAccount)
- 获取绑定的 Role/ClusterRole 的 PolicyRules
- 检查是否有规则匹配当前请求
- 返回 DecisionAllow 或 DecisionNoOpinion
关键代码路径:plugin/pkg/auth/authorizer/rbac/rbac.go
5. 如果多个授权器同时存在,授权决策是如何做出的?
参考答案:
使用 Union Authorizer(联合授权器):
- 按顺序遍历所有授权器
- 任一授权器返回
DecisionAllow→ 允许 - 任一授权器返回
DecisionDeny→ 拒绝 - 所有授权器返回
DecisionNoOpinion→ 拒绝
1 | // staging/src/k8s.io/apiserver/pkg/authorization/union/union.go |
6. 解释 ResourceVersion 的作用和乐观并发控制机制。
参考答案:
ResourceVersion 是对象的乐观锁机制:
- 每次对象更新,ResourceVersion 会变化
- 更新时携带旧的 ResourceVersion
- 如果 etcd 中的版本与请求不匹配,更新失败(409 Conflict)
1 | # 更新失败示例 |
用途:
- 防止并发更新冲突
- Watch 请求的起始点
- List 请求的一致性保证
7. kube-apiserver 如何处理高并发请求?
参考答案:
**API Priority and Fairness (APF)**:
- 按优先级分级(system、workload、default等)
- 每个分级有独立的并发限制
- 公平调度防止饿死
MaxInFlight 限制:
--max-requests-inflight:非 mutating 请求限制--max-mutating-requests-inflight:mutating 请求限制
Watch 缓存:
- Cacher 提供 List/Watch 缓存
- 减少 etcd 直接访问
高级题
8. 描述 AggregatorServer、KubeAPIServer、APIExtensionsServer 三者的关系和请求流转。
参考答案:
1 | 请求 -> AggregatorServer -> KubeAPIServer -> APIExtensionsServer |
委托链(Delegation Chain):
- AggregatorServer:处理聚合 API(如 metrics-server)
- KubeAPIServer:处理核心 Kubernetes API(Pod、Service等)
- APIExtensionsServer:处理 CRD 定义的 API
请求先到达 Aggregator,如果无法处理则委托给下一个,形成责任链模式。
9. etcd 交互中,Cacher 的作用是什么?如何保证 Watch 的一致性?
参考答案:
Cacher 作用:
- 内存缓存,减少 etcd 压力
- 为 List/Watch 请求提供数据
- 维护 watchCache 和 listWatch
Watch 一致性保证:
- ResourceVersion:每个事件携带版本号
- Bookmark:定期发送书签事件,保持连接
- ProgressNotify:通知客户端当前版本
- 反射器(Reflector):通过 listAndWatch 保持缓存同步
10. 如何实现一个自定义的准入控制 Webhook?
参考答案:
1. 创建 Webhook 服务:
1 | // 接收 AdmissionReview 请求 |
2. 配置 Webhook:
1 | apiVersion: admissionregistration.k8s.io/v1 |
11. kube-apiserver 如何保证高可用?
参考答案:
- 多实例部署:运行多个 kube-apiserver 实例
- 负载均衡:前端使用 LB(如 HAProxy、云 LB)
- 无状态设计:所有状态存储在 etcd
- etcd 集群:奇数节点(3/5/7),Raft 共识
12. 审计日志(Audit)的工作原理是什么?
参考答案:
审计日志记录所有 API 请求:
1. 审计策略配置:
1 | apiVersion: audit.k8s.io/v1 |
2. 审计阶段:
RequestReceived:收到请求ResponseStarted:响应开始ResponseComplete:响应完成Panic:发生 panic
场景题
13. 用户报告 kubectl get pods 返回 403 Forbidden,如何排查?
参考答案:
排查步骤:
检查用户认证:
1
kubectl auth whoami
检查 RBAC 绑定:
1
2
3
4
5# 检查 RoleBinding
kubectl get rolebinding -n <namespace>
# 检查 ClusterRoleBinding
kubectl get clusterrolebinding模拟授权检查:
1
kubectl auth can-i get pods --as=<username> -n <namespace>
常见原因:
- 缺少 RoleBinding
- Role 中没有 get pods 权限
- namespace 不匹配
- 用户不在正确的 Group 中
14. 大量 List 请求导致 etcd 压力过大,如何优化?
参考答案:
使用 Informer 缓存:
1
2
3
4
5informer := cache.NewSharedIndexInformer(
&cache.ListWatch{...},
&corev1.Pod{},
time.Hour * 12,
)使用 Limit 和 Continue:
1
kubectl get pods --limit=100
使用 ResourceVersion:
1
kubectl get pods --resource-version=12345
调整 etcd 配置:
- 增加
--quota-backend-bytes - 使用 SSD 存储
- 增加
15. 自定义资源(CRD)的请求处理流程与内置资源有何不同?
参考答案:
| 特性 | 内置资源 | CRD |
|---|---|---|
| API 定义 | 编译时 | 运行时 |
| Schema 验证 | Go 代码 | OpenAPI v3 |
| 版本转换 | 编译时 | Webhook(可选) |
| 准入控制 | 内置 | Webhook |
| 性能 | 更优 | 略低(需要反射) |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Joohwan!
评论

