应用弹性管理最佳实践

2021-12-16 09:40:08 浏览数 (1)

背景

生产环境中,业务面临的负载压力变化是不定的,为了保障业务的稳定性,需要根据负载大小的变化调整应用实例的数量或资源规格,同时从资源成本角度考虑,需要在保障业务稳定性的同时,尽量减少不必要的资源占用。

为了满足上述两方面的诉求,应用管理平台需要提供弹性能力。下述将整体分析弹性技术以及 K8s 中的实现,并通过一款云产品做演示,从业务视角使用弹性能力。

弹性技术

对于弹性技术,一般会从两个维度进行考虑:

  • 弹性策略
  • 弹性效率

弹性策略重点关注如何管理触发弹性行为的发生以及弹性行为作用的维度,弹性效率重点关注弹性行为触发后多快完成弹性任务。

1. 弹性策略

弹性策略主要关注弹性触发、弹性作用维度,常见的包括:

  • 弹性触发:定时弹性,基于资源的弹性,基于业务指标的弹性,基于事件的弹性。
  • 弹性作用维度:HPA (Horizontal Pod Autoscale,水平弹性伸缩),VPA (Vertical Pod Autoscale,垂直弹性伸缩)

1.1 应用弹性触发的场景

场景1:很多应用负载与时间有关,如多媒体处理应用、游戏、电商等,会呈现出有明显规律的请求流量高峰、低谷现象,且高峰、低谷持续的时间相对是连续的。

对于这种场景,可以考虑定时弹性策略,在指定的时间段内维持固定数量的应用数量,请求高峰时段保持较多的应用实例,请求低峰时段保持较少的应用实例,同时避免应用实例数量在时间段内波动。

场景2:应用实例处理能力是有限的,在请求量增大时,若 CPU/Memory 等资源使用量超过一定限度,会影响应用的服务性能。

对于这种场景,可以考虑基于资源使用率的弹性策略,定时计算应用实例的 CPU/Memory 等资源的使用率,动态调整应用实例数量,灵敏应对突发流量。

场景3:应用通常会有业务指标,如 QPS/RT/消息堆积数 等,业务指标的变化会影响业务服务质量,而资源使用率不一定能够反映出业务指标的变化,需要考虑其他方法应对这种情况。

对于这种场景,可以考虑基于业务指标的弹性,定时计算 QPS/RT/消息堆积数 等业务维度的指标压力,动态调整应用实例数量,满足业务服务质量的需求。

场景4:实际生产中,时间因素、资源使用率、业务指标 不是互斥的,通常是混合出现。如在业务潮汐流量阶段,会出现资源使用率、业务指标飙升情况,此时需要更为灵敏的基于资源的弹性策略和基于业务指标的弹性策略。

对于这种场景,可以将时间、资源使用率、业务指标作为无差别的事件,根据事件做弹性行为触发的判断,即基于事件的弹性。

1.2 弹性作用维度

在弹性行为发生时,通常的做法是调整实例数量,做水平伸缩。在固定资源规格情况下,单个实例处理能力有限且可以预期的,通过调整实例数量来控制应用整体的处理能力,这种做法更为普适和可控,即 HPA。

还有一种方式是调整实例规格,如调大、调小实例的 CPU/Memory 等资源的上限,提升单个实例的处理能力,即 VPA。

当前 HPA 比 VPA 更易理解、满足预期和更强的可控性,通常在弹性策略执行时,会通过 HPA 的方式作用于应用实例。

2. 弹性效率

弹性效率关注弹性策略执行时,多长时间可以执行完成。下述以 HPA 场景为例,分析影响弹性效率的因素和改善措施。

在容器场景下,实例的运行通常会有如下阶段:

整体的流程会分为 3 个阶段:

  1. 镜像构建:对于代码包 (如 war/jar) 形态的交付物,需要有个构建过程,将代码包构建成镜像
  2. 实例调度:将应用实例调度到适合的节点
  3. 实例启动:这个过程通常会涉及到 镜像处理 启动 两个阶段,先将镜像拉取到节点上,然后启动容器。

可以针对上述每个阶段进行优化,提升弹性效率。

镜像构建阶段,可采用具有高效构建的服务,如 buildkit,充分利用 build cache、concurrent dependency resolution 等能力提升镜像构建效率。针对 Java 类应用,也可以采用类似 jib 等项目加速 Java 类镜像的构建。镜像构建好之后,需要将镜像推送到指定的 registry 中,也可以考虑通过 buildkit 工具控制 是否压缩层数据 和 推送层的并发量 来提升效率。

实例调度阶段,若调度过程中涉及资源准备等,可通过 K8s Scheduler Framework 提供的插件机制进行扩展,将多个流程并行处理。也可以考虑在这个过程中实现 镜像预热,在实例调度到的节点确定后,对于目标节点发起镜像拉取操作,可考虑使用 OpenKruise 提供的 ImagePullJob 实现镜像预热。

实例启动阶段,会涉及 镜像处理 和 启动 两个阶段,在镜像处理过程中,又会有 镜像拉取 和 镜像解压 两个阶段,需要分别考虑优化措施。参考下图,镜像拉取时涉及到镜像层下载和解压。

containerd 支持调整拉取镜像层的并发量,配置可参见 config,通过该配置调节拉取镜像层的并发量。详细链接:

https://github.com/containerd/containerd/blob/main/docs/cri/config.md

containerd 从 1.2 版本开始支持 pigz,节点上安装 unpigz 工具后,会优先用其进行解压。通过这种方法,可通过节点多核能力提升镜像解压效率。

上述思路是 将镜像完整拉到节点后再启动容器,还可参考业界 《Slacker: Fast Distribution with Lazy Docker Containers》paper,采用 边拉镜像边启动容器 的方法进一步提升容器启动效率。

社区有类似的实现,参见 stargz-snapshotter。目前国内各大云厂商也有相应的技术实现,如腾讯云 ImageApparate等。

容器启动后会涉及到应用程序的启动,对于 Java 类应用,可以考虑采用启动效率优化的 JVM Runtime,如腾讯云 KonaJDK等。

【详细链接】

  1. Slacker: Fast Distribution with Lazy Docker Container:https://www.usenix.org/conference/fast16/technical-sessions/presentation/harter
  2. stargz-snapshotter:https://github.com/containerd/stargz-snapshotter
  3. ImageApparate:https://mp.weixin.qq.com/s?__biz=Mzg5NjA1MjkxNw==&mid=2247492105&idx=1&sn=26c2f4eabde8975e2e4974a33622dcde
  4. KonaJDK:https://github.com/Tencent/TencentKona-11

K8s中的弹性能力实现

1.HPA

1.1 原生实现

通过 Kubernetes monitoring architecture 可了解到 K8s HPA 的实现:

如上图所示,K8s 中有 2 条 metrics 数据采集链路 Core Metrics Pipeline 和 Monitoring Pipeline,分别对应基于资源的弹性策略基于指标的弹性策略

对于 Core Metrics Pipeline,kube-apiserver 通过 metrics-server 组件获取 Pod 的 cpu/memory 使用情况,然后由 kube-controller-manager (简称 kcm) 访问 kube-apiserver 获取 workload 的资源利用率,根据算法判断是否要对目标 workload 进行扩缩容操作,处理详情可参见 Horizontal Pod Autoscaler:https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/

其中 metrics-server 是 K8s 社区维护的项目,K8s 集群中部署 metrics-server 组件后,立即可以使用基于资源的弹性能力。

对于 Monitoring Pipeline,实现流程为:

  1. 业务方实现 metrics-adapter:metrics-adapter 提供 Custom Metrics API 或 External Metrics API,满足外部查询指定 metrics 的需求;metrics-adapter 从第三方获取相应的 metrics 数据。
  2. 业务方通过 APIService 资源进行注册:将对 kube-apiserver 的指标请求与 metrics-adapter 关联,便于 kube-apiserver 将请求转发到 metrics-adapter。
  3. kcm 中的 HPA Controller 按照配置和 HPA 资源,请求 kube-apiserver 获取当前 metrics 数据,计算是否需要对指定的 workload 进行扩缩,若需要,则调用指定 workload 的 /scale 接口进行扩缩。

K8s 社区为了简化 metrics-adapter 实现成本,提供了一个开发框架,将 metrics-adapter 中通用实现逻辑模板化,可参见custom-metrics-apiserver:https://github.com/kubernetes-sigs/custom-metrics-apiserver。

1.2 KEDA

对于弹性能力的实现,不得不提 KEDA 项目,它是微软推出的基于事件的弹性伸缩项目,已捐赠给 CNCF,是 CNCF incubating 中的项目,被广泛用于生产环境 (参见 keda users)。

KEDA 的概念和设计如下:

KEDA 将 K8s Core Metrics Pipeline 和 Monitoring Pipeline 处理流程统一化,并内置多种 scaler ( link ),提供开箱即用的弹性策略支持,如常见的基于 CPU/Memory 的弹性策略、定时弹性等:

平台维护者可通过实现 scaler 来扩展弹性策略,支持更丰富的弹性策略,实现参见 External Scalers:https://keda.sh/docs/2.4/concepts/external-scalers/

比较推荐平台层面使用 KEDA 来统一弹性能力的实现,将时间、CPU/Memory 等资源使用率、业务指标等作为 KEDA 的数据源,统一化为事件,基于事件满足对弹性策略的需求。

2. VPA

VPA 是另一种弹性行为的实现,用户可以不再显式配置 workload 的资源申请量,由 VerticalPodAutoscaler 自动配置 workload 资源量,并自动根据 Pod 资源使用情况调整 Pod 资源申请量,项目参见autoscaler/vertical-pod-autoscaler:https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler

目前该项目还处于实验阶段,生产环境中谨慎使用。公有云产品中,GKE 对 VPA 进行了支持,详情参见:https://cloud.google.com/kubernetes-engine/docs/concepts/verticalpodautoscaler

上述 VPA 实现在调整 Pod 资源配置时会重建 Pod,对于一些对重建敏感的应用,重建可能会导致业务异常。

业界也有一种方案是在实现 VPA 的同时不重建 Pod,即在节点层面调整 container cgroup 配置。但这种方案会打破 K8s 的资源管理模型,导致实际分配的资源与 K8s 调度链路感知到的资源申请量不一致,会影响 K8s 集群整体的调度,同时也有可能影响节点自身的稳定性。

目前 K8s 社区有一个 KEP 讨论 In-place Update of Pod Resources,可以持续关注社区对 VPA 的标准化和支持:https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/1287-in-place-update-pod-resources

小结

上述整体介绍了弹性技术和 K8s 中弹性能力的实现,在业务场景中,需要根据业务需求,实现和使用与需求匹配的弹性能力,避免过度使用高级能力影响业务稳定性,如:

  • 有明显潮汐流量特征的业务,可以重点使用 定时弹性
  • 突发流量特征的业务,可重点使用 基于资源的弹性 或 指标弹性
  • 若业务是混合流量特征,即既有潮汐流量特征,又有突发流量特征,可重点使用 基于事件的弹性,根据多种事件综合做弹性决策

基于云产品实践

弹性微服务TEM (Tencent Cloud Elastic Microservice) 是腾讯云推出的面向微服务应用的 Serverless PaaS 平台,实现资源 Serverless 与微服务架构的完美结合,提供一整套开箱即用的微服务解决方案。

TEM 当前提供使用率较高的定时弹性策略基于资源的弹性策略,对应的弹性动作行为均为 HPA,接下来会支持基于指标弹性策略基于事件弹性策略,满足用户对更灵活的弹性策略的需求。

同时针对 Java 应用,TEM 近期会支持 KonaJDK11,提升 Java 应用的启动效率,并计划支持更为通用的 按需拉取的启动策略,进一步提升弹性效率,敬请期待。

TEM 中,用户可以在两个流程中配置弹性策略,一种是在应用部署过程中,一种是在应用部署后在应用详情页中配置弹性策略。推荐后者,更灵活组合应用管理的能力。

可在应用部署后的详情页中编辑弹性伸缩来配置弹性策略:

1. 定时弹性

在弹性伸缩策略中,选择 定时策略,如下示例配置:每天 11:00~14:00 期间保持 10 个实例,14:00~18:00 期间保持 2 个实例,18:00~23:00 期间保持 10 个实例,23:00~11:00 保持 2 个实例。

配置提交后,可通过 预览 可视化查看未来执行效果:

2. 基于资源的弹性策略

在弹性伸缩策略中,选择 指标弹性策略,如下示例配置:当 CPU 使用率不小于 60% 时,扩缩应用实例数量,扩缩范围为 2~20:

总结

通过理解弹性技术,可以在业务中更好选择合适的弹性策略来满足需求,并根据业务对弹性效率的诉求,选择合适的技术优化弹性效率,或在弹性效率限制下,优化弹性策略的使用。

Serverless 云产品提供了资源池的能力,用户不用关心资源池的准备、运维等工作,将注意力集中在业务层面对资源弹性的需求,面对潮汐流量或突发流量,在大促等活动中更好保障业务稳定性,降低业务运行成本。

0 人点赞