作者 | 字节跳动基础架构 / 服务框架团队研发工程师 - 刘立伟
本文主要介绍了字节跳动 Sidecar 应用场景,以及进行 Sidecar 大规模版本升级的实践和总结。
字节 Sidecar 场景介绍
Sidecar 是一种用于扩展应用程序功能的架构模式。在 Sidecar 架构中,应用程序主进程和一个或多个 Sidecar 进程运行在同一个计算节点中,例如 Pod、物理机等,Sidecar 进程与主进程保持相同的生命周期,为应用程序提供额外的功能支持,例如网络、安全、日志、监控等相关功能。
目前,在字节跳动的微服务架构下,有丰富的 Sidecar 应用场景,包括 Service Mesh、网关、风控、流量录制、业务安全等几十种业务场景 Sidecar,支持了抖音、飞书、基础架构等多个业务线 / 部门。
以下,对几个典型 Sidecar 应用场景进行介绍。
Service Mesh
在微服务体系下,RPC 框架是微服务之间通信的核心组件,RPC 框架支持了服务发现、流量调度、负载均衡、访问控制等复杂的服务治理功能。随着微服务规模变大,RPC 框架暴露出一些问题:
Service Mesh 解决了上述问题,作为服务通信的基础设施,它实现了一个高性能多协议的数据面代理和一个灵活可扩展的控制面服务,RPC 框架复杂的治理功能下沉到了数据面,数据面以 Sidecar 的形式部署在服务实例中。
相比于传统的 RPC 框架,Service Mesh 优势如下:
分布式 API 网关
API 网关(APIGateway)以 API 为核心,提供流量调度、稳定性策略、服务治理等全套解决方案。
API 网关最初的架构是中心化网关,一个网关集群为多个服务进行分流,存在一些痛点问题:
API 网关团队将网关改造成 Sidecar 部署到服务实例中,实现了分布式网关,并通过 Sidecar 运维平台对分布式网关进行管理。
通过分布式网关方案,解决了上述痛点问题:
除了上述优化,也有其他收益:
风控 Sidecar
风控团队为业务提供 API 反爬取、反作弊支持,可以降低业务接口风险,加强 API 安全防护。
风控最初提供 SDK 接入方式,用户接入时,需要在业务代码中主动集成风控 SDK,存在以下痛点问题:
为解决以上问题,风控团队和 Service Mesh 团队合作,借助 Sidecar 方案和 Service Mesh 的能力,设计开发了风控 Sidecar:
对比风控 SDK,通过风控 Sidecar 的方案,解决了上述痛点问题:
MQ Sidecar
消息队列 MQ 团队提供了 RocketMQ/BMQ 两种消息队列来处理在线、离线场景。为了满足业务接入,目前每种消息队列提供了多个语言的 SDK,存在一些问题:
因此,MQ 团队引入 Sidecar 架构方案,实现了 MQ Sidecar:
对比 MQ SDK,通过 MQ Sidecar 的方案,解决了上述痛点问题:
Sidecar 架构的优势和挑战
优势
综合对几个典型 Sidecar 应用场景的介绍,可以总结出 Sidecar 架构核心优势如下:
挑战 - 升级运维
从上述分析可以看出,Sidecar 架构的关键是 Sidecar 进程可以独立运行、单独升级,因此,只有支持 Sidecar 的升级运维能力,才能使 Sidecar 架构真正发挥出优势。然而,Sidecar 的升级运维面临严峻的挑战。
不同于传统的微服务升级,Sidecar 升级场景更加复杂:
其中最关键的特点,Sidecar 升级面向的服务规模很大,以 Service Mesh Sidecar 举例,生产环境接入情况如下:
在如此大规模的场景下,在进行版本升级的时候,一些问题会被放大:
事故案例介绍
以下是一个真实的事故案例,展示了一次 Service Mesh 升级导致业务故障的处理全过程:
核心问题:稳定性 & 效率
在进行大规模 Sidecar 升级时,最核心的两个问题是稳定性和效率。
对于稳定性,主要关注业务故障风险:
历史上,Service Mesh 升级导致过 P0 事故,导致业务受损
历史上,Service Mesh 升级导致过 P0 事故,导致业务受损
对于效率,主要关注时间、人力成本:
历史上,Service Mesh 进行 1 次大版本升级,历时 5 个月,期间多次 feature 插入、问题修复,共发了 25 个小版本才最终完成升级
历史上,Service Mesh 进行 1 次大版本升级,历时 5 个月,期间多次 feature 插入、问题修复,共发了 25 个小版本才最终完成升级
Sidecar 大规模升级 - 思考
如何设计一套可靠的 Sidecar 大规模升级方案?为应对稳定性和效率两个挑战,主要从变更安全和变更效率两个角度展开思考:
变更安全
要保障升级过程的安全,必须树立对风险的正确意识:问题一定存在!
只不过,对于问题,存在已知问题和未知问题,对两种问题有不同的应对措施:
当然,总有问题不可避免的发生,此时需要积极应对已发生问题:
变更效率
为提升变更效率,首先,要完善变更规范:
其次,通过技术手段,尽量加快升级速度:
总结
综上,对 Sidecar 大规模升级的思路进行总结:
在不同的升级阶段,综合多种策略保障变更安全和变更效率:
同时,最关键的,要将版本升级流程平台化,将上述策略固化在平台上。
Sidecar 大规模升级 - 方案解析
我们构建了一套 Sidecar 运维管理系统,在系统上落地了 Sidecar 大规模升级方案,本节对如何进行安全、高效的 Sidecar 大规模升级进行详细解析。
运维管理系统
Sidecar 运维管理系统提供了一套 Sidecar 应用运维管理解决方案,支持多种云环境下 Sidecar 标准化接入、安全运行、观测运维、版本治理等能力。
系统包含以下核心组件:
方案总览
以下为完整的升级方案总览:
方案从升级的各个阶段入手,通过引入多项措施控制变更质量,保障变更安全,并在安全的基础上加速升级,提升变更效率。
在升级前,严格控制准入,包括:变更准入、版本准入、服务准入等策略。
在升级中,平台构建了灰度验证、逐步全量的自动化发布流程,可以谨慎的对版本进行验证,并且谨慎的将版本逐步全量。
在问题发生时,平台支持通过快速回滚、修复覆盖的流程,支持快速恢复,快速止损。
在升级后,支持版本治理,包括对长尾版本的收敛,以及在版本发现异常后,对版本进行快速的召回。
另外,在发布的整个流程中:
以下,对升级流程中灰度验证、逐步全量和异常检测进行介绍,详细介绍如何将上述策略落地。
升级流程
灰度验证
灰度是逐步将新版本验证稳定、可靠的过程,要在灰度阶段尽可能的验证出问题,不要到全量阶段才暴露出问题,不然会导致更大面积的影响。
谨慎验证
首先,关于灰度覆盖面,要确保灰度验证的有效性,需要保证足够的覆盖面,这样才能验证到足够多的场景。
但是,如何保证足够的覆盖面,对于 Sidecar 新版本可能影响的服务,分为两类:
比如:新版本变更了负载均衡算法,升级时会明确关注服务的流量负载情况
比如:新版本变更了负载均衡算法,升级时会明确关注服务的流量负载情况
比如:一些历史逻辑受影响,或者有用户使用了非公开的特性
比如:一些历史逻辑受影响,或者有用户使用了非公开的特性
但是,“预期外受影响的服务”是很难知道的,如果灰度覆盖不到这些服务,就无法保证灰度的有效性。为了简单起见,我们选择了大力出奇迹的做法,选择对所有服务进行灰度,这样就尽量保证了覆盖面。
其次,关于单服务灰度范围,字节的服务部署区分小流量、单机房、全流量的部署阶段,小流量阶段一般只部署少量的实例,业务升级服务时使用该阶段进行新版本验证,因此 Sidecar 也使用小流量阶段进行灰度验证。
另外,关于升级方式,要保证灰度版本快速生效,这样有问题才能尽快暴露出来,因此,我们选择使用热升级的方式,热升级后,服务使用的 Sidecar 版本可以立即更新。
最后,还构建了特征服务机制,Sidecar 的升级,可能会对特定服务产生影响,比如特定语言、框架、通信协议,或者使用了特殊配置的服务,因此,我们构建了特征集合,并对每种特征选取有代表性的服务集合,灰度验证时,首先对这些服务进行验证,并充分观察服务是否异常。
比如:Service Mesh HTTP 压缩算法调整,影响到了配置特殊 HTTP 压缩算法的服务
比如:Service Mesh HTTP 压缩算法调整,影响到了配置特殊 HTTP 压缩算法的服务
防扩散
在灰度阶段,要将问题尽早的暴露出来,并防止问题扩散,其中有两个关键点:
为达成防扩散的目标,设计实现了以下方案:
首先,控制升级顺序,保障:
具体顺序如下:
基于上述升级顺序,对全量服务进行顺序编排,然后逐步对服务进行灰度升级。
其次,控制升级节奏,要防止一次变更影响过多服务,控制好爆炸半径:
分批发布:对服务进行合理的批次划分,确定合适的分批间隔,逐个批次进行升级,目前平台支持指数分批、线性分批策略;
限制变更数量上限:限制好每批的变更数量上限,也限制好每天的变更数量上限。
分批发布 - 指数分批
分批发布 - 线性分批
最后,支持异常检测、异常阻断:
检测到异常后的工单详情页面
异常检测详情页面
逐步全量
灰度验证完成后,说明新版本已经基本稳定,可以开始全量的发布,但是,仍不排除有特殊问题没有暴露出来,因此,在全量的过程中,也要防范问题的发生。
全量阶段,主要目的是进行安全的铺量,在保证安全的前提下,将新版本逐步的升级到全量服务。
主要采用了以下策略:
不同于灰度阶段使用热升级的方式,使用安全升级进行全量,安全升级不会让版本立即生效,而是配置好目标版本,跟随业务升级生效。使用安全升级,可以避免热升级可能导致的业务流量受损,并且服务在升级时,有服务负责人进行充分的稳定性观察,相比热升级安全很多。
和灰度验证类似,安全铺量阶段,也采用相同的升级顺序控制,确保先升级不敏感 / 不重要的服务,保障敏感 / 重要的服务。
和灰度验证类似,安全铺量阶段,也采用相同的升级节奏控制,进行分批升级,限制变更数量上限,控制好爆炸半径。
由于升级的区域很多,为加速升级速度,对不同的区域进行合理的并行推进,加快推进速度。
流程总结
对升级流程进行总结,以下为一个升级流程的全貌,包括灰度阶段、全量阶段,以及,升级完成后的版本收敛阶段。
平台将这些流程、策略都固化下来,支持了大规模升级流水线,可以支持自动化的版本升级,保障变更安全,提升变更效率。
以 Service Mesh 升级为例,各阶段大概耗时如下:
- 灰度阶段 - 线下:5 个工作日
- 灰度阶段 - 线上各区域:12 个工作日
- 全量升级(线下 & 线上):11 个工作日
以 Service Mesh 升级为例,各阶段大概耗时如下:
异常检测
在 Sidecar 升级过程中,平台支持主动检测、主动发现异常,在出现问题后,平台可以及时的阻断异常,降低故障影响时间,减少业务损失。
Sidecar 升级过程中,如果新版本有问题,一般会导致 Sidecar 自身或者业务出现异常问题,比如:
这些问题一般能从指标、日志等方面检测出来,也可以从服务告警反映出异常。因此,我们可以对这些指标、日志、服务告警等进行检测,检测是否有异常发生。
我们和字节内部上线检测平台(Niffler)合作,构建了 Sidecar 检测模型,在升级过程中对服务、Sidecar 的异常进行检测,检测模型包含以下三类检测指标:
落地效果
以 Service Mesh 为例,该大规模升级方案上线后,升级稳定性和效率都有明显收益:
在稳定性方面,很多问题在灰度验证时被及时发现,异常检测机制也检测、发现到很多异常,版本升级导致的事故数量、等级明显降低。
在升级效率方面,Service Mesh 发布一次大版本,小版本数量和发布耗时都明显下降:
Service Mesh 在一个大版本的升级过程中,会发布小版本进行灰度、全量的全流程,如果小版本成功全量到所有服务,则完成大版本的升级。
但是,在小版本发布过程中,如果有紧急 feature、问题修复,则需要重新发布新的小版本,一般要发布多个小版本,才能完成大版本升级。
Service Mesh 在一个大版本的升级过程中,会发布小版本进行灰度、全量的全流程,如果小版本成功全量到所有服务,则完成大版本的升级。
但是,在小版本发布过程中,如果有紧急 feature、问题修复,则需要重新发布新的小版本,一般要发布多个小版本,才能完成大版本升级。
下一步计划
1. 继续提升效率
目前,虽然大规模升级效率已经有了明显提升,但是由于字节跳动业务覆盖区域很多,平台缺乏多区域串联能力,目前操作所有区域的升级仍是一件繁琐的事情。因此,我们计划会进一步增强多区域升级的能力,降低多区域操作成本。
另外,为了解决升级过程中,如果发现版本缺陷,进行修复并重新升级,对升级速度影响过大的问题,我们也在探索更高效的小版本自动验证机制,进一步加快问题发现能力,加快升级速度。
2. 完善异常检测
目前,虽然支持了异常检测能力,但是当前的检测模型还比较简单,检测准确率有待提升,存在较多的误报、漏报。因此,我们后续会对检测模型进行进一步调优,提升准确率,以发挥异常检测的更多价值。
3. 加强版本收敛
目前,虽然设计了版本收敛阶段,但是平台对于版本收敛的功能支持并不好。有些 Sidecar 仍旧会存在比较多的长尾版本,并且如果出现缺陷版本,召回流程也比较繁琐。因此,我们后续会进一步加强版本收敛能力,支持更有效的长尾版本收敛、缺陷版本召回功能。
AI 大模型热潮来袭,看机密计算如何应对敏感数据安全挑战
号称比 Python 快 68000 倍的 Mojo 语言正式发布!Rust 能否与之匹敌?
小米一开源项目被批“三无”,项目导师回应;Ruby on Rails之父将Type从Turbo框架中移除 | Q资讯
大模型之战,腾讯来了