4、API优先级与公平性(APF):FlowSchema与PriorityLevelConfiguration原理

在Kubernetes多租户控制面中,API Server是唯一的请求入口。当大量请求(来自不同租户、不同组件、不同优先级)同时涌入时,如果没有精细的流量控制机制,高优先级的控制面操作(如kubelet心跳、调度器绑定)可能被低优先级的List-Watch请求淹没,导致集群不稳定。Kubernetes 1.20+引入的API优先级与公平性(APF)机制,通过FlowSchema和PriorityLevelConfiguration两个核心资源,实现了基于队列的、可配置的请求调度隔离。

4.1 APF核心设计目标

APF取代了旧的--max-requests-inflight和--max-mutating-requests-inflight全局硬限制,提供了更细粒度的控制:

  • 优先级隔离:不同租户或不同请求类型使用独立的队列,避免相互影响。
  • 公平调度:同一优先级内的请求按先进先出(FIFO)排队,但通过队列数和并发度控制防止饥饿。
  • 拒绝降级:当队列满时,新请求被拒绝(HTTP 429 Too Many Requests),而非阻塞整个API Server。
  • 可观测性:通过Prometheus指标暴露每个优先级的排队深度、拒绝次数、执行延迟。
关键指标:APF引入两个核心配置对象——FlowSchema(流量模式)和PriorityLevelConfiguration(优先级级别)。前者负责将请求分类,后者定义每个分类的排队与并发行为。

4.2 FlowSchema:请求分类器

FlowSchema定义了如何将进入API Server的请求映射到某个PriorityLevelConfiguration。每个请求会按顺序匹配FlowSchema列表,第一个匹配的FlowSchema决定该请求的归属。

4.2.1 FlowSchema匹配规则

每个FlowSchema包含一组rules,规则由以下维度组成:

匹配维度 描述 示例值
subjects 请求发起者身份(用户、组、ServiceAccount) system:serviceaccounts:kube-system
resourceRules 请求的资源类型、命名空间、动词(get/list/create) pods, namespaces=default, verb=list
nonResourceRules 非资源请求路径(如/healthz、/api) /healthz, verb=get

匹配顺序由matchingPrecedence字段控制,数值越小优先级越高。系统内置的FlowSchema(如system-leader-election、workload-high)通常具有较高的优先级。

4.2.2 内置FlowSchema示例

apiVersion: flowcontrol.apiserver.k8s.io/v1beta3
kind: FlowSchema
metadata:
  name: system-leader-election
spec:
  matchingPrecedence: 50
  priorityLevelConfiguration:
    name: leader-election
  rules:
  - subjects:
    - kind: Group
      group:
        name: system:authenticated
    resourceRules:
    - verbs: ["get", "update"]
      apiGroups: ["coordination.k8s.io"]
      resources: ["leases"]
      resourceNames: ["*"]
      clusterScope: true

上述FlowSchema确保所有经过认证的用户对coordination.k8s.io/leases资源的get和update请求,都被路由到leader-election优先级级别。

4.3 PriorityLevelConfiguration:排队与并发控制器

PriorityLevelConfiguration定义了每个优先级级别的队列行为和并发限制。它是APF实现公平性和隔离性的核心。

4.3.1 核心参数

参数 类型 说明 默认值
spec.limited.assuredConcurrencyShares int32 该优先级在全局并发配额中的权重,权重越高,可同时执行的请求越多 3
spec.limited.limitResponse.type string 限流策略类型:Queue(队列)或Reject(直接拒绝) Queue
spec.limited.limitResponse.queuing.queues int32 该优先级下的队列数量(用于实现公平性) 64
spec.limited.limitResponse.queuing.handSize int32 每个请求的哈希种子数,用于将请求分配到队列 8
spec.limited.limitResponse.queuing.queueLengthLimit int32 每个队列的最大长度,超过后请求被拒绝 50

4.3.2 队列公平性原理

APF使用公平排队(Fair Queuing)算法:

  1. 每个请求根据其FlowSchema和请求特征(如用户、资源)计算哈希值,映射到queues中的某个队列。
  2. 同一队列内的请求按FIFO顺序处理。
  3. 调度器以轮询方式从各队列取出请求执行,确保每个队列都能获得执行机会,防止某个队列被饿死。
  4. 当队列满时,新请求立即返回HTTP 429,不会阻塞其他队列。
最佳实践:对于多租户场景,建议为每个租户或每个关键组件(如kubelet、scheduler、controller-manager)创建独立的PriorityLevelConfiguration,并设置合理的assuredConcurrencyShares。例如,kubelet心跳请求应分配较高的权重,而普通用户的List请求分配较低权重。

4.4 APF请求处理流程(SVG)

下图展示了从请求到达API Server到最终被处理或拒绝的完整APF流程:

APF请求处理流程 APF请求处理流程 API请求到达 FlowSchema匹配(按优先级顺序) 映射到PriorityLevelConfiguration 哈希分配至具体队列 队列是否已满? 是 HTTP 429拒绝 否 入队等待调度 请求执行 说明:每个PriorityLevelConfiguration独立管理自己的队列集合。当队列满时,请求被直接拒绝,不影响其他优先级级别的请求。 队列调度采用轮询机制,确保同一优先级内不同队列的请求公平获得执行机会。

4.5 多租户场景下的APF配置策略

在面向多租户的控制面中,APF的配置需要兼顾隔离性和资源利用率。以下是一个典型的多租户APF配置方案:

优先级级别 目标租户/组件 assuredConcurrencyShares 队列数 队列长度 说明
leader-election 系统租约 20 1 10 最高优先级,确保选举不阻塞
node-health kubelet心跳 15 4 20 节点健康检查,低延迟要求
scheduler 调度器绑定 10 8 30 调度操作,中等优先级
tenant-a-critical 租户A关键操作 8 16 50 租户A的写操作
tenant-b-critical 租户B关键操作 8 16 50 租户B的写操作
default 普通用户请求 3 64 50 低优先级,大量队列防饥饿
注意:不要为每个租户创建过多的优先级级别(建议不超过20个),否则会增加API Server的调度开销。对于非关键租户,可以考虑合并到default优先级,通过调整队列数实现软隔离。

4.6 APF与旧限流机制的对比

特性 旧机制(max-requests-inflight) APF(FlowSchema + PriorityLevelConfiguration)
隔离粒度 全局(所有请求共享一个队列) 按优先级、按队列隔离
公平性 无(先到先服务,可能被大请求阻塞) 公平排队,防止饥饿
配置方式 启动参数(静态) API资源(动态,无需重启API Server)
拒绝行为 HTTP 429(无区分) HTTP 429(可区分优先级)
可观测性 有限(仅全局指标) 每个优先级、每个队列的详细指标
适用场景 小规模集群 多租户、大规模、关键业务集群

4.7 监控与调试APF

APF暴露了丰富的Prometheus指标,用于监控每个优先级级别的状态:

# 每个优先级的当前排队请求数
apiserver_flowcontrol_current_inqueue_requests{priority_level="tenant-a-critical"}

# 每个优先级的并发执行请求数
apiserver_flowcontrol_current_executing_requests{priority_level="tenant-a-critical"}

# 请求被拒绝的总数
apiserver_flowcontrol_rejected_requests_total{priority_level="tenant-a-critical"}

# 请求在队列中的等待时间(分位数)
apiserver_flowcontrol_request_wait_duration_seconds{priority_level="tenant-a-critical"}
调试建议:当发现某个租户的请求延迟增加时,首先检查该优先级级别的current_inqueue_requests是否持续增长。如果队列深度接近queueLengthLimit,说明需要增加队列长度或提高assuredConcurrencyShares。如果rejected_requests_total快速上升,则说明请求量已超过该优先级的处理能力,需要扩容或限流。

4.8 总结

APF通过FlowSchema和PriorityLevelConfiguration的组合,为Kubernetes API Server提供了强大的流量控制能力。在多租户控制面中,合理配置APF可以实现:

  • 关键业务保障:系统组件(如kubelet、调度器)的请求始终优先处理。
  • 租户隔离:每个租户的突发流量不会影响其他租户。
  • 可预测的拒绝行为:当负载超过容量时,低优先级请求被优雅拒绝,而非整个API Server不可用。
  • 动态调整:无需重启API Server即可调整限流策略,适应业务变化。