2. APF基础架构:FlowSchema与PriorityLevelConfiguration资源对象详解、控制面请求分类原理
API Priority and Fairness (APF) 是 Kubernetes 1.20+ 默认启用的控制面请求排队与调度机制,替代了原有的 MaxInFlight 限流器。APF 的核心由两个 CRD 资源对象构成:FlowSchema 与 PriorityLevelConfiguration。理解这两个对象的字段语义与交互逻辑,是进行 Operator 控制面安全审计与性能调优的前提。
关键认知: FlowSchema 负责“分类”——将每个到达 apiserver 的请求归入某个“流”;PriorityLevelConfiguration 负责“调度”——为每个流分配独立的排队队列与并发预算。两者通过
spec.priorityLevelConfiguration 字段绑定。
2.1 FlowSchema:请求分类的规则引擎
FlowSchema 本质上是一组匹配规则,按 spec.matchPrecedence 升序评估。每个请求会命中第一个匹配的 FlowSchema,然后被分配到该 FlowSchema 引用的 PriorityLevelConfiguration。
| 字段路径 | 类型 | 说明 |
|---|---|---|
spec.matchPrecedence |
int32 | 匹配优先级,数值越小优先级越高。范围 1~10000,集群默认值通常为 1000。 |
spec.rules |
[]ResourcePolicyRule | 资源请求匹配规则列表,支持 verbs、apiGroups、resources、namespaces、clusterScope 等维度。 |
spec.rules[].subjects |
[]Subject | 非资源请求匹配主体,支持 User、Group、ServiceAccount。 |
spec.distinguisherMethod |
FlowDistinguisherMethod | 可选字段,定义如何区分同一 FlowSchema 内的不同“流”。常用值:ByUser、ByNamespace。 |
spec.priorityLevelConfiguration |
string | 绑定的 PriorityLevelConfiguration 名称,必须已存在。 |
审计要点: 检查是否存在
matchPrecedence 值相同且规则重叠的 FlowSchema,这会导致非确定性匹配,引发请求分类混乱。默认的 system-leader-election 与 workload-leader-election 常因 matchPrecedence 相同而产生竞态。
2.2 PriorityLevelConfiguration:并发控制与排队模型
每个 PriorityLevelConfiguration 定义了一个独立的调度队列,包含并发限制、排队策略与队列参数。APF 使用“公平排队 + 权重轮询”算法,确保高优先级请求不会被低优先级流量淹没。
| 字段路径 | 类型 | 说明 |
|---|---|---|
spec.type |
string | Limited 或 Exempt。Exempt 类型的请求不排队、不限并发,通常预留给系统关键组件。 |
spec.limited.nominalConcurrencyShares |
int32 | 名义并发份额,用于计算该级别可用的并发数。总并发数 = apiserver --max-requests-inflight × (该级别 shares / 所有级别 shares 之和)。 |
spec.limited.limitResponse.type |
string | 超限响应策略:Queue 或 Reject。推荐使用 Queue 避免直接丢弃请求。 |
spec.limited.limitResponse.queuing |
QueuingConfiguration | 排队参数:queues(队列数)、handSize(哈希种子数)、queueLengthLimit(队列深度)。 |
误报风险: 当
nominalConcurrencyShares 设置过小(如 1~3),且 queueLengthLimit 默认 50 时,Operator 的 List-Watch 请求极易触发队列满而返回 429。审计时需核对 Operator 使用的 ServiceAccount 所命中的 FlowSchema 的并发份额是否充足。
2.3 控制面请求分类完整流程
一个请求从到达 apiserver 到被放行或排队,经历以下 5 个阶段:
- 请求到达:apiserver 的 HTTP 处理链捕获请求,提取用户、组、资源、动词、命名空间等属性。
- FlowSchema 匹配:按
matchPrecedence升序遍历所有 FlowSchema,找到第一个匹配的规则。 - 流区分:如果 FlowSchema 定义了
distinguisherMethod,则根据该字段生成“流标识”;否则整个 FlowSchema 视为一个流。 - 优先级绑定:通过 FlowSchema 的
priorityLevelConfiguration引用找到对应的 PriorityLevelConfiguration。 - 排队与调度:根据 PriorityLevelConfiguration 的并发份额与排队参数,决定请求是立即执行、进入队列等待、还是被拒绝(429)。
2.4 默认 FlowSchema 与 PriorityLevelConfiguration 清单
Kubernetes 集群安装时会自动创建一组内置的 FlowSchema 和 PriorityLevelConfiguration。Operator 开发者必须了解这些默认对象,以避免自定义 FlowSchema 与内置规则冲突。
| FlowSchema 名称 | matchPrecedence | 绑定的 PriorityLevelConfiguration | 典型匹配对象 |
|---|---|---|---|
system-leader-election |
100 | leader-election |
kube-system 中的 leader election 请求 |
workload-leader-election |
200 | leader-election |
自定义 controller 的 leader election 请求 |
system-nodes |
500 | node-high |
kubelet 对 apiserver 的请求 |
system-service-accounts |
900 | workload-high |
kube-system 以外的 ServiceAccount 请求 |
global-default |
1000 | global-default |
未匹配任何规则的兜底请求 |
Operator 适配建议: 如果 Operator 使用自定义 ServiceAccount 且需要高频 List-Watch 操作,建议创建独立的 FlowSchema(
matchPrecedence 设为 800~899),并绑定一个 nominalConcurrencyShares 较高的 PriorityLevelConfiguration,避免与 system-service-accounts 共享默认的 workload-high 级别。
2.5 控制面请求分类原理:从属性提取到流哈希
APF 的分类引擎在内部将每个请求抽象为 FlowSchema 匹配 + 流区分 + 优先级映射 三个步骤。其中流区分通过 distinguisherMethod 生成一个哈希键,用于将同一 FlowSchema 内的请求分散到不同的队列中,实现公平性。
2.6 审计与误报复核关注点
- FlowSchema 匹配冲突:检查是否存在
matchPrecedence相同且规则有交集的 FlowSchema,这会导致请求分类结果不确定。 - Exempt 级别滥用:只有必要的系统组件(如 kube-controller-manager 的选举请求)应使用
Exempt类型。Operator 的 ServiceAccount 不应被映射到 Exempt 级别。 - 队列深度与并发份额不匹配:如果
queueLengthLimit远大于nominalConcurrencyShares对应的实际并发数,请求容易堆积超时。 - distinguisherMethod 缺失:对于多租户场景,未设置
distinguisherMethod会导致所有请求挤在同一队列,失去公平性。
误报案例: 某 Operator 使用
system-service-accounts FlowSchema(默认 matchPrecedence: 900),但集群中同时存在自定义 FlowSchema my-operator(matchPrecedence: 900)且规则更宽泛。由于优先级相同,请求可能随机命中任一 FlowSchema,导致 Operator 的请求时而进入 workload-high 时而进入 global-default,引发间歇性 429。审计时应优先检查 matchPrecedence 的唯一性。