Skip to content

Instantly share code, notes, and snippets.

@chenchun
Last active June 25, 2024 03:52
Show Gist options
  • Save chenchun/fb364b4232457d16ad447299f564ea46 to your computer and use it in GitHub Desktop.
Save chenchun/fb364b4232457d16ad447299f564ea46 to your computer and use it in GitHub Desktop.
apf, kubernetes, apiserver

APF

参考文档 https://v1-26.docs.kubernetes.io/zh-cn/docs/concepts/cluster-administration/flow-control/ https://blog.csdn.net/sinat_37367944/article/details/116329588

API 优先级与公平性(APF)特性由特性门控控制,默认情况下启用

请求占用的席位(并发度)

上述并发管理的描述是基线情况。其中,各个请求具有不同的持续时间, 但在与一个优先级的并发限制进行比较时,这些请求在任何给定时刻都以同等方式进行计数。 在这个基线场景中,每个请求占用一个并发单位。

但有些请求所占用的席位不止一个。有些请求是服务器预估将返回大量对象的 list 请求。 和所需运行时间相近的其他请求相比,我们发现这类请求会给服务器带来异常沉重的负担。 出于这个原因,服务器估算将返回的对象数量,并认为请求所占用的席位数与估算得到的数量成正比。

APF 管理 watch 请求,但这需要考量基线行为之外的一些情况。 第一个关注点是如何判定 watch 请求的席位占用时长。 取决于请求参数不同,对 watch 请求的响应可能以针对所有预先存在的对象 create 通知开头,也可能不这样。 一旦最初的突发通知(如果有)结束,APF 将认为 watch 请求已经用完其席位。

每当向服务器通知创建/更新/删除一个对象时,正常通知都会以并发突发的方式发送到所有相关的 watch 响应流。 为此,APF 认为每个写入请求都会在实际写入完成后花费一些额外的时间来占用席位。 服务器估算要发送的通知数量,并调整写入请求的席位数以及包含这些额外工作后的席位占用时间。

队列

PriorityLevelConfiguration 定义可用的优先级和可处理的并发预算量,还可以微调排队行为。 FlowSchema 用于对每个入站请求进行分类,并与一个 PriorityLevelConfiguration 相匹配。

每个请求都被分配到某个 流(Flow) 中,该流由对应的 FlowSchema 的名字加上一个 流区分项(Flow Distinguisher) 来标识。 这里的流区分项可以是发出请求的用户、目标资源的名字空间或什么都不是。将请求划分到流中之后,APF 功能将请求分配到队列中。 分配时使用一种称为混洗分片(Shuffle-Sharding)的技术

PriorityLevelConfiguration 的额定并发限制不是指定请求绝对数量,而是以“额定并发份额”的形式指定。 API 服务器的总并发量限制通过这些份额按例分配到现有 PriorityLevelConfiguration 中, 为每个级别按照数量赋予其额定限制。

当入站请求的数量大于分配的 PriorityLevelConfiguration 中允许的并发级别时, type 字段将确定对额外请求的处理方式。 Reject 类型,表示多余的流量将立即被 HTTP 429(请求过多)错误所拒绝。 Queue 类型,表示对超过阈值的请求进行排队,将使用阈值分片和公平排队技术来平衡请求流之间的进度。

  • 启用 APF 特性时,服务器的总并发限制被设置为 --max-requests-inflight 及 --max-mutating-requests-inflight 之和。变更性和非变更性请求之间不再有任何不同。这些并发数被分配给各个PL,分配方式是根据 PriorityLevelConfiguration.Spec.Limited.AssuredConcurrencyShares 的数值按比例分配。PL 的 AssuredConcurrencyShare 越大,分配到的并发份额越大。即PL的并发数=ACS*(max-requests-inflight+max-mutating-requests-infligh)/sum(ACS)
  • 单个流中可能排队的请求的最大数量为 handSize * queueLengthLimit
  • 当给定的请求与某个 FlowSchema 的 rules 的其中一条匹配,那么就认为该请求与该 FlowSchema 匹配。 判断规则与该请求是否匹配,不仅要求该条规则的 subjects 字段至少存在一个与该请求相匹配, 而且要求该条规则的 resourceRules 或 nonResourceRules 字段至少存在一个与该请求相匹配。
  • FlowSchema 的 distinguisherMethod.type 字段决定了如何把与该模式匹配的请求分散到各个流中。 可能是 ByUser,在这种情况下,一个请求用户将无法饿死其他容量的用户; 或者是 ByNamespace,在这种情况下,一个名字空间中的资源请求将无法饿死其它名字空间的资源请求; 或者它可以为空(或者可以完全省略 distinguisherMethod), 在这种情况下,与此 FlowSchema 匹配的请求将被视为单个流的一部分。

建议的配置

  • 强制的 exempt 优先级用于完全不受流控限制的请求:它们总是立刻被分发。 强制的 exempt FlowSchema 把 system:masters 组的所有请求都归入该优先级。 如果合适,你可以定义新的 FlowSchema,将其他请求定向到该优先级
  • catch-all 优先级的并发度份额很小, 并且不会对请求进行排队
  • node-high 优先级用于来自节点的健康状态更新。
  • system 优先级用于 system:nodes 组(即 kubelet)的与健康状态更新无关的请求; kubelet 必须能连上 API 服务器,以便工作负载能够调度到其上。
  • leader-election 优先级用于内置控制器的领导选举的请求 (特别是来自 kube-system 名字空间中 system:kube-controller-manager 和 system:kube-scheduler 用户和服务账号,针对 endpoints、configmaps 或 leases 的请求)。 将这些请求与其他流量相隔离非常重要,因为领导者选举失败会导致控制器发生故障并重新启动, 这反过来会导致新启动的控制器在同步信息时,流量开销更大。
  • workload-high 优先级用于内置控制器的其他请求。
  • workload-low 优先级用于来自所有其他服务帐户的请求,通常包括来自 Pod 中运行的控制器的所有请求。
  • global-default 优先级可处理所有其他流量,例如:非特权用户运行的交互式 kubectl 命令

DEBUG

接口

  • 所有优先级及其当前状态的列表 kubectl get --raw /debug/api_priority_and_fairness/dump_priority_levels
  • 所有队列及其当前状态的列表 kubectl get --raw /debug/api_priority_and_fairness/dump_queues
  • 当前正在队列中等待的所有请求的列表 kubectl get --raw /debug/api_priority_and_fairness/dump_requests
  • 获得更详细的清单 kubectl get --raw '/debug/api_priority_and_fairness/dump_requests?includeRequestDetails=1'

日志

在 -v=3 或更详细的情况下,服务器会为每个请求输出一行 httplog,它包括以下属性。

apf_fs:请求被分类到的 FlowSchema 的名称。 apf_pl:该 FlowSchema 的优先级名称。 apf_iseats:为请求执行的初始(正常)阶段确定的席位数量。 apf_fseats:为请求的最后执行阶段(考虑关联的 WATCH 通知)确定的席位数量。 apf_additionalLatency:请求执行最后阶段的持续时间。 在更高级别的精细度下,将有日志行揭示 APF 如何处理请求的详细信息,主要用于调试目的。

metrics

  • apiserver_flowcontrol_rejected_requests_total 记录被拒绝的请求数量(自服务器启动以来累计值), 可按标签 flow_chema、priority_level 和 reason 分解
  • apiserver_flowcontrol_dispatched_requests_total 记录开始执行的请求数量(自服务器启动以来的累积值), 由标签 flow_schema(表示与请求匹配的 FlowSchema)和 priority_level(表示分配给该请求的优先级)来区分。
  • apiserver_flowcontrol_current_inqueue_requests 记录排队中的(未执行)请求的瞬时数量,可按 priority_level 和 flow_schema 分解
  • apiserver_flowcontrol_current_executing_requests 记录执行中(不在队列中等待)请求的瞬时数量,可按 priority_level 和 flow_schema 分解。
  • apiserver_flowcontrol_request_wait_duration_seconds 是一个直方图向量, 记录了按 flow_schema、priority_level 和 execute 标签细分的请求在队列中等待的时长。 execute 标签表示请求是否已开始执行
  • apiserver_flowcontrol_nominal_limit_seats 是一个测量向量, 记录了每个优先级的额定并发限制。 此值是根据 API 服务器的总并发限制和优先级的配置额定并发份额计算得出的
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment