作者简介:
杨森,达达集团 DevOps & SRE 负责人,专注于提升分布式系统的稳定性和可观测性、弹性容量、故障自愈、多云容器架构及效能平台建设。
面对节假日常规促销、618/双11购物节、以及去年初疫情全民线上买菜购物等配送业务订单量的暴增时期,我们通过智能弹性伸缩架构和精细化的容量管理,有效地做到了业务系统对配送全链路履约和服务体验的保驾护航和进一步提升,同时业务低峰期的极限缩容又将弹性发挥到极致,使得我们在成本控制方面获得了不错的收益。
1、弹性容量的重要性及自动扩缩容初探
1.1 从一次故障说起弹性的重要性
时间要回到2019年的某次常规促销,鲜花业务待接单在短时间内陡增,消息队列有积压告警后研发先后手动扩容了服务A、B来增加队列的消费能力,之后服务A、B以高于日常N倍的量请求服务C某个接口,继而加剧了服务C集群负载同时该服务的接口响应在逐渐变差,服务C的集群机器开始CPU告警,研发联系运维扩容,接下来等待了19分钟后运维介入扩容了2台服务C(1台成功1台失败),此刻服务C集群中有一半机器CPU被打满,另外一半机器 CPU 接近 80%,App 端请求服务C的接口超时,线上业务开始受损,接下来的11分钟,运维扩容x台机器又全部失败,最后只能通过手动拉起拉起上线后,业务才彻底恢复。
复盘整个故障过程,引发了更多的灵魂拷问,比如常规促销是否也需要压测以确保容量是足够的、扩容SOP及成功率和效率的保障、故障处理流程优化、业务设置降级开关等等, 其中容量规划及扩容成功率、效率是运维侧首当其冲要复盘跟进解决的。
我们的思考是通过弹性容量来应对压力的变化。
上图中,黄线所代表的传统容量规划,在应对时刻变化的业务需求时,要么是资源不足造成系统性能不足,要么是资源浪费。而绿线所代表的弹性伸缩可以实现 “哪些服务应该在哪个时间点扩容多少实例” 以自适应应对业务需求的变化, 这正是我们想要做到的弹性容量。
1.2 自动扩缩容初探
自动扩缩容之所以可以顺利开展,得益于我们在配置管理引入 Apollo、基于 Consul 实现服务注册发现和数据源高可用、基于 OpenResty+Consul 的网关实现了 upstream 节点热更新,并做到了节点无状态。
AutoScaler 弹性配置如下:
-
最小实例数:默认2,可调整
-
扩容:
-
缩容:
P0、P1核心服务:
集群CPU水位>30%,直接扩容线上一半实例数
集群CPU水位>50%,直接扩容线上一倍实例数
非 P0、P1核心服务:
集群CPU水位>50%,直接扩容线上一半实例数
集群CPU水位<5%,告警通知,触发StackStorm回收线上一半实例,且剩余实例数>=最小实例数
然而,仅仅靠集群 CPU 水位指标是无法覆盖更多业务场景的,比如某些业务队列积压需要扩容更多的消费者、连接池打满、单机离群(CPU 使用率偏高、磁盘 IO、网卡进出、错误日志数、接口响应超时等有明显差异的)、单机 QPS 等场景需要更多的指标,迫使我们往更深层次考量和设计更加灵活智能的弹性架构。
2、智能弹性架构的思考和设计
毫无疑问,精细化的容量管理对系统持续稳定运行和云成本控制至关重要,而弹性架构又是实现这一问题的核心点。
但是,弹性架构和自动伸缩是一定需要结合实际业务场景来考虑,“从上至下思考,从下至上执行”,我们对问题的分析和拆解如下图:
这就如同无人自动驾驶这样的场景:既要感知实时路况的同时,也考虑不同时段可能遇到堵车等突发情况,又要满足不同年龄层次的乘客对时间、费用和舒适度的体验要求,还要尽可能省电省油。
自动驾驶系统体系架构图如下:
参考如上自动驾驶的架构,且弹性系统需要满足如下需求:
-
弹性覆盖更多核心服务,且研发可以自助配置弹性策略
-
支持大促压测链路服务的自动扩容
-
支持除 cpu.busy 以外的指标,比如消息队列长队、连接数、DiskIO、错误日志数、接口响应时间、服务端不可达比例等
-
自定义缩容及极限缩容,以降低成本
-
弹性对云原生技术改造过程中多运行时、多云的支持
于是,我们围绕 “感知” - “决策” - “执行” 设计了如下弹性伸缩架构:
没错,以上即我们从自动驾驶获得的灵感,弹性系统需观测到每个环节涉及服务及关联消息队列等组件相关指标,也就是输入是某个metric,结合策略及时序数据分析,执行相应策略以保障配送全流程的履约率和体验。
2.1 感知 - 观测业务系统指标
感知部分是为了接入更多已有的业务系统观测指标(某个metric),且能适配多种时序数据库。
-
Falcon:系统监控,如 cpu.busy、cpu.switches、mem.memused.percent、disk.io.util、ss.timewait、net.if.total.packets 等指标,以及集群机器这些指标的方差来衡量是否离群
-
InfluxDB:定制化的中间件将服务与服务、服务与缓存和队列的请求及耗时统计均存入 Influxdb 中,用于 monitor 业务指标监控
-
Loki:对 info、error 日志收集后存入 Loki,并直接在 granfa 上形成 metrics,比如 error 中某个 class 的 Exception 异常(对应一类业务场景)的指标数据
-
Prometheus:支持在云原生技术升级改造过中使用到的 Docker 和 Kubernetes 的核心指标监控
-
OpenTSDB:目前在集群指标聚合时会把多种时序格式统一转换成 opentsdb 格式形成 metric
2.2 决策 - 弹性伸缩的核心
-
Configuration:弹性规则配置入口,研发可自助配置当前服务的最小实例数、所在链路、所在云、扩缩容指标、阈值、速率和开关
-
Dashboard:弹性扩缩容运行情况实时展示(每个服务当前在线实例数、期望实例数、弹性扩缩实例数、实例成本)
-
Notification:扩缩容消息通知到企业微信、发送每日扩缩容汇总邮件
-
Aggregator:计算并聚合集群指标, 如下图是某服务集群基础分组的 cpu.busy 的平均水位
-
Collector:时序数据统一转换到 opentsdb 并生成 metric
-
Juge:决策引擎
-
Rule:弹性扩缩总控平台,Configuration的汇总并存入CMDB -
TSA:目前采用的是MA3、MA5并结合TP50、TP90做时序数据分析 -
CMDB+Consul:服务元数据,供Aggregator和Collector计算和生产metric -
Cache:缓存Collector和Jude历史数据和决策,辅助下一次决策下发和算法预测
2.3 执行 - 弹性容量的落地保障
-
Dispatch:并发执行扩缩容流程及上下线操作、重试策略、日志审计、以及缩容流程的优化点(和schedulejob的对接加入防止将正在运行的节点回收、跳到白名单机器等) -
Providers:抽象统一的扩缩容接口,以适配多种发布系统(deployng、tars、k8s、serverless等)
3、弹性扩缩容的落地实践
-
支持基础链路 base 和压测链路 benchmark -
支持应用分组group -
支持多云cloud -
支持分时段的极限缩容 -
支持多 metric 协同,并且通过sql语句可适配多种metric,比如队列长度
SELECT sum("value") FROM "*_queue_*" WHERE ("queue" = 'XXXX') AND time >= now() - 5m GROUP BY time(1m) fill(null)
弹性伸缩总控配置面板如下图所示
这里,着重分享3点我们在落地弹性扩缩容过程中遇到的问题和经验。
3.1 扩缩容定期演练
扩缩容系统能不能随时随地正确的工作,是需要通过经常演练才能确保的。
实际过程我们遇到的情况有如下几点:
-
弹性核心功能和策略是否如期生效,metric 数据聚合的准确度,以及分时段缩容 及多 metric 协同;扩容实例需要考虑已有节点的多可用区的分布情况,尽量做到多可用均分打散。 -
对下游发布系统、云资源、扩缩容也需要一并验证,发现问题点和瓶颈点并及时解决。我们曾遇到过账户余额不足、云主机无资源、发布系统多任务有瓶颈、缩容了正在跑 job 的节点、缩容了不该缩容的节点(其他业务有写死固定IP到/etc/hosts的情况)、缩容太多触发了中间件的兜底策略等。 -
扩容时刻要坚决扩容,缩容需要应对流量徒增情况,我们引入速率 ratio 参数有效控制了缩容的速率,从 2.3 节的图可以证实生产环境自动缩容是缓慢下降的。 -
不能无止尽无脑的扩容,要有刹车机制:我们和每个服务的研发负责人确认服务的实例最大上限,防止数据源连接池耗尽或者打爆。 -
同时我们也会监控 DB 的连接和负载并及时做好垂直拆分的预案。 -
观测大规模并发扩容时,服务依赖的缓存、队列、DB的连接数、主从复制等是否有压力或延时,新加节点是否会造成超时以及线上服务响应有无剧烈抖动等。 -
每日跟踪扩缩容的核心指标:扩缩容成功率、效率、成本趋势可视化。
3.2 极限缩容
3.3 支持多运行时
-
为了兼容并支持VM、VM+Container、Kubernetes、Serverless安全容器等多种运行时 -
为了保持扩缩容流程标准化的延续 -
为了实现扩容优雅上线、缩容优雅下线,进程中止/宕机立即停流量止血
-
进程管理:容器内多进程的依赖管理,实现进程启动/销毁的顺序和进程存活管理 -
流量控制:Pod 的健康检查通过后会自动推送当前节点到 Consul上;Pod 被 Kill时,dinit 会先停外部流量及内部流量,再杀服务进程,实现优雅销毁 -
原地重启:Kubernetes 不支持 Pod 原地重启,dinit 可以实现服务进程就地重启
4、总结和展望
-
时序数据分析后的决策和实际情况仍有一定程度的滞后,比如连续扩容的情况,我们希望容量在一定程度上是可以预测出来的,且最小实例数也是会随实际情况变化的,目前基于 facebook prophet 的 Predict 模块正在设计开发中,希望可以自适应做到提前预测并执行扩缩容; -
优化并提升 TSA 模块,以便可以有效地检测识别出异常点,辅助问题定位并最终生成决策,目标是实现全自动的故障自愈。
感谢运维团队小伙伴在弹性伸缩架构方面做出的努力和贡献,感谢算法团队在弹性扩缩容及极限缩容落地过程中的给予的支持和协作。
附:招聘广告
目前我们正在招聘 SRE 工程师,欢迎有激情有能力有自驱力的小伙伴加入,一起玩转SRE、玩转云原生技术,提升系统稳定性和高可拓展性!
请直接发送简历到 [email protected] ^_^
来源:本文转自公众号达达集团技术,点击查看原文。
基于 Prometheus 的监控系统实践
“高效运维”公众号诚邀广大技术人员投稿,
投稿邮箱:[email protected],或添加联系人微信:greatops1118.
点击阅读原文,更多精彩
本文始发于微信公众号(高效运维):从自动驾驶到自动扩缩容:达达智能弹性伸缩架构和实践
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论