目录
一、概述
二、 设计
三、服务网格
四、总结
一、概述
容器化技术与容器编排推动了微服务架构应用的演进,于是应用的扩展与微服务的数量日益增加,新的问题随之而来,监控服务的性能变得越来越困难,微服务与微服务之间相互通信变得越来越复杂,请求链路越来越长,排查问题变得越来越繁琐……
云原生应用下使用服务网格作为解决上述问题的方案之一。
服务网格不仅描述了这个应用的网络,而且还描述了分布式应用程序组件之间的交互,所有在该应用之间传递的数据都会由服务网格来接管。这意味着它能管控流量,控制路由……如果仅仅只是这些倒是与传统的网关基础设施没什么区别。但微服务体系结构通常还有更复杂的操作需求,比如A/B测试,Canary部署,速率限制,访问控制,加密和端到端身份验证等。
服务网络可以通过可观测性,网络和安全策略来分隔应用程序的业务逻辑。通过服务网格可以链接微服务,让微服务更安全,可以更好地监控微服务。
二、 设计
假设我们现在已存在一个微服务架构的系统,但是我们用传统的网关代理方式来作为服务之间的通信代理(如下图所示)。
可以看到Nginx代理了该系统中的所有服务,无论是服务1还是Minio,DB等都在Nginx的代理下。在这种网络代理下如果Server1请求Server2还是访问DB服务都要将流量先打到Nginx,然后再由路由进行分发,代理到具体的某个服务下。
在上述这种代理模式下,服务的Path管理会变得很繁琐,每引入或者扩容一个新服务就需要更改一次Nginx的配置,服务可能因为某种原因而崩溃,但是Nginx只能做到基础的健康检查,如果想做负载均衡还得再调整配置……
服务发现也许能通过引入Consul来解决,但是路由的代理最终还是需要在网关层面做配置,健康检查也不能解决服务因为崩溃后断连的问题,手动运维这些会相当繁琐。这时候可能会想:不如直接上Kubernetes,容器化技术解决自启动的问题,Kubernetes中自带服务发现/注册,只需要使用Nginx代理一下Server就好。
于是设计可能会演变成:
上述示意图中为了代理各个服务,由ingress接管原本Nginx路由分发,然后将流量转发给Service,由Service来做负载均衡。而Minio则代表着⼀些边缘服务。
Minio API 在代码访问中不能添加Path路径,它的安全策略不允许,所以 www.demo.com/minio 这类的地址是无法访问的。使用Ingress时代理Minio需要额外申请一个域名。
当请求从客户端发起时,由Nginx转发到Kubernetes Nginx-Ingress服务端口,再由Ingress进行流量分割发送到不同的Service。这一网络链路看似没什么问题,但是在做单体应用向微服务应用拆分时,往往也容易背负巨大的技术债务。
例如:Minio/DB从单体部署演变成集群,势必涉及到部署的方式改变,数据的迁移,数据备份,容灾等......某些暂时无法进行拆分的基础设施成为了云原生环境下的边缘服务,示意图中的Minio也代表着这一类的服务(它们不好拆分或成本略高)。
于是我们依旧保留着Nginx作为唯一网关的入口,并代理一部分的边缘服务,业务服务的网络代理由Kubernetes接管,服务与服务之间的通信使用集群网络。
上述的方案可能对于一定规模的应用下够用了,但是随着业务要求,引入一些新技术,比如为了服务的稳定性,要求上线前做金丝雀发布(Kubernetes固然可以通过更改Pod的数量来按照比例伸缩达到目的);收集整个系统的日志信息(还记得我们有一部分部署在集群之外的边缘服务吗?);跨集群进行访问,亦或跨不同云厂商的集群访问;
这些新技术的引入会让原本就复杂的网络链路变得更加复杂,当你想对系统进行测压时,一个配置(可能是Nginx的配置,也可能是Ingress的配置)错误都会让你难以定位,可能你会找错瓶颈,混淆你的判断从而走向错误的方向。
三、服务网格
Kubernetes最精细的颗粒度也只能达到容器层次,如果再想进一步只能依靠工程师来管理,容器编排系统很难提供更有效的支持。但是服务网格的出现就是为了弥补这一缺憾。
服务网格只是处理程序间通信的基础设施,但它不是一个独立的存在,它以"边车"的形式直接部署在应用旁边,一对一为应用提供服务代理。
"边车",⼀种常见的容器设计模式,用来形容外挂在容器身上的辅助程序。
服务网格在容器的支持下,不需要侵入业务代码就能强制性地对应用通信进行管理,原理类似中间人流量劫持,透明地接管容器。
下图出自《凤凰架构》
服务网格包括两大块内容:和微服务共同部署的边车代理;用于控制这些代理的管理者;服务网格使用数据平面通信和控制平面通信来形容这两类流量。
我们使用服务网格其实希望更好梳理网络的访问链路,期望在基础设施服务就能解决网络的一部分问题,比如中断重试,不同云厂商之间平稳迁移,统一纳入网络平面,不依赖程序就能控制访问等……
数据平面也被称为转发平面,为了在不可靠的物理网络中保证程序间通信的最大可靠性,它可以在无感情况下自动完成服务路由,健康检查,负载均衡,认证鉴权,产生监控数据等……
四、总结
我们从单体应用向微服务的演变讲述了网络代理在各个阶段的变化。服务网格可能是未来的一个趋势,时至今日服务网格的代表Istio已经从CNCF中毕业了,但服务网格并非是"银弹",它不支持与其他系统或服务集成,也不解决转换映射或路由类型之类的问题……使用服务网格也需要云原生环境,一些边缘,独立部署的服务也无法纳入系统中享受新技术带来的便利;引入一套全新的网络服务也会增加应用的成本,使用不当反而会增加项目风险,留下成本巨大的技术债务。
在实际项目中我们需要考虑不同应用架构,规模使用最合适的网络服务代理。如果仅仅只是一个单体应用,那么Nginx或许是最好的选择;如果是正在演进的分布式系统,又在不断迭代,那么Nginx ingress 在这一阶段也许就能满足需求;如果微服务应用已经达到一定规模,开发工程师或运维工程师已经无法了解整个系统的全貌,那使用服务网格倒也无可厚非。
版权声明:本文由神州数码云基地团队整理撰写,若转载请注明出处。
公众号搜索神州数码云基地,了解更多技术干货!