4. APF 关键参数详解:queues、handSize、queueLengthLimit、nominalConcurrencyShares、lendablePercent

APF(API Priority and Fairness)的流量整形效果完全由五个核心参数决定。理解每个参数的含义、默认值以及调优方向,是进行容量校准的前提。本章将逐一拆解这些参数,并给出生产环境下的推荐配置思路。

4.1 参数全景图

下表列出了 APF 配置中每个 FlowSchema 和 PriorityLevelConfiguration 所涉及的关键字段及其作用域:

参数名称 所属对象 默认值 核心作用
queues PriorityLevelConfiguration 64 为该优先级分配的队列数量,决定并发隔离粒度
handSize PriorityLevelConfiguration 8 每次从队列中取出的请求数,影响公平轮转的步长
queueLengthLimit PriorityLevelConfiguration 50 单个队列的最大排队深度,超过后请求被拒绝
nominalConcurrencyShares PriorityLevelConfiguration (取决于优先级) 该优先级在总并发配额中的权重比例
lendablePercent PriorityLevelConfiguration 50 空闲并发配额可借给其他优先级的百分比
调优起点: 在修改任何参数前,务必通过 kubectl get prioritylevelconfigurations 和 kubectl get flowschemas 查看当前集群的默认配置。Kubernetes v1.29+ 的默认配置已经过优化,但大型集群仍需根据实际流量模式调整。

4.2 queues —— 并发隔离的粒度

queues 参数定义了某个优先级下有多少个独立的请求队列。APF 使用 Shuffle Sharding 算法将不同的 FlowSchema 请求分散到这些队列中,从而实现流量的细粒度隔离。

  • 工作原理: 每个请求根据其 FlowSchema 的标签选择器被哈希到某个队列。队列之间通过公平轮转(Round Robin)竞争执行机会。
  • 调优影响:
    • 队列数过多(如 >128): 增加调度开销,且每个队列的请求密度降低,可能导致吞吐量下降。
    • 队列数过少(如 <16): 隔离性变差,一个高流量 FlowSchema 可能占据整个优先级的大部分队列,导致其他 FlowSchema 被饿死。
  • 推荐实践: 对于关键系统优先级(如 workload-high),建议保持 64 或 128;对于低优先级(如 catch-all),可适当降低至 32 以减少资源占用。

4.3 handSize —— 公平轮转的步长

handSize 控制 APF 调度器在每次轮转中从每个队列取出的请求数量。它与 queues 共同决定了调度的公平性。

  • 数学关系: 调度器在每个调度周期内,会遍历所有队列,并从每个队列中取出 handSize 个请求进行处理。因此,一个调度周期内最多处理的请求数为 queues × handSize。
  • 调优影响:
    • handSize 过大: 单个队列的突发流量会快速消耗调度周期,导致其他队列等待时间变长。
    • handSize 过小: 调度器频繁切换队列,增加上下文切换开销,降低整体吞吐。
  • 推荐实践: 保持默认值 8 通常是最佳选择。如果发现某个优先级下的请求延迟抖动较大,可以尝试将 handSize 降低到 4 以提升公平性。
关键公式: 调度周期容量 = queues × handSize。当集群 API Server 的并发处理能力(即 --max-requests-inflight 和 --max-mutating-requests-inflight)固定时,调整这两个参数可以改变请求的排队和分发模式。

4.4 queueLengthLimit —— 排队深度的安全阀

queueLengthLimit 定义了单个队列中最多允许排队的请求数量。当队列已满时,新的请求会被直接拒绝(HTTP 429 Too Many Requests)。

  • 默认值 50 的含义: 假设 queues=64,则该优先级下最多可同时排队 64 × 50 = 3200 个请求。超过此阈值后,请求开始被丢弃。
  • 调优影响:
    • 值过大(如 >200): 队列深度增加,请求在队列中等待的时间变长,导致端到端延迟飙升,且内存占用增加。
    • 值过小(如 <10): 队列容易满,导致大量请求被直接拒绝,客户端需要频繁重试,可能引发重试风暴。
  • 推荐实践: 对于延迟敏感的关键业务(如 workload-high),建议将 queueLengthLimit 降低到 20-30,以快速失败而非排队等待;对于批处理或后台任务,可以保持 50 或适当增加到 100。

4.5 nominalConcurrencyShares —— 权重分配的核心

nominalConcurrencyShares 是 APF 中最关键的权重参数。它决定了当集群处于并发压力下时,各个优先级之间如何分配 API Server 的处理能力。

  • 计算方式: 每个优先级的并发配额 = (该优先级的 shares / 所有优先级 shares 之和) × 总并发配额。总并发配额由 --max-requests-inflight 和 --max-mutating-requests-inflight 决定。
  • 默认值分布: 在 Kubernetes 默认配置中,workload-high 通常为 2000,workload-low 为 1000,catch-all 为 5。这意味着 workload-high 获得了绝大部分的并发处理能力。
  • 调优影响:
    • shares 过高: 该优先级获得过多并发资源,可能导致其他优先级(如系统监控、kube-proxy)被饿死。
    • shares 过低: 该优先级下的请求大量排队或拒绝,影响核心业务。
  • 推荐实践: 基于历史监控数据(API Server 的请求延迟、拒绝率)进行比例调整。例如,如果 workload-high 的请求延迟正常但 catch-all 的拒绝率过高,可以适当降低 workload-high 的 shares 或提高 catch-all 的 shares。
注意: nominalConcurrencyShares 仅在集群达到并发瓶颈时才生效。在低负载时,所有优先级都可以使用空闲的并发配额(受 lendablePercent 控制)。因此,不要仅根据低负载时的表现来调整 shares。

4.6 lendablePercent —— 空闲配额的借贷机制

lendablePercent 控制一个优先级在空闲时,可以将多少比例的并发配额借给其他优先级使用。这是 APF 实现资源利用率最大化的关键机制。

  • 取值范围: 0 到 100。默认值为 50。
  • 工作原理:
    • 当优先级 A 的实际并发使用量低于其 nominal 配额时,空闲部分(按 lendablePercent 比例)可以被其他优先级借用。
    • 当优先级 A 的负载上升,需要回收借出的配额时,借用方会立即被抢占(请求可能被重新排队或拒绝)。
  • 调优影响:
    • lendablePercent = 100: 完全共享空闲配额,资源利用率最高,但高优先级在突发时可能无法立即获得全部配额(因为部分配额被低优先级占用)。
    • lendablePercent = 0: 严格隔离,每个优先级只能使用自己的配额,资源利用率低,但隔离性最强。
  • 推荐实践: 对于关键系统优先级(如 workload-high),建议设置 lendablePercent = 0 或 10,确保其始终拥有完整的并发能力;对于低优先级(如 catch-all),可以设置 lendablePercent = 100,以充分利用空闲资源。

4.7 参数协同关系图

下图展示了五个参数在 APF 调度周期中的协同工作流程:

APF 关键参数协同关系图 APF 关键参数协同关系图 请求到达 FlowSchema Shuffle Sharding 分配队列 queues = 64(隔离粒度) 请求进入队列排队 queueLengthLimit = 50(排队深度) 公平轮转调度(Round Robin) handSize = 8(每次取出数) API Server 并发执行 nominalConcurrencyShares(权重) + lendablePercent(借贷) 返回响应 / 429 拒绝 参数作用域 queues / handSize queueLengthLimit nominalConcurrencyShares lendablePercent

4.8 参数调优决策矩阵

在实际调优中,不同场景下的参数调整方向如下表所示:

问题现象 优先调整参数 调整方向 预期效果
高优先级请求延迟高 nominalConcurrencyShares 增加该优先级的 shares 获得更多并发配额,减少排队
低优先级请求被大量拒绝 queueLengthLimit 适当增加(如 50 → 100) 提高排队容量,减少 429
请求延迟抖动明显 handSize 降低(如 8 → 4) 更细粒度的公平轮转,减少突发
资源利用率低,空闲时浪费 lendablePercent 增加(如 50 → 80) 空闲配额可被其他优先级借用
关键业务被非关键业务影响 lendablePercent 降低关键优先级的借贷比例(如 50 → 0) 严格隔离,关键业务不受影响
整体吞吐量不足 queues 适当减少(如 64 → 32) 减少调度开销,提升吞吐
实战建议: 每次只调整一个参数,并观察至少 15 分钟的监控数据(重点关注 apiserver_flowcontrol_request_wait_duration_seconds 和 apiserver_flowcontrol_request_rejected_total 指标)。避免同时修改多个参数,否则无法定位根因。