内容简介:【编者的话】随着见闻业务不断增加,所涉及语⾔也越来越多。由于微服务化的引入,就需要为不同语言开发各自的服务发现、监控、链路追踪等组件,更新运维成本较高。同时应用的灰度部署也是见闻在着⼒解决的问题。 Istio通过下沉基础设置,很好的解决了组件跨语言兼容问题, 同时带来了智能路由、服务熔断、错误注入等重要的特性。整个搭建过程中也遇到了很多坑和经验,希望和大家分享。见闻开发团队以Golang为主,同时存在Python,Java服务,这就需要SRE提供更容易接入的微服务基础组件,常见的方案就是为每种语言提供适配的
【编者的话】随着见闻业务不断增加,所涉及语⾔也越来越多。由于微服务化的引入,就需要为不同语言开发各自的服务发现、监控、链路追踪等组件,更新运维成本较高。同时应用的灰度部署也是见闻在着⼒解决的问题。 Istio通过下沉基础设置,很好的解决了组件跨语言兼容问题, 同时带来了智能路由、服务熔断、错误注入等重要的特性。整个搭建过程中也遇到了很多坑和经验,希望和大家分享。
见闻开发团队以Golang为主,同时存在Python,Java服务,这就需要SRE提供更容易接入的微服务基础组件,常见的方案就是为每种语言提供适配的微服务基础组件,但痛点是基础组件更新维护的成本较高。
为了解决痛点,我们将目光放到服务网格,它能利用基础设施下沉来解决多语言基础库依赖的问题,不同的语言不需要再引入各种不同的服务发现、监控等依赖库,只需简单的配置并运行在给定的环境下,就能享有服务发现、流量监控、链路追踪等功能,同时网络作为最重要的通信组件,可以基于它实现很多复杂的功能,譬如智能路由、服务熔断降级等。
我们调研了一些服务网格方案,包括Istio、Linkerd。
对比下来,Istio拥有更多活跃的开源贡献者,迭代速度快,以及Istio架构可行性讨论,我们选择Istio作为实践方案。
服务网格架构图:
这张图介绍了华尔街见闻典型的服务网格架构,左半图介绍了用户请求是如何处理,右半图介绍运维系统是如何监控服务。
架构可行性
通过架构图,我们拆分出以下关键组件,经过评估,Istio高度模块化、可拓展,各个组件的可用性、拓展性都有相应的策略达到保障,我们认为Istio是具有可实施性的。
Istio Ingress高性能,可拓展
性能:Istio Ingress用来处理用户入流量,使用Envoy实现,转发性能高。
可用性:保证实例数量并使用服务探活接口保证服务可用性。
拓展性:挂载在负载均衡后,通过增加实例实现可拓展。
Istio Proxy随应用部署,轻微性能损耗,可随应用数量拓展
Istio Proxy以Sidecar形式随应用一起部署,增加2次流量转发,存在性能损耗。
性能:4核8G服务器,上面运行Proxy服务和API服务,API服务只返回ok字样。(此测试只测试极限QPS)
单独测试API服务的QPS在59k+,平均延时在1.68ms,CPU占用4核。 通过代理访问的QPS6.8k+,平均延时14.97ms,代理CPU占用2核,API服务CPU占用2核。
CPU消耗以及转发消耗降低了QPS,增加了延时,通过增加机器核数并增加服务部署数量解决该问题,经过测试环境测试,延时可以接受。
可用性:基于Envoy,我们认为Envoy的可用性高于应用。依赖Pilot Discovery进行服务路由,可用性受Pilot Discovery影响。
拓展性:Sidecar形式,随应用数拓展。
Istio Policy服务可拓展,但同步调用存在风险
Istio Policy需要在服务调用前访问,是同步请求,会增加服务调用延时,通过拓展服务数量增加处理能力。属于可选服务,华尔街见闻生产环境未使用该组件。
性能:未测试。
可用性:若开启Policy,必须保证Policy高可用,否则正常服务将不可用。
拓展性:增加实例数量进行拓展。
Istio Telemetry监控收集服务
性能:从监控上观察Report 5000qps,使用25核,响应时间p99在72ms。异步调用不影响应用的响应时间。
可用性:Telemetry不影响服务可用性。
拓展性:增加实例数量进行拓展。
Pilot Discovery
性能:服务发现组件(1.0.5版本)经过监控观察,300个Service,1000个Pod,服务变更次数1天100次,平均CPU消耗在0.04核左右,内存占用在1G以内。
可用性:在服务更新时需要保证可用,否则新创建的Pod无法获取最新路由规则,对于已运行Pod由于Proxy存在路由缓存不受Pilot Discovery关闭的影响。
拓展性:增加实例数量可以增加处理量。
服务监控
Istio通过mixer来搜集上报的遥测数据,并自带Prometheus、Grafana等监控组件,可方便的对服务状态进行监控。见闻目前监控在用Istio自带的,利用Prometheus拉取集群指标,经由Grafana看板展示,可直观展示出各种全局指标及应用服务指标,包括全局QPS、全局调用成功率、各服务延时分布情况、QPS及状态码分布等, 基本满足监控所需。
存储暂未做持久化操作,采用Prometheus的默认的内存存储,数据的存储策略可通过设定Prometheus的启动参数 --storage.tsdb.retention 来设定,见闻生产时间设定为了6h。
Prometheus服务由于数据存储原因会消耗大量内存,所以在部署时建议将Prometheus部署在专有的大内存node节点上,这样如果内存使用过大导致该node节点报错也不会对别的服务造成影响。Istio mixer担负着全网的遥测数据搜集任务,容易成为性能瓶颈,建议和Prometheus一样将其部署在专有节点上, 避免出现问题时对应用服务造成影响。
以下是Mesh汇总面板的Demo:
Service Mesh汇总监控页面
链路追踪
Envoy原生支持分布式链路追踪, 如Jaeger、Zipkin等,见闻生产选择了Istio自带的Jaeger作为自身链路追踪系统。 默认Jaeger服务为all_in_one形式,包含jaeger-collect、jaeger-query、jaeger-agent等组件,数据存储在内存中。
见闻测试集群采用了此种部署形式。见闻生产环境基于性能与数据持久性考虑,基于Cassandra存储搭建了单独的jaeger-collect、jaeger-query服务。Jaeger兼容Zipkin,可以通过设定Istio ConfigMap中的 zipkinAddress 参数值为jaeger-collector对应地址,来设置Proxy的trace上报地址。同时通过设置istio-pilot环境变量 PILOT_TRACE_SAMPLING 来设置tracing的采样率,见闻生产采用了1%的采样率。
Tracing不像Istio监控系统一样对业务代码完全无侵入性。Envoy在收发请求时若发现该请求没有相关trace headers,就会为该请求自动创建。tracing的实现需要对业务代码稍作变动,这个变动主要用来传递trace相关的header,以便将一次调用产生的各个span串联起来。
见闻底层采用 grpc 微服务框架,在Gateway层面将trace header 加入到入口grpc调用的context中,从而将trace headers 逐级传递下去。
Istio探活
Istio通过向Pod注入Sidecar接管流量的形式实现服务治理,那么就会有Sidecar与业务容器状态不同步的可能,从而造成各种的调用问题,如下两方面:
- Sidecar就绪时间晚于业务容器:业务容器此时若发起调用,由于Sidecar还未就绪, 就会出现类似no healthy upstream之类错误。若此时该Pod接收请求,就又会出现类似upstream connect error错误。
- Sidecar就绪时间早于业务容器:例如某业务容器初始化时间过长导致Kubernetes误以为该容器已就绪,Sidecar开始进行处理请求,此时就会出现类似upstream connect error错误。
探活涉及Sidecar、业务容器两部分,只有两部分同时就绪,此Pod才可以正式对外提供服务,分为下面两方面:
- Sidecar探活:v1.0.3及以上版本针对Pilot-agent新增了一个探活接口healthz/ready,涉及statusPort、applicationPorts、adminPort等三个端口。其基本逻辑为在statusPort上启动健康监测服务,监听applicationPorts设定的端口是否至少有一个成功监听,之后通过调用本地adminPort端口获取xDS同步状态。若满足至少一个applicationPort成功监听,且CDS、LDS都进行过同步,则该Sidecar才被标记为Ready。
- 业务容器探活:见闻通过基本库,在所有Golang grpc后端服务中注册了一个用于健康检查的handler, 该handler可由开发人员根据自身业务自定义,最后根据handler返回值来判断业务容器状态(如下图)。
Istio应用更新
为了实现灰度部署,见闻基于Kubernetes Dashboard进行了二次开发,增加了对Istio相关资源的支持,利用Gateway、VirtualService、DestinationRule等crd实现了应用程序的灰度部署,实际细节如下:
- 更新流量控制将流量指向已有版本 ,利用VirtualService将流量全部指向v1版本(见下动图)。
- 部署新版本的Deployment ,查找旧的Deployment配置,通过筛选app标签符合应用名的Deployment,运维人员基于该Deployment创建v2版本的Deployment,并向destinationRule中增加v2版本。
- 更新流量控制将流量指向新版,本 利用VirtualService将ServiceA的服务流量全部指向v2版本。
- 下线老版本的Deployment并删除对应DestinationRule。
利用Istio Dashboard来实现上述流程:
为了方便开发人员服务部署,开发了精简版后台,并对可修改部分进行了限定。最终,SRE提供两个后台,对Istio Dashboard进行精细控制:
实践中的宝贵经验
在Istio实践过程中,有哪些需要注意的问题。
API server的强依赖,单点故障
Istio对Kubernetes的API有很强的依赖,诸如流量控制(Kubernetes资源)、集群监控(Prometheus通过Kubernetes服务发现查找Pod)、服务权限控制(Mixer Policy)。所以需要保障API server的高可用,我们曾遇到Policy组件疯狂请求Kubernetes API server使API server无法服务,从而导致服务发现等服务无法更新配置。
* 为避免这种请求,建议使用者了解与API server直接通信组件的原理,并尽量减少直接通信的组件数量,增加必要的Rate limit。
* 尽量将与API server通信的服务置于可以随时关闭的环境,这是考虑如果部署在同一Kubernetes集群,如果API server挂掉,无法关闭这些有问题的服务,导致死锁(又想恢复API server,又要依靠API server关闭服务)。
服务配置的自动化
服务配置是Istio部署后的重头戏,避免使用手动方式更改配置,使用代码更新配置,将常用的几个配置更新操作做到运维后台,相信手动一定会犯错。
关于Pilot Discovery
Pilot Discovery 1.0.0版本有很大的性能问题,1.0.4有很大的性能提升,但引入了一个新bug,所以请使用1.0.5及以上的版本,我们观察到CPU消耗至少是1.0.0版本的1/10,大大降低了Proxy同步配置的延时。
关于Mixer Policy 1.0.0
这个组件曾导致API server负载过高(很高的list pods请求),所以我们暂时束之高阁,慎用。
性能调优
在使用Proxy、Telemetry时,默认它们会打印访问日志,我们选择在生产上关闭该日志。 时刻观察Istio社区的最新版本,查看新版本各个组件的性能优化以及bug修复情况,将Istio当做高度模块化的系统,单独升级某些组件。上面就提到我们在Istio1.0的基础上使用了1.0.5版本的Policy、Telemetry、Pilot Discovery等组件。
服务平滑更新和关闭
Istio依靠Proxy来帮助APP进行路由,考虑几种情况会出现意外的状态:
* APP启动先于Proxy,并开始调用其它服务,这时Proxy尚未初始化完毕,APP调用失败。
* Service B关闭时,调用者Service A的Proxy尚未同步更新Service B关闭的状态,向Service B发送请求,调用失败。 第一种情况要求APP有重试机制,能适当重试请求,避免启动时的Proxy初始化与APP初始化的时差,Istio提供了retry次数配置,可以考虑使用。 第二种情况,一种是服务更新时,我们使用新建新服务,再切流量;一种是服务异常退出,这种情况是在客户端重试机制。希望使用Istio的开发人员有更好的解决方案。
Q&A
Q:学Service Mesh什么用?
A:Service Mesh是最近比较火的一个概念,和微服务、Kubernetes有密切关系。出于以后业务发展需要,可以学习下, 增加知识储备。见闻上Istio的主要目的在文章已说明,主要是基础服务的下沉,解决了语言兼容性问题, 还有一个就是灰度发布。
Q:链路追踪的采集方式是怎样的,比如Nodejs,C++等多语言如何支持的?
A:Envoy本身支持链路追踪,也就是将Envoy会在请求head中增加链路追踪相关的数据头,比如x-b3-traceid,x-b3-spanid等等。业务要做的就是将这些head沿着调用链路传递下去即可。所以多语言的话需要在自己的业务侧实现该逻辑。所以Istio的链路追踪对业务代码还是有很小的侵入性的(这个分享中有说明)。
Q:Istio与Spring Cloud两者的优缺点与今后的发展趋势会是怎么样?
A:见闻技术栈是Golang,所以没太认真对比过两者。从社区活跃度上将,Istio > Spring Cloud,稳定性方面,Spring Cloud是更有优势,更适合 Java 沉淀较深的企业。但个人感觉对于更多企业来讲,跨越了语言兼容性的Istio未来发展很值得期待。
Q:Docker镜像部署可以做到代码保护吗,比如像Nodejs这种非二进制执行程序的项目?
A:代码保护可以通过将镜像上传至指定云服务商上的镜像仓库中,见闻是将自己的业务镜像提交保存在了腾讯云。如果镜像泄露,那么非二进制执行程序的代码还是有泄露风险的。
Q:选型时为什么没考虑Linkerd?
A:选型之初也调研了Linkerd, 对比下来,Istio拥有更多活跃的开源贡献者,迭代速度快,以及Istio架构相较于见闻有较大可行性,所以选择了Istio作为实践方案。
Q:Istio在做运维部署时没有UI工具,你们如何实现运维人员更加便捷地使用?
A:见闻基于Kubernetes官方的Dashboard, 对内容进行了扩充,增加了对Gateway,VirtualService等Istio crd资源的支持, 同时增加了灰度部署等和见闻运维业务相关的功能,所以一定程度上解决了运维部署的问题。
Q:流量从Sidecar代理势必会对请求响应时间有影响,这个有没有更详细案例的说明性能上的损耗情况?
A:Sidecar的转发其实带来了性能一定的性能损耗。4核8G服务器,上面运行Proxy服务和API服务,API服务只返回ok字样。(此测试只测试极限QPS)单独测试API服务的QPS在59k+,平均延时在1.68ms,CPU占用4核。通过代理访问的QPS6.8k+,平均延时14.97ms,代理CPU占用2核,API服务CPU占用2核。 CPU消耗以及转发消耗降低了QPS,增加了延时,通过增加机器核数并增加服务部署数量缓解该问题,经过测试环境测试,延时可以接受。
Q:Sidecar在生产中资源占用为多少?是否会对集群资源占用很多?
A:以单个Pod为例,见闻业务单个Pod中Sidecar所占资源约占整个Pod所耗资源的1/10。
Q:Jeager你们是进行了代码埋点吗?更为底层代码级别的追踪,有用其他方案吗?
A:Envoy本身对tracing有良好的支持,所以业务端所做的改动只需将其所产生的追踪数据延续下去即可。上Istio之前,见闻在相关微服务中通过在基础库中增加链路追踪逻辑(Zipkin)实现了链路追踪,不过只做了Golang版,多语言兼容开发运维难度较大。
Q:相信咱们的mixer在生产环境中,也出现过瓶颈,咱们从哪几个大方向优化的?如何优化的?方面讲解一下吗?
A:mixer见闻在生产过程中所遇的坑在于Policy组件, 会疯狂的list pod,导致API server负载骤增,之后见闻基于自身业务关闭了Policy。
Q:Istio组件实现了高可用么?
A:Istio本身也是基于Kubernetes,所以可用性还是有较好保证的。
以上内容根据2019年4月23日晚微信群分享内容整理。分享人 张安伟,华尔街见闻SRE团队运维工程师,负责公司日常运维开发 。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesd,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 面试见闻
- AAAI 19见闻
- AIS2019见闻
- SpringOne Platform大会见闻
- 顶会见闻系列:NeurIPS 2018 论文精选
- JetBrains开发者日见闻(一)之Kotlin/Native 尝鲜篇
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Filter Bubble
Eli Pariser / Penguin Press / 2011-5-12 / GBP 16.45
In December 2009, Google began customizing its search results for each user. Instead of giving you the most broadly popular result, Google now tries to predict what you are most likely to click on. Ac......一起来看看 《The Filter Bubble》 这本书的介绍吧!