此文已由作者刘超授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
在Kubernetes称为容器编排的标准之后,Service Mesh开始火了起来,但是很多文章讲概念的多,讲技术细节的少,所以专门写一篇文章,来解析Service Mesh背后的技术细节。
一、Service Mesh是Kubernetes支撑微服务能力拼图的最后一块
在上一篇文章为什么 kubernetes 天然适合微服务中我们提到,Kubernetes是一个奇葩所在,他的组件复杂,概念复杂,在没有实施微服务之前,你可能会觉得为什么Kubernetes要设计的这么复杂,但是一旦你要实施微服务,你会发现Kubernetes中的所有概念,都是有用的。
在我们微服务设计的是个要点中,我们会发现Kubernetes都能够有相应的组件和概念,提供相应的支持。
其中最后的一块拼图就是服务发现,与熔断限流降级。
众所周知,Kubernetes的服务发现是通过Service来实现的,服务之间的转发是通过kube-proxy下发iptables规则来实现的,这个只能实现最基本的服务发现和转发能力,不能满足高并发应用下的高级的服务特性,比较SpringCloud和Dubbo有一定的差距,于是Service Mesh诞生了,他期望讲熔断,限流,降级等特性,从应用层,下沉到基础设施层去实现,从而使得Kubernetes和容器全面接管微服务。
二、以Istio为例讲述Service Mesh中的技术关键点
就如SDN一样,Service Mesh将服务请求的转发分为控制面和数据面,因而分析他,也是从数据面先分析转发的能力,然后再分析控制面如何下发命令。今天这篇文章重点讲述两个组件Envoy和Pilot
一切从Envoy开始
我们首先来看,如果没有融入Service Mesh,Envoy本身能够做什么事情呢?
Envoy是一个高性能的C++写的proxy转发器,那Envoy如何转发请求呢?需要定一些规则,然后按照这些规则进行转发。
规则可以是静态的,放在配置文件中的,启动的时候加载,要想重新加载,一般需要重新启动,但是Envoy支持热加载和热重启,一定程度上缓解了这个问题。
当然最好的方式是规则设置为动态的,放在统一的地方维护,这个统一的地方在Envoy眼中看来称为Discovery Service,过一段时间去这里拿一下配置,就修改了转发策略。
无论是静态的,还是动态的,在配置里面往往会配置四个东西。
一是listener,也即envoy既然是proxy,专门做转发,就得监听一个端口,接入请求,然后才能够根据策略转发,这个监听的端口称为listener
二是endpoint,是目标的ip地址和端口,这个是proxy最终将请求转发到的地方。
三是cluster,一个cluster是具有完全相同行为的多个endpoint,也即如果有三个容器在运行,就会有三个IP和端口,但是部署的是完全相同的三个服务,他们组成一个Cluster,从cluster到endpoint的过程称为负载均衡,可以轮询等。
四是route,有时候多个cluster具有类似的功能,但是是不同的版本号,可以通过route规则,选择将请求路由到某一个版本号,也即某一个cluster。
这四个的静态配置的例子如下:
如图所示,listener被配置为监听本地127.0.0.1的10000接口,route配置为某个url的前缀转发到哪个cluster,cluster里面配置负载均衡策略,hosts里面是所有的endpoint。
如果你想简单的将envoy使用起来,不用什么service mesh,一个进程,加上这个配置文件,就可以了,就能够转发请求了。
对于动态配置,也应该配置发现中心,也即Discovery Service,对于上述四种配置,各对应相应的DS,所以有LDS, RDS, CDS, EDS。
动态配置的例子如下:
控制面Pilot的工作模式
数据面envoy可以通过加装静态配置文件的方式运行,而动态信息,需要从Discovery Service去拿。
Discovery Service就是部署在控制面的,在istio中,是Pilot。
如图为Pilot的架构,最下面一层是envoy的API,就是提供Discovery Service的API,这个API的规则由envoy定,但是不是Pilot调用Envoy,而是Envoy去主动调用Pilot的这个API。
Pilot最上面一层称为Platform Adapter,这一层是干什么的呢?这一层不是Kubernetes, Mesos调用Pilot,而是Pilot通过调用Kubernetes来发现服务之间的关系。
这是理解Istio比较绕的一个点。也即pilot使用Kubernetes的Service,仅仅使用它的服务发现功能,而不使用它的转发功能,pilot通过在kubernetes里面注册一个controller来监听事件,从而获取Service和Kubernetes的Endpoint以及Pod的关系,但是在转发层面,就不会再使用kube-proxy根据service下发的iptables规则进行转发了,而是将这些映射关系转换成为pilot自己的转发模型,下发到envoy进行转发,envoy不会使用kube-proxy的那些iptables规则。这样就把控制面和数据面彻底分离开来,服务之间的相互关系是管理面的事情,不要和真正的转发绑定在一起,而是绕到pilot后方。
Pilot另外一个对外的接口是Rules API,这是给管理员的接口,管理员通过这个接口设定一些规则,这些规则往往是应用于Routes, Clusters, Endpoints的,而都有哪些Clusters和Endpoints,是由Platform Adapter这面通过服务发现得到的。
自动发现的这些Clusters和Endpoints,外加管理员设置的规则,形成了Pilot的数据模型,其实就是他自己定义的一系列数据结构,然后通过envoy API暴露出去,等待envoy去拉取这些规则。
常见的一种人工规则是Routes,通过服务发现,Pilot可以从Kubernetes那里知道Service B有两个版本,一般是两个Deployment,属于同一个Service,管理员通过调用Pilot的Rules API,来设置两个版本之间的Route规则,一个占99%的流量,一个占1%的流量,这两方面信息形成Pilot的数据结构模型,然后通过Envoy API下发,Envoy就会根据这个规则设置转发策略了。
另一个常用的场景就是负载均衡,Pilot通过Kubernetes的Service发现Service B包含一个Deployment,但是有三个副本,于是通过Envoy API下发规则,使得Envoy在这三个副本之间进行负载均衡,而非通过Kubernetes本身Service的负载均衡机制。
容器服务是网易云提供的无服务器容器服务,让企业能够快速部署业务,轻松运维服务。容器服务支持弹性伸缩、垂直扩容、灰度升级、服务发现、服务编排、错误恢复及性能监测等功能。点击可免费试用。
更多网易技术、产品、运营经验分享请点击。