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 个阶段:

  1. 请求到达:apiserver 的 HTTP 处理链捕获请求,提取用户、组、资源、动词、命名空间等属性。
  2. FlowSchema 匹配:按 matchPrecedence 升序遍历所有 FlowSchema,找到第一个匹配的规则。
  3. 流区分:如果 FlowSchema 定义了 distinguisherMethod,则根据该字段生成“流标识”;否则整个 FlowSchema 视为一个流。
  4. 优先级绑定:通过 FlowSchema 的 priorityLevelConfiguration 引用找到对应的 PriorityLevelConfiguration。
  5. 排队与调度:根据 PriorityLevelConfiguration 的并发份额与排队参数,决定请求是立即执行、进入队列等待、还是被拒绝(429)。
APF 请求分类与排队流程 ① 请求到达 提取用户/资源/动词 ② FlowSchema 匹配 按 matchPrecedence 升序 ③ 流区分 distinguisherMethod ④ 优先级绑定 引用 PriorityLevelConfiguration ⑤ 立即执行 并发配额充足 ⑤ 排队等待 队列 + 公平调度 ⑤ 拒绝 429 说明:Exempt 类型跳过所有排队逻辑

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 内的请求分散到不同的队列中,实现公平性。

请求属性提取 → 流哈希 → 队列映射 请求属性 user: system:serviceaccount resource: pods verb: list FlowSchema 匹配 命中: system-service-accounts distinguisher: ByUser 流哈希计算 hash(user) % queues → 队列索引: 3 队列 3 handSize: 4 深度: 50 分类原理关键点: 1. 同一 FlowSchema + 同一 distinguisher 值 → 同一流 → 同一队列 2. 不同 distinguisher 值 → 不同流 → 不同队列 → 公平调度 3. 未设置 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 的唯一性。