阿里云 ACK 中使用 cronhpa 计划性弹性伸缩来应对整点秒杀
业务背景
整点秒杀活动背景
跨境电商独立站业务,计划在 3月8日 零点整点开启 85折 整点抢券,预计将在 3月8日零点,会产生高于平日 2倍 的流量,很明显这属于整点秒杀类型的业务场景
为什么 K8S 自带的弹性扩容 HPA 无法应对爆发性流量(整点秒杀)?
调节滞后性:HPA 指标采集与评估有时间间隔,决策到执行也有延迟,难以及时应对整点秒杀瞬时流量。
扩容速度限制:新 Pod 创建依赖资源准备(健康检查),受资源紧张和镜像拉取等影响速度慢,且受集群资源上限制约
预测能力不足:HPA 不了解业务模式,无法提前预知整点秒杀流量,错过准备时机 。
所以 HPA 更适用于平稳的流量增长带来的扩缩容场景,而“整点秒杀”类型的业务场景, 瞬时性的突发流量直接把 容器组负载打满,此刻业务的反应是 ———— 卡卡卡 ————
因此,整点秒杀的场景,一定要利用云计算的弹性能力预准备计算资源,覆盖活动周期可以很好的应对突发性的流量,弥补 HPA 的不足。
接下来要引入 阿里云 ACK 的 cronhpa 能力来解决这个问题。
准备条件
已创建ACK托管集群、ACK Serverless集群
已通过 kubectl 工具连接集群
CronHPA 基础模板及参数介绍
CronHPA 基于 kubernetes-cronhpa-controller 实现。kubernetes-cronhpa-controller 是一个基于时间的 Pod 水平伸缩 Controller,按照类似 Crontab 的策略定时地对集群进行扩缩容,例如在工作日的业务高峰期自动增加Pod数量,在业务低谷时自动减少Pod数量。
CronHPA 可以作用于任何支持伸缩子资源(Scale Subresource)的Kubernetes对象,例如Deployment、StatefulSet 等。
安装 CronHPA 的组件
登录容器服务管理控制台,在左侧导航栏选择集群。
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理 > 组件管理。
单击应用管理页签,找到ack-kubernetes-cronhpa-controller,按照页面提示完成组件的安装。
CronHPA 模板参数
apiVersion: autoscaling.alibabacloud.com/v1beta1 kind: CronHorizontalPodAutoscaler metadata: labels: controller-tools.k8s.io: "1.0" name: cronhpa-sample namespace: default spec: scaleTargetRef: # 指定扩缩容的对象 apiVersion: apps/v1 kind: Deployment name: nginx-deployment-basic excludeDates: # 需要跳过不执行的时间段,最小单位为天。 # exclude November 15th # 例如:11月15日不运行任务 - "* * * 15 11 *" # exclude every Friday # 例如:每周五不运行任务 - "* * * * * 5" jobs: - name: "scale-down" # 在 job 中是唯一的,通过 job 来区分不同的任务用途 schedule: "30 */1 * * * *" # 秒 分 时 日 月 周 targetSize: 1 # 目标副本数量 - name: "scale-up" schedule: "0 */1 * * * *" targetSize: 3 runOnce: false # 设置为true时,任务将只执行一次,第一次执行完则退出(Exit)
实现CronHPA与HPA的协同 的部署案例
由于 CronHPA 和 HPA 两者无法相互感知,如果您的应用使用 YAML 同时配置了 CronHPA 和 HPA,可能会出现两种配置独立工作,后执行操作覆盖了先执行操作的现象。
ACK 提供了 CronHPA 兼容 HPA 的方案——当检测到两者同时存在时,通过将 HPA 作为 CronHPA 的 scaleTargetRef,CronHPA 可以明确知晓并综合考虑 CronHPA 任务当前的目标副本数, HPA 中的 minReplicas、 maxReplicas 和 desiredReplicas 数值,以及 HPA 中 scaleTargetRef 对象的当前副本数。
一句话概括就是:CronHPA 不会直接调整 Deployment 的副本数目,而是通过 HPA 来修改 Deployment配置,避免HPA 和 CronHPA 发生冲突。
HPA
以下策略定义了一个应用的常规 HPA 策略:
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: labels: app: shopping-mall app.kubernetes.io/managed-by: Helm name: shopping-mall namespace: mall spec: maxReplicas: 100 # 最大维持100个副本上限 metrics: - resource: name: cpu target: averageUtilization: 50 type: Utilization type: Resource minReplicas: 25 # 最小维持25个副本 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: shopping-mall
CronHPA
以下策略定义了 CronHPA 以 HPA 为操作对象(即协同):
在 3月7日晚上 23点(提前一小时)讲负载能力扩容两倍
在 3月8日凌晨 3点回收资源
apiVersion: autoscaling.alibabacloud.com/v1beta1 kind: CronHorizontalPodAutoscaler metadata: name: shopping-mall namespace: mall spec: jobs: - name: scale-up runOnce: false schedule: 0 0 23 7 3 * # 3月7日23点执行扩容任务,副本数扩容到平日的两倍数量 targetSize: 50 runOnce: true # true 这是一个一次性的任务 - name: scale-down # 3月8日凌晨执行缩容任务,副本数量恢复 runOnce: false schedule: 0 0 3 8 3 * targetSize: 25 runOnce: true # true 这是一个一次性的任务 scaleTargetRef: apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler name: shopping-mall # 以 HPA 为操作对象
Prometheus 监控流量负载
3月7日 23点 ~ 3月8日 3点,期间预部署2倍动态资源,仅覆盖4小时,极大程度的节约服务器成本,又应对了整点秒杀流量高峰。
阿里云后台成本
阿里云 弹性容器实例 单价:
覆盖4小时仅使用了 12元。
案例总结
对于平日常规性的流量峰谷场景,普通的 HPA 就可以完成动态扩容缩容任务。
但是对于电商整点秒杀场景:用计划性弹性容器实例预部署,既能很好的应对已知的流量高峰,又能很好的解决用云成本
如果应用同时部署了 HPA 和 CRONHPA,那么必须配置两者协同来防止相互覆盖的问题。