摘要
提出微服务的面临的一个挑战是为每个微服务找到最佳的分配资源和服务实例的数量。达到保证性能的同时最大限度的提高资源利用率这样一个目标。本文的SHOWAR是一个通过确定服务实例数量(横向扩展)以及每个服务实例的资源如CPU和内存(纵向扩展)来配置资源的框架。
对于纵向扩展,SHOWAR通过历史资源中的经验方差来寻找最佳资源分配量,保证性能同时减少不必要的资源浪费;对于横向扩展,使用控制理论的基本思想以及内核级性能指标来实施。
在确定微服务的现有状态后,SHOWAR使用调度程序生成亲和性规则来弥合最佳资源分配和调度之间的差距,实现资源分配和性能提高。
实验表明,SHOWAR与现有的最先进的自动缩放和调度系统相比,资源分配提高了22%,同时降低了99%的端到端请求延迟20%。
Intro
本文的SHOWAR是一个用于微服务横向和纵向自动扩展的微服务管理系统,用于Kubernetes编排的微服务系统。
对于纵向缩放,SHOWAR 依赖历史资源使用情况的差异,找到每个微服务的最佳资源大小,保持良好的性能的同时提高资源利用率。
对于横向自动缩放,SHOWAR 使用来自 Linux 内核线程调度程序队列的指标(特别是 eBPF 运行时延迟)作为其自动缩放信号,以做出更准确和有意义的自动缩放决策。为了实现这个目标,SHOAWR使用了控制理论的基本思想,基于来自微服务运行时的信号控制每个微服务的副本数量。
该团队设计了一个比例积分微分proportional–integral–derivative (PID) 控制器作为有状态自动缩放器,它使用历史自动缩放操作和当前运行时测量来做出下一个水平自动缩放决策并保持微服务“稳定”。此外,SHOWAR考虑不同微服务之间的依赖关系,优先考虑被依赖的微服务,以防止不必要的自动缩放操作和低资源利用率。
除了使用自动缩放器来确定微服务的资源外,SHOWAR还旨在桥接微服务的最佳资源分配和高效调度,在达成最佳资源分配和高效调度之间取得最佳平衡。一旦确定了微服务的最佳大小,SHOWAR就会协助集群调度程序调度微服务以获得更好的端到端性能。为了防止资源争用和管理噪声邻居对微服务性能的影响,SHOWAR使用不同微服务之间历史资源使用情况的估计相关性来为Kubernetes调度程序生成规则。例如,这些规则可能会建议调度程序共同定位(调度亲和性)与某种资源类型具有负相关性的微服务,或者以其他方式分发它们(调度反亲和性)。
文章通过在AWS公共云上的虚拟机集群部署各种交互式微服务应用程序来评估SHOWAR。将SHOWAR的性能与两种最先进的自动缩放系统进行了比较:Google Autopilot和Kubernetes 默认的自动缩放器。使用实际生产工作负载,结果表明,SHOWAR在有效资源分配和端到端请求延迟的尾部分布方面优于这些参照。SHOWAR 平均将资源分配提高了22%,这可以直接转化为集群相关成本的总节省22%,同时将99%的端到端用户请求延迟降低20%。
贡献
- 提出一种自动化的纵向扩容和横向扩容框架,达到保证服务性能的前提下提高资源利用率的目标
- 提出调度亲和性和反亲和规则,通过生成调度亲和性和反亲和性规则来帮助调度程序更好地放置微服务并提高微服务性能,弥合了适当调整微服务规模以提高资源效率和高效微服务调度之间的差距
- 通过实验证明SHOWAR的良好表现
前置知识
这一个比较典型的微服务架构示意图,微服务之间的依赖关系错综复杂。其中一些微服务依赖于其他微服务,SHOWAR使用此依赖关系图信息来做出更好的自动缩放决策。
除了 CPU 和内存使用数据外,SHOWAR还使用扩展的伯克利数据包过滤 ( Berkeley Packet Filtering - eBPF) [6] 指标数据进行水平自动缩放决策。eBPF 是最新的Linux内核技术,它支持在内核级别运行安全且低开销的程序,以从内核级别的事件(例如 CPU 调度程序决策事件、内存分配事件和内核网络堆栈中的数据包事件)中收集准确的指标。它已被广泛用于微服务可观察性,用于性能改进、分析和跟踪、负载平衡、网络监控和安全等广泛目的。
SHOWAR
系统架构
SHOWAR使用每个节点上的相应代理来收集资源使用日志以及 eBPF 指标,然后聚合到时间序列数据库中。
SHOWAR使用收集到的指标通过分别与Kubernetes API服务器及其调度程序通信来做出自动缩放决策以及调度亲和性和反亲和性规则。
系统实现
SHOWAR 作为服务部署在控制器节点并与kubernetes API服务器及其调度程序交互以进行自动缩放操作以及为微服务应用生成的亲和性和反亲和性规则。
-
监控代理Monitoring Agents
监控和日志数据是任何应用程序部署最重要的部分。监控数据用于可观察性、健康检查和自动缩放。本文使用最先进的监控和指标收集工具Prometheus从节点和容器收集不同的指标。Prometheus在集群中的每个节点上启动一个监控代理来收集容器指标,例如 CPU 使用率、内存使用率、网络带宽使用率等。代理被配置为每秒收集和报告指标(一秒是Prometheus 代理可以收集指标的最短时间。为了获得尽可能多的数据点,我们每秒钟收集一次数据)。Prometheus 带有一个时间序列数据库,代理存储收集的指标。此外,提供查询语言来查询其他模块使用的时间序列数据库以利用收集的指标。
除Prometheus外,文章还开发了一个eBPF程序,该程序作为监控代理部署在集群中的每个节点上,以收集横向自动缩放器使用的 𝑟𝑢𝑛𝑞 𝑙𝑎𝑡𝑒𝑛𝑐𝑦 指标。该指标是每个pod中的CPU线程在获取CPU之前所经历的延迟直方图。程序每1秒收集一张𝑟𝑢𝑛𝑞 𝑙𝑎𝑡𝑒𝑛𝑐𝑖𝑒𝑠的直方图并存储在Prometheus时间序列数据库中。
-
纵向缩放器The Vertical Autoscaler
这一个简单的循环,每分钟进行一轮。在前 5 分钟的窗口内为每种资源类型 𝑟(CPU 和内存)计算 𝑠𝑟 =𝜇𝑟 +3∗𝜎𝑟,如果 𝑠 的值变化超过 15%,它会更新服务的资源需求为𝑠。
触发缩放器的另一个条件是微服务报告 OOM 错误时。在应用微服务的新资源需求之前,纵向自动缩放器通过共享通道向横向自动缩放器发送消息,不让其进行任何横向自动缩放操作,因为纵向自动缩放操作的优先级高于水平自动缩放。
如果该微服务的 CPU 数量超过一个 CPU 内核(即 𝑠𝐶𝑃𝑈 >1000𝑚),纵向自动缩放器也不会对微服务进行自动缩放操作,在这种情况下,它会通过另一个共享通道发送消息到横向自动缩放器触发横向自动缩放操作。
-
横向缩放器The Horizontal Autoscaler
横向自动缩放器的核心是一个 PID 控制器,旨在保持每个微服务稳定。对于给定的目标 𝑟𝑢𝑛𝑞 𝑙𝑎𝑡𝑒𝑛𝑐𝑦,它对该微服务执行水平自动缩放操作,使其始终具有𝑟𝑢𝑛𝑞𝑟𝑢𝑛𝑞𝑙控制器每 1 分钟做出决定,eBPF 程序收集 60 个度量直方图实例(每秒 1 个)。对于每个直方图,选择第 95 个百分位数,控制器使用这 60 个数据点的平均值作为其当前观察(也称为测量)来执行其控制操作。每个水平扩展操作添加或删除至少 1 个或可配置百分比(默认为 10%)的微服务当前副本数,分别用于扩展和缩减。PID 控制参数的初始值取为 𝑘𝑃 =𝑘𝐼 =𝑘𝐷 =1/3(每个参数约束为 ∈ [0,10])。这些参数的增量变化是 10%(我们通过实验发现 10% 的性能非常好)。控制器输出的波动是进行此类更改的基础,使用之前的 𝑁 = 10 个样本进行测量。此外,控制器的“速度”被测量为达到区间 [target(1 −𝛼),target(1 + 𝛼)] 所需的迭代次数,因为 𝛼 =10%。
-
亲和规则生成器The Affinity Rule Generator
SHOWAR的亲和性规则生成器每 5 分钟使用一次 CPU、内存和网络利用率,这是一个由 300 个数据点组成的向量(每个数据点是微服务副本的平均值)来计算每个数据点之间不同资源类型的相关系数。消除弱相关或无相关实例,[−0.8,+0.8] 中的任何值都将被丢弃。其他强负相关和强正相关微服务用于生成亲和性和反亲和性规则。资源使用模式会随着工作负载的变化(也称为工作负载转移)而变化,因此如果在随后的 5 分钟时间窗口内强烈的负相关或正相关变化超过 20%(可配置),SHOWAR 将撤销关联(或anti-affinity)规则。
-
SHOWAR的开销
SHOWAR是作为Kubernetes的控制器构建的,它对于自动缩放器和其他类型的控制器具有高度可插拔性。SHOWAR使用常用的 Kubernetes监控代理(如Prometheus)和一个自定义eBPF指标监控代理。因此,与默认的Kubernetes自动缩放器相比,SHOWAR 不会引入任何额外的开销。此外,自动缩放器被调度在控制器节点上,并且不与调度在工作节点上的应用程序 Pod 共享资源。