问题的出现
微服务的出现使得各个业务模块可以独立演进的同时也带来了很多复杂度。
从业务开发来说:
业务服务程序需要引入更多的组件,增加学习负担及开发工作量
服务发现SDK
负载均衡SDK
熔断降级SDK
分布式追踪SDK
服务认证SDK
服务授权SDK
服务日志收集SDK*
配置中心SDK*
......
引入的组件难以更新换代
业务服务程序暂时没有上线计划
业务开发人员不知道版本有更新
业务开发时间紧,没有时间更新不太紧急外围组件
业务开发人员抗拒
对线上运维来说:
网络策略变的更为复杂
若严格配置IP级别的隔离策略,则配置工作量巨大,且无法实弹性伸缩
若配置IP范围段的隔离策略,则安全性有所降低,难以隔离不层级服务的权限
难以快速调整线上限流、熔断等策略
应用可能没有加入相的组件,无法调整
只能从应用级配置中调整该策略,调整位置分散且所需权限较高
解决的办法——ServiceMesh
Service Mesh实际上是一种SDN,等同于OSI模型中的会话层。
(引用自https://www.nginx.com/resources/library/the-enterprise-path-to-service-mesh-architectures/)
ServiceMesh通常用一种叫SideCar的模式完成,SideCar是一个服务的代理,其:
接收发送给被代理服务的所有流量,经过相关处理后,发送给被代理服务
拦截被代理服务往外发送的所有流量,经过相关处理后,发送给其他服务
因为SideCar管控了被代理服务的所有进出网络流量,因此对所有能通过网络路由修改、网络数据分析、网络数据修改达到的功能,ServiceMesh都能达到,包括以下内容:
流量管理
服务注册
服务间调用的负载均衡
服务间调用的限流、熔断甚至于降级
服务间调用重试、故障转移和故障注入
金丝雀发布(灰度发布)
A/B测试
监控管理
服务间调用的分布式追踪*
收集调用请求、反馈等日志
服务间网络调用相关元信息收集
安全
服务身份认证
服务鉴权
终端客户识别(基于JWT等通用协议)
(结合服务身份认证及服务鉴权以及传统的IP范围隔离策略可以得到一个安全性更高、且弹性伸缩友好的综合网络策略。)
目前主流的ServiceMesh框架包含Istio及Linkerd,Linkerd是是ServiceMesh概念的提出者,Istio是谷歌、IBM及Lyft联手打造,目前该项目是ServiceMesh的主流。以下将以Istio为例,浅析ServiceMesh的架构。
Istio实现
Istio 服务网格逻辑上分为数据平面和控制平面。
数据平面由一组以 sidecar 方式部署的智能代理(Envoy)组成。这些代理可以调节和控制微服务及 Mixer 之间所有的网络通信。
控制平面负责管理和配置代理来路由流量。此外控制平面配置 Mixer 以实施策略和收集遥测数据。
Proxy
Istio 使用 Envoy的扩展版本作为Proxy,Envoy 是以 C++ 开发的高性能代理,用于调解服务网格中所有服务的所有入站和出站流量。
其功能包括:
动态服务发现
负载均衡
TLS 终止
HTTP/2 & gRPC 代理
熔断器
健康检查、基于百分比流量拆分的灰度发布
故障注入
丰富的度量指标
Envoy 被部署为 sidecar,和对应服务在同一个 Kubernetes pod 中。这允许 Istio 将大量关于流量行为的信号作为属性提取出来,而这些属性又可以在 Mixer 中用于执行策略决策,并发送给监控系统,以提供整个网格行为的信息。
Mixer
Mixer 是一个独立于平台(K8S等)的组件,负责在服务网格上执行访问控制、执行相关策略、收集遥测数据等。这些操作是由Envoy及Mixer上的插件扩展实现,使其能够接入到各种主机环境和基础设施后端。
在每次请求执行先决条件检查之前以及在每次报告遥测请求之后,Envoy sidecar 在逻辑上调用 Mixer。
该 sidecar 具有本地缓存,从而可以在缓存中执行相对较大比例的前提条件检查。此外,sidecar会批量汇集请求后一次性发给Mixer以此提高性能
我们可以通过在Mixer上开发自定义的Adapter以扩展我们的需要
Pilot
Pilot 为 Envoy sidecar 提供服务发现功能,为智能路由(例如 A/B 测试、金丝雀部署等)和弹性(超时、重试、熔断器等)提供流量管理功能。它将控制流量行为的高级路由规则转换为特定于 Envoy 的配置,并在运行时将它们传播到 sidecar。
Pilot 将平台特定的服务发现机制抽象化并将其合成为符合 Envoy 数据平面 API 的任何 sidecar 都可以使用的标准格式。这种松散耦合使得 Istio 能够在多种环境下运行(例如,Kubernetes、Consul、Nomad),同时保持用于流量管理的相同操作界面。
Citadel
Citadel 通过内置身份和凭证管理可以提供强大的服务间和最终用户身份验证。可用于升级服务网格中未加密的流量,并为运维人员提供基于服务标识而不是网络控制的强制执行策略的能力。从 0.5 版本开始,Istio 支持基于角色的访问控制,以控制谁可以访问您的服务。
应用ServiceMesh效益评估
当开发的业务系统多时,将获得客观的收益。假设一个有近千个微服务的企业,则可以:
减少上千开发人员各种微服务SDK的学习消耗时间
减少近千微服务整合微服务SDK的时间
减少推动上千微服务SDK升级所需要的精力及时间
统一的服务间权限控制、实现更安全的服务隔离及弹性扩容
统一的流量控制、熔断策略、运行可直接调控
其中流量及权限控制的逻辑示意图如下:
所有流量入口只能通过istio定义的Gateway进入,在ServiceMesh的边界内服务之间通过PROXY通讯,并会做身份认证及权限校验,离开ServiceMesh边界的流量可以通过Egress,或者从Proxy直接到外部,但其都需要显式配置。这整个模型很好地兼顾了安全以及扩容时的灵活性。
ServiceMesh的缺点
通过网络代理必然会增加计算、延时等消耗
调试困难
负载均衡等操作由于被代理,因此直接在IDE等本地开发环境跑起来的服务是无法正常运行
需要结合相关专有工具,将IDE调试环境与K8S及Istio环境联通才能实施调试
使用了ServiceMesh依然存在一些微服务特有的组件只能用SDK整合,如
配置中心SDK
Swagger等接口文档配置SDK
分布式追踪仍需要微服务在代层次配合(发出的请求带上原始的TraceId等)
引入ServiceMesh的考量
ServiceMesh的一些框架依然处于初级阶段,目前最流行的Istio刚刚发布1.0.0生产可用版本,使用的案例少。
Istio的组件多种语言构成,包括C++及GO,如果我们要在早期使用Istio必须有具备这些语言开发能力的高手能排坑,或者引入实力厂商做背书,否则建议再等等才可应用到生产
或者使用蚂蚁金服改写的Istio,其用GO重写了用C++编写的Envoy,因GO是目前主流云服务的编程语言(K8S,Docker等),可以适当储备培养相关人员。
对于Istio来说,目前仍缺乏进行配置的UI,需要适用yaml来手工配置
参考
https://jimmysong.io/kubernetes-handbook/usecases/service-mesh.html
https://www.nginx.com/resources/library/the-enterprise-path-to-service-mesh-architectures/
https://www.nginx.com/blog/what-is-a-service-mesh/
https://istio.io/zh/docs/concepts/what-is-istio/