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(优先级级别配置)和排队队列(公平调度)。

APF 请求处理流程与核心组件 API 请求到达 FlowSchema 匹配 按请求属性(用户、资源、Verb)匹配规则 PriorityLevelConfig 分配优先级级别与并发配额 排队队列(公平排队) 按 QueueSet 权重分配并发槽位 直接执行 并发配额充足,立即处理 请求处理完成 关键参数 • FlowSchema: 匹配规则 • PriorityLevel: 并发配额 • Queues: 排队深度 • HandSize: 队列分配因子

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,避免队列无限增长。
同一优先级内的公平排队(QueueSet 模型) FS-A (权重 2) FS-B (权重 1) FS-C (权重 1) 队列 0 队列 1 队列 2 队列 3 队列 4 队列 5 队列 6 队列 7 队列 8 队列 9 队列 10 队列 11 FS-A 分配 3 个队列 FS-B 分配 3 个队列 FS-C 分配 3 个队列 空闲队列 权重 2 的 FlowSchema 获得更多队列,从而获得更多并发处理机会,但不会饿死权重低的 FlowSchema

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,以获得更精细的流量控制能力。