共计 7725 个字符,预计需要花费 20 分钟才能阅读完成。
作者
吴连火,腾讯游戏专家开发工程师,负责欢畅游戏大规模分布式服务器架构。有十余年微服务架构教训,善于分布式系统畛域,有丰盛的高性能高可用实践经验,目前正率领团队实现云原生技术栈的全面转型。
导语
欢畅游戏这边对 istio 服务网格的引进,自 2019 开始,从调研到规模化落地,至今也已近三年。本文对实际过程做了一些思考总结,冀望能给对网格感兴趣的同学们以参考。
在注释开始之前,先明确一下本文所说的服务网格(service mesh)概念 —— 基于 sidecar 通信代理,网状拓扑的后端架构级解决方案。目前业界最风行的开源解决方案为 istio。
服务网格的架构思维,是解耦,以及加一层。通过将根底的治理能力从过程中解耦进来,以 sidecar 的模式提供,以达到更大规模的复用,一旦标准化,将会是行业级的复用!其实作为微服务畛域煊赫一时的解决方案,网格所做的解耦分拆过程这件事件自身就很“微服务”,因为微服务其实也是做过程拆分,解耦并独立部署,以不便服务的复用。
现状与收益
技术栈现状
- 编程语言:go / c++ / python
- meta 体系:protobuf(用于形容配置、存储、协定)
- RPC 框架:gRPC
- 单元测试:gtest
- 容器化:docker + k8s
- 网格:istio,envoy 网关
- 配置:基于 pb 的 excel 转表工具,配置散发管理中心
- 监控:prometheus
- 其余:代码生成工具,蓝盾流水线,codecc 代码扫描,helm 部署等。
外围收益
- 技术价值观:团队的技术价值观变得比拟凋谢,拥抱开源生态,贴近云原生技术栈。
- 团队成长:大技术栈演进,是一项颇具挑战性的工作,团队同学在打怪降级之后天然就有了能力的晋升。
- RPC 框架:通过引入 gRPC 对立了跨语言的 RPC 框架,原自研 RPC 框架也持续在用,但底层会适配为 gRPC。
- 引入 golang:引入了 golang 做惯例个性研发,进步了研发效率。
- 网格能力:无需开发,基于 istio 的 virtual service 做流量治理,按 label 聚合分版本调度流量,应用一致性 hash。
- 机器老本:这是惟一绝对好量化的收益点,精确的数据还是要等后续实现 100% 上云后才好给出,初步估算的话,可能是原来的百分之六七十。
总体上,咱们做的是一个大技术栈体系的演进,体现了较好的技术价值,晋升了研发效力。所以对于咱们而言,当初再回望,网格化是否值得实际?答案仍旧是必定的。
但如果抛开技术栈演进这个大背景,独自看网格自身的话,那么坦率地讲,咱们对网格能力的应用是较为初步的:
- 转不转包:熔断、限流、重试(以幂等为前提),暂未实际。
- 包转给谁:名字服务,有实际,应用了 virtual service,应用了 maglev 一致性 hash。
- 调试性能:故障注入、流量镜像,暂未实际。
- 可观测性:关掉了 tracing,暂未实际。
思考到理论开销状况,咱们并没有拦挡 inbound 流量,所以如果有依赖这点的性能个性,目前也无奈实际。
网格的真正卖点
从笔者集体的察看来讲,istio 网格最具吸引力的,实际上就两点:
- 凋谢技术栈的设想空间,随着 istio、envoy、gRPC 整个生态越来越丰盛,将来可能会有更多能力提供,开箱即用,业务团队不用投入开发。
- 多语言适配,不必为每种语言开发治理 sdk,例如 C++ 编写的 envoy 能够给所有用 gRPC 的 service 应用。
至于熔断、限流、平衡、重试、镜像、注入,以及 tracing 监控之类的能力,严格来讲不能算到网格头上,用 sdk 也是一样能够实现的。在团队语言对立的时候,只用保护一种语言版本的 sdk,此时采纳治理 sdk 计划也是可行的,也就是所谓的微服务框架计划。采纳 sdk 形式下的版本保护问题,以及前期进一步演进网格的问题,这些都不难解决,这里不再发散。
对于咱们本人来讲,因为恰好有引进 golang 以及 gRPC,所以当初再看,抉择 istio 作为网格计划也算适合。
网格的思考实际
一些前置条件
接入网格,要思考天时地利人和。即,须要满足一些根本条件:
- 须要我的项目阶段容许,如果团队自身始终在做快版本内容迭代,业务需要都忙不过来,恐怕也很难有人力保障。
- 要有基础设施环境反对(咱们应用了腾讯云的 tke mesh 服务),这样不至于所有货色都从零开始。
此外,对于这类大的技术优化,还有必要先对立思维:
- 自上而下,取得各级治理干系人的认可,这样才好做较大人力的投入。
- 自下而上,动员同学们深度染指探讨,使得整体的方向、计划失去大家的认可,这样大家才有干劲。
口头之前的三思
在晚期的构思阶段,须要明确几个大的关键问题:
- 1)想要达到什么指标?节约机器老本 / 晋升研发效力 / 造就团队 / 技术栈演进?如果要达到对应的指标,有没有其余更优门路?
- 2)有没有失控危险?性能是否不可承受,k8s、istio 稳定性是否足够,有没有极其的可用性大危险?
- 3)如何安稳地过渡?服务搬迁过程,研发模式是否都能够平稳过渡?
对于第一点,不同团队要看本人的理论状况,这里不做开展。
对于第二点,k8s 在业界的大规模利用十分多,所以还算是牢靠的,而且它 level triggered 的设计,使其具备较好的健壮性。绝对未知的是 istio,团队一开始对 istio 做了一些压测,也思考了回退无 mesh 的情景,论断是能够尝试。istio 实质上就是一个简单大型软件,所以其自身次要使人望而却步的点,是其简单的配置,版本之间的兼容性担心,以及偏黑盒可控性不好这几点。当初想来,其实咱们团队的步子迈得还是比拟大的。侥幸的是,前面的落地过程表明,istio 自身稳定性也还行,不至于三天两头出问题。
对于第三点,咱们针对性地做了引入间接层的设计,应用公有协定与 gRPC 互转的网关确保了服务平滑迁徙上云,在服务外部引入 grpc 适配层确保了研发人员的开发模式根本不变。
零碎整体架构
零碎整体架构如下图所示,能够清晰地看到上文所说的间接层:
图示:gRPC 适配与网格内外通信代理
云原生研发体验
对于评需要、定计划、写代码等差别不大的点,这里不做开展。上面次要列举一些在云原生的技术栈体系下,与咱们以前相比,有显著差别的一些研发体验。
- helm:通过 helm 治理所有服务的内外网 yaml,在服务本身 yaml 里残缺形容其所有部署依赖。
- 测试环境 dev 正本:因为零碎服务过多,尽管内网都是 debug version,资源耗费要远低于 release 版本,但思考到简单的服务间依赖,为每个人部署一套测试环境也不可取,所以目前还是抉择的多数几套环境,大家复用。对于多人自测环境的抵触问题,咱们借助网格的能力,做了基于 uin 的 dev 正本部署,这样当小 A 同学开发特定服务的时候,他本人的申请会落到本人的专属 deployment 上。
图示:基于不同号码部署不同的专属 deployment
- 测试环境每日全量 主动构建部署:然而这也带来一个问题,pod 重建漂移后日志、coredump 等信息都不匹配,例如测试同学反馈说前一天遇到个什么问题,而后开发也不晓得前一天在哪个 pod(曾经被销毁)。咱们通过设置 k8s 节点亲和策略 preferredDuringSchedulingIgnoredDuringExecution,联合日志门路固定化(取 deployment 名而非 pod 名),确保测试环境下 pod 重建后还在原 node,日志门路也保持一致,这样进入同服务的新 pod 便能够持续看到前一天的日志。
- 外网金丝雀版本:灰度期间应用,间接通过 yaml 的 deploymentCanary 配置项关上,借助 istio virtual service 来配置灰度的流量比例。排查外网问题有时候也会启用,对于染色的号码,流量也会导入金丝雀版本。具体实现就是网关过程会读一份号码列表配置,只有是在列表里的号码申请,就给 gRPC 的 header 打上相干的 label,再基于 vs 的路由能力导入到金丝雀版本。
- hpa 实际:对于 hpa 笔者新近的态度还是有些犹豫的,因为这实质上是会将服务部署公布机会变得不可控,不像是惯例人工干预的公布,出了问题好染指。线上也的确出过一些问题,例如 hpa(会依赖 hpa 关联的 metric 链路畅通)夜间生效导致业务过载;还有就是在日志采集弄好之前,hpa 导致 pod 漂移,前一天夜里某 pod 的告警信息,第二天想看就比拟吃力,还得跑到之前调度到的 node 下来看;另外也呈现过过程 hpa 启动不起来的问题,配置有误无奈加载初始化胜利,正在跑着的过程只会 reload 失败,然而停掉重启就会启动失败。不过 hpa 对于晋升资源利用率,还是很有价值的,所以咱们当初的做法是做辨别看待,对于一般的业务,min 正本数能够较小,对于重要的服务,min 正本数则配置稍大一些。
- 优雅启停:间接基于 k8s 的就绪、存活探针实现。
- 外网日志收集:这块之前始终还没有用到比拟好用的平台服务,业务本人有打过 rsyslog 近程日志,前面可能会用 cfs 挂网盘,也算能对付用。
- 配置体系:配置的定义用 protobuf,配置的解析基于代码生成,配置的散发基于 rainbow,配置的拉取基于 configAgent,配置的归档表白以 excel 模式放在了 svn,用工具实现 excel 到程序读取格局的转换。configAgent,是 webhook 给 pod 动静注入的容器。
- 监控体系:prometheus,云监控。
- DEBUG_START 环境变量:在容器化部署的晚期,咱们遇到过一些过程启动失败的状况,重复拉起失败,而后 pod 到处漂移,排查很不不便,所以咱们减少了 DEBUG_START 环境变量,如果设置为 true 的时候,过程启动失败时不退出容器。
- 云上 perf因为一些平安的权限起因,容器内无奈 perf,当初是长期申请 node 的 root 权限进行 perf,须要在 node 上也放一份二进制文件,不然 perf 无奈解析 symbol 信息。对于 go 服务的话,则间接应用它本人的工具链来分析。
- 问题 pod 现场保留:因为 deployment 是基于 label 辨认的,所以对于外网那种想保留故障 pod 的现场时会很简略,间接改一下 label 就好了。
- coredump 查看:段谬误信号捕捉后会把二进制自身也拷贝到 coredump 的文件夹,轻易 attach 到 coredump node 上以后存活的任意 pod 就能够查看。
- 代码生成:这个其实和是否上云关系不大,只是咱们基于 protobuf 做了不少工作(例如用 .proto 定义配置文件,提供相似 xresloader 的性能),深感颇有好处,这里也列一下。后续整顿相干代码并欠缺文档后,也会思考开源。
性能状况
探讨性能之前,这里先说一下咱们的实际形式:关掉 tracing,关掉 inbound 拦挡(远端流量过去的时候,并不会走 sidecar)。
图示:pod1 上的业务容器调用 pod2 上的服务,仅拦挡 outbound
在上述背景下,联合咱们的线上实在案例状况,分享一下读者可能会比拟感兴趣的性能数据:
- 内存开销:零碎中共有几百个服务,应用一致性 hash,envoy sidecar 的内存占用约两三百兆。
- CPU 开销:典型 cpu 开销和扇出状况相干,例如一个服务较多拜访其余 gRPC 服务,那么 envoy 的 cpu 开销甚至会超过主业务过程,但当业务过程扇出较少时 envoy 的开销就比拟低。
对于内存开销的问题,社区有绝对明确的解决方案,采纳 sidecar crd 来限定载入业务所需拜访指标服务的 xds 信息,即可大幅缩小内存占用。业务过程须要拜访哪些指标服务,能够通过手动保护、动态注册或代码生成之类的方法明确,咱们前面也会做相干的优化。
接下来咱们用绝对大的篇幅讨论一下 cpu 开销的问题,先看一个大扇出业务的性能 top 示例:
图示:大扇出业务过程与 envoy 性能比照示意
看到上图中的数据,读者可能会有这样的疑难:为什么仅反对 gRPC 的转发,envoy 就须要如此高的 cpu 开销(图中 71.3%,远超业务过程的 43.7%)呢?对于这点,咱们在剖析火焰图之后,也没有发现显著异样的中央,它所做的次要工作,也就是在做协定的编解码与路由转发而已,无显著异样热点。
图示:envoy 火焰图示意
当初网上大量介绍 envoy 的材料,根本都会说它性能比拟好,难道 … 假相其实是 envoy 其实做的不够高效么?针对这个问题,笔者这里也无奈给出一个明确的答案,envoy 外部的确大量应用了各种 C++ 的形象,调用层级比拟多,但这未必是问题的关键所在,因为:
- 可能是 envoy 应用的 libnghttp2 协定解析库的性能连累所致 …
- 可能是 envoy 应用 libnghttp2 的“姿态”不大对,没有充分发挥其性能 …
- 抑或是 http2 解析、编解码,以及收发包原本就须要耗费这么多的 cpu?
对于最初这一点,咱们观测了业务主过程中的 grpc thread,它也须要做 http2 的解析和编解码,但它的 cpu 开销显然低得多。
图示:业务过程中的 grpc 线程 %cpu * 2 后仍然比 envoy 小很多
将业务过程中的 grpc 线程(红框局部)%cpu 乘 2 后再与 envoy(蓝框局部)做比照,是因为 envoy 对 outbound 拦挡的 workload 绝对业务过程而言的确近似翻倍,例如就编解码而言,对于一次 req、rsp,业务过程就是 req 的编码和 rsp 的解码,然而对于 envoy,则是 req 的解码 + 编码,rsp 的解码 + 编码。
图示:envoy vs 业务过程的编解码开销
从下面的示例来看,grpc 本人做 http2 parse + 编解码 + 收发包的性能,要远好于应用 libnghttp2 的 envoy,但 envoy 显然不可能间接采纳 grpc 外面的相干代码。要想更好地答复对于 envoy 做 grpc 通信代理性能的疑难,恐怕还须要做更加粗疏的剖析论证以及测试(欢送感兴趣或有教训的读者来交换)。
总之对于 gRPC 大扇出业务 sidecar cpu 损耗过大的这个问题,咱们临时也没想到好的优化计划。当然下面那个案例其实绝对极其,因为是大扇出 + 主业务过程为 C++ 的状况,如果是小扇出则 sidecar 不会耗多少 cpu,如果是 golang 业务过程则 sidecar 占 pod 整体 cpu 开销的比例不会这么夸大(当然这也反过来阐明 golang 性能和 C++ 差距还是蛮大的 …)。
对于咱们本身来讲,网格的综合性能并没有重大到无奈承受的境地:
- 首先很多业务并不是大扇出型的,这类业务下的 sidecar 的开销并不大。
- 其次对于 golang 类的业务过程,sidecar 相较带来的涨幅比例也会小一些。
- 最初绝对于传统 IDC 粗放的部署形式,在咱们做了整体上云之后,总体上还是更省机器的。
公有协定或公有网格
如前文所述,envoy 的性能问题,在大扇出业务场景下的确难以漠视。
如果真的无奈承受相应的性能开销,那么可能公有协定或公有网格会是可选的代替计划。
- 采纳公有协定,基于 envoy 本人写 filter,解析公有协定头,而后联合 envoy xds 相干的能力来提供服务(能够参考腾讯开源的解决方案 https://github.com/aeraki-mes…),不难想象在该计划下,齐全无需解析 http2,性能必然会有十分显著的晋升。但如果咱们真的走到公有协定的老路上去,其实就等于又放弃了 gRPC 生态。(参考前文网格外围卖点 1)
- 采纳公有网格,本人实现 xDS 绝对应的系列能力,能够先从最外围能力做起。但采纳该计划的话,就又会回到多语言反对的问题上来,须要为 C++ 和 golang 都实现对应的能力(参考前文网格外围卖点 2)。如果真的要本人实现公有网格,在设计上,该当思考语言相干的 sdk 代码是绝对繁难的,路由策略等管制面性能仍旧下沉在自研 sidecar/agent 里,数据面逻辑出于性能思考则由业务过程本人解决。
将来趋势瞻望
欢畅本人的实际
对于欢畅本人的团队而言,前面会继续做更深度的实际。例如 envoy filter 开发、k8s crd,以及 istio 的更多能力的实际(上文也提到了,咱们目前仅应用了一小部分网格能力,冀望当前能应用熔断、限流等能力来晋升业务的可用性)。
ebpf 的交融
ebpf 可能将来会与容器网络、网格有更好的交融,能够晋升网络相干性能体现,或者还会带来其余一些可能。
proxyless mesh
proxyless mesh 能够看做基于前文探讨性能问题的一个延长,和后面提及的公有网格有些相似。这类计划也会有对应的生存空间,因为始终有些团队无奈承受数据面 sidecar 所带来的性能开销:
- 时延,这点也有不少团队提及,但如果是一般互联网业务,笔者集体认为多几十毫秒级别的提早影响都不大。
- cpu 和内存开销,前文已有较多探讨。
proxyless mesh 实际上就是 sdk + 网状拓扑的计划,gRPC 当初也在继续欠缺对 xDS 的反对,所以也有可能借助 gRPC 的能力来实现。如果自行研发反对 xDS 的 sdk,那对于团队的投入还是有要求的,除非团队自身就是大厂的中间件类团队(网易轻舟、百度服务网格、阿里 dubbo,这一两年都有做 proxyless mesh 的实际)。
图示:proxyless gRPC mesh
公有计划对标 xDS
对于编程语言对立的团队,例如全 golang,那么只用保护一套服务治理相干的 sdk(管制面逻辑也能够用 agent 承载),所以可能会偏向于做一套本人公有的解决方案。据笔者理解,B 站之前就是采纳的这种计划,参考 eureka 实现名字服务本人做流量调度。
当初随着网格的风行(起码对应的理念曾经广为人知了),公有计划也能够参考对标 xDS 的各种 feature。因为公有计划通常是自研的,所以实践上还能提供绝对高效可控的实现,然而须要团队继续投入保护。
Dapr 运行时
概念很好,故事很巨大,不过目前看来还为时过早。
参考资料
让 istio 反对公有协定:【https://github.com/aeraki-mes…】
grpc 对 xDS 的反对:【https://grpc.github.io/grpc/c…】
proxyless grpc:【https://istio.io/latest/blog/…】
nghttp2 解析库:【https://nghttp2.org/】
infoQ 根底软件翻新大会微服务专场:【https://www.infoq.cn/video/7R…】
xresloader 配置转换工具:【https://github.com/xresloader…】
Dapr:【https://dapr.io/】
对于咱们
更多对于云原生的案例和常识,可关注同名【腾讯云原生】公众号~
福利:
①公众号后盾回复【手册】,可取得《腾讯云原生路线图手册》&《腾讯云原生最佳实际》~
②公众号后盾回复【系列】,可取得《15 个系列 100+ 篇超实用云原生原创干货合集》,蕴含 Kubernetes 降本增效、K8s 性能优化实际、最佳实际等系列。
③公众号后盾回复【白皮书】,可取得《腾讯云容器平安白皮书》&《降本之源 - 云原生老本治理白皮书 v1.0》
④公众号后盾回复【光速入门】,可取得腾讯云专家 5 万字精髓教程,光速入门 Prometheus 和 Grafana。
【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!