APF 基础概念:API优先级与公平性(APF)的工作原理与设计目标
在 Kubernetes 集群中,API 服务器(kube-apiserver)是所有控制面操作的唯一入口。当集群规模扩大或出现异常流量时,请求洪峰可能导致 API 服务器过载,进而影响核心组件(如调度器、控制器管理器)的正常通信。API 优先级与公平性(APF)正是为了解决这一问题而设计的原生流量管理机制。
1. 设计目标:从“无差别拒绝”到“分级保障”
APF 的核心设计目标是在请求过载时,确保高优先级、关键控制面操作(如 Pod 调度、节点心跳)不被低优先级请求(如大规模 List 操作、kubectl 查询)饿死。其设计遵循以下原则:
| 目标 | 说明 | 解决的传统痛点 |
|---|---|---|
| 优先级隔离 | 将请求按重要性分为多个优先级级别,不同级别之间互不抢占配额 | 一个 Namespace 的批量 List 操作阻塞所有 Watch 请求 |
| 公平排队 | 同一优先级内,多个 FlowSchema 按权重公平分配并发资源 | 某个异常客户端持续发送请求,挤占同优先级其他客户端的资源 |
| 过载保护 | 当全局并发超过阈值时,优先拒绝低优先级请求,保障控制面存活 | 突发流量导致 API Server OOM 或全端口拒绝 |
| 无锁设计 | APF 使用无锁队列和原子操作,避免排队本身成为性能瓶颈 | 传统限流器在高并发下自身锁竞争严重 |
关键认知: APF 不是简单的“限流器”,而是一个带有优先级感知的“流量调度系统”。它允许集群管理员在容量不足时,主动决定“谁可以继续工作,谁需要等待或重试”。
2. 核心工作原理:FlowSchema、PriorityLevelConfig 与排队机制
APF 的工作流程可以抽象为三个核心组件:FlowSchema(流量模式匹配)、PriorityLevelConfig(优先级级别配置)和排队队列(公平调度)。
3. 核心数据结构:FlowSchema 与 PriorityLevelConfig
APF 通过两个 CRD 资源来定义流量管理策略:
3.1 FlowSchema(流量模式)
FlowSchema 负责将请求分类。每个请求到达 API Server 后,会按顺序匹配 FlowSchema 列表,匹配到第一个即停止。匹配规则支持基于 请求用户、用户组、资源、命名空间、Verb(操作类型) 等属性。
apiVersion: flowcontrol.apiserver.k8s.io/v1beta3
kind: FlowSchema
metadata:
name: kube-controller-manager
spec:
priorityLevelConfiguration:
name: workload-high # 关联的优先级级别
rules:
- subjects:
- kind: ServiceAccount
serviceAccount:
name: kube-controller-manager
namespace: kube-system
resourceRules:
- verbs: ["*"]
apiGroups: ["*"]
resources: ["*"]
3.2 PriorityLevelConfig(优先级级别)
PriorityLevelConfig 定义每个优先级级别的并发配额和排队行为。关键参数包括:
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
assuredConcurrencyShares |
int32 | 该级别在全局并发中的权重占比 | 根据级别不同 |
queues |
int32 | 该优先级下的队列数量(用于公平排队) | 64 |
handSize |
int32 | 每个队列可分配的并发槽位数 | 8 |
queueLengthLimit |
int32 | 单个队列的最大排队深度 | 50 |
实践要点: 在集群容量调优时,
assuredConcurrencyShares 是最常调整的参数。例如,将 workload-high 的 shares 从 30 提升到 50,可以确保调度器和控制器在负载高峰时获得更多并发资源。
4. 公平排队算法:如何避免“饿死”
APF 使用基于 QueueSet 的公平排队算法。同一优先级内的多个 FlowSchema 共享一组队列,每个 FlowSchema 根据其权重被分配到特定数量的队列上。算法保证:
- 权重公平性: 权重高的 FlowSchema 获得更多队列,从而获得更多并发处理机会。
- 无锁竞争: 每个队列独立维护,请求入队和出队操作无需全局锁。
- 过载丢弃: 当队列深度超过
queueLengthLimit时,新请求直接返回 429 Too Many Requests,避免队列无限增长。
5. 内置优先级级别:开箱即用的分级保障
Kubernetes 默认创建了多个 PriorityLevelConfig,覆盖了从系统关键操作到用户查询的完整链路:
| 优先级级别 | 典型用途 | AssuredConcurrencyShares | 是否可修改 |
|---|---|---|---|
system |
节点心跳、kubelet 关键操作 | 30 | 不建议 |
workload-high |
调度器、控制器管理器、核心控制器 | 40 | 可调优 |
workload-low |
普通控制器、Operator 协调循环 | 30 | 可调优 |
global-default |
未匹配到其他 FlowSchema 的请求 | 20 | 可调优 |
catch-all |
兜底级别,防止请求丢失 | 5 | 不建议 |
exempt |
完全免于限流(如 kube-apiserver 自身健康检查) | N/A | 不可修改 |
注意:
exempt 级别的请求不经过任何排队和限流,直接执行。只有关键的内部通信才应使用此级别。误用可能导致 API Server 过载时无法保护自身。
6. APF 与传统限流器(MaxRequestsInFlight)的对比
| 特性 | 传统 MaxRequestsInFlight | APF(API 优先级与公平性) |
|---|---|---|
| 优先级支持 | 无,所有请求一视同仁 | 多级优先级,支持隔离 |
| 公平排队 | 无,先到先服务 | 基于 QueueSet 的公平排队 |
| 过载行为 | 全局拒绝,高优请求也被拒绝 | 按优先级分级拒绝,保障关键请求 |
| 可观测性 | 仅提供全局拒绝计数 | 提供每个 FlowSchema 和 PriorityLevel 的排队深度、拒绝率、等待时间等指标 |
| 配置灵活性 | 仅一个全局参数 | 通过 CRD 动态调整,无需重启 API Server |
| 适用场景 | 小型集群或测试环境 | 生产环境、大规模集群、多租户场景 |
升级建议: 从 Kubernetes 1.20 开始,APF 进入 Beta 并默认启用。如果你的集群仍在使用
--max-requests-inflight 和 --max-mutating-requests-inflight 参数,建议迁移到 APF,以获得更精细的流量控制能力。