K8sDubbo

DubboKubernetes

Kubernetes已经阐述过,下面的内容也是假设一个应用部署在一个容器里,一个容器部署在一个Pod里。接下来方案的讨论,互相之间其实是有关联的,如服务治理可能会影响到服务注册发现,服务查询也不能依赖于服务注册的内容。整个设计的过程是不断优化的过程。下面所说的内容,以Dubbo来举例说明。

服务治理

Dubbo原有体系里的服务治理是强依赖于IP,当配置了一套服务治理规则的时候,最后都是基于一个或多个IP地址。到Kubernetes体系下之后,要考虑的是PodIP不是固定的。所以当前的路由规则不能满足条件,而且会产生很多规则垃圾数据。Kubernetes体系下,通过Service查找Pod,是基于label selector;通过deployment管理Pod,其实也是基于Pod label selector。所以Pod label selector是在Kubernetes习题中比较通用的解决方案。

以路由规则为例,需要支持一种新的路由规则:label路由。通过一定条件匹配之后,将结果定位到以label selector查询到的Pod列表里,而非原来的IP列表。应用获取当前Pod的信息方式:

  • Pod定义环境变量,应用获取,Dubbo提供对环境变量读取的支持,Pod中需要按照Dubbo定义的环境变量设置具体的Pod信息。

  • 通过Downward Api传递Pod信息,Dubbo需要提供对Downward的目录读取,Pod中需要定制downward的对应配置。

  • 通过API Server获取数据,最强大的方式,但是应用需要强依赖于API Server

应用获取其他Pod的信息方式:

  • 通过调用其他Pod的服务获取,依赖于应用能获取自身的Pod信息,同时将自身的Pod信息暴露成服务(RestDubbo协议client端通过调用对用的Pod获取到对应Pod的完整信息。

  • 通过API server获取数据,很强大,但增加了对API Server的依赖。

服务注册和发现

Kubernetes体系下,RPC服务发现有几种方式:

  • 注册机制:将IP写入注册中心,用心跳保持连接;当心跳停止,从注册中心删除。

  • 利用Service + DNS:新建一个Service,可以通过标签选择到一组pod列表,这个Service对应一个不变的集群IPClient端通过DNS方式或者直接访问集群IP。这个集群IP,约等于实现了负载均衡(iptable方式

  • 利用Headless Service(DNSHeadless Service和上面的Service的区别是,它不提供集群IP,通过主机名的形式获取一组IP列表,Client端自己决定访问哪个Pod

  • API Server:Client端直接请求API Server,获取到Pod的列表,Client自己决定访问Pod的逻辑。同时获取的时候增加watchAPI Server会将Pod的变化信息同步Client

通过拿到Server端的IP或者hostClient端就可以发起http或者其他协议的请求。

Dubbo + ZooKeeper Pod Cluster(HSF+CS cluster)

这是最简单的方式,Dubbo本身不需要做任何改造。带来的问题是增加了ZooKeeper的维护,同时这个方案很不云原生,和Kubernetes的体系没有任何关系。

上面方案是将ZooKeeper作为注册中心,那么是否可以将KubernetesService作为注册中心呢?Dubbo里每个接口去建立一个Service,每个应用实例启动过程中去更新Endpoint信息,建立Service-> Endpoint-> IP列表的关系。这种方案中Kubernetes Service的定义被改造了,而且定义了过多的ServiceService的维护管理是个难题。

在传统的RPC领域,服务分成服务注册和服务发现。在Kubernetes领域Pod和应用是一对一的关系,Kubernetes本身就提供了Pod查找的能力,所以一定程度上服务注册其实可以不存在,而只需要服务发现。但是这个其实需要一个前提:

  • Dubbo需要将服务注册发现的粒度改造成应用维度。

  • 在运维层面,将app=xxx(应用名)写入到Podlabel中。

Dubbo + Kubernetes DNS

如果Kubernetes Service提供了Cluster IP,那么Dubbo只负责调用该集群IP,路由和负载均衡的逻辑则交给了KubernetesProxy来完成。此方案削减了Dubbo的核心能力。

通过请求<service>.<ns>.svc.<zone>. IN A的方式发起请求获取IP列表,但是需要轮询方式不断获取更新的IP列表。

Dubbo + API Server

Pod的容器中部署的Dubbo应用,服务注册流程可以直接删除,服务发现功能通过和API Server进行交互,获取PodService信息,同时watch podService的变更。通过这种方式之后,服务治理相关的信息也可以通过API Server直接获取。

Dubbo &amp; API Server

Dubbo + Istio + Envoy

Dubbo可以直接使用指定IP +端口的方式调用同一个PodEnvoy(也可能是同一个NodeEnvoyDubbo将路由规则,负载均衡,熔断等功能交给IstioEnvoyEnvoy需要支持Dubbo协议的转发。

所以Dubbo需要完成两个事情:本地IP直连(现有功能,多余功能裁剪(暂未实现

Dubbo + Istio

Dubbo应用不再依赖Envoy作为sidecar,而是直接和Istio进行交互,把Istio作为注册中心,作为服务治理的配置中心。Dubbo需要提供类似的xDS协议,在PilotServiceinstance转换成Dubbo的协议格式。Dubbo还需要去适配Istio的一些功能,如健康检查,安全相关的逻辑。具体实现可以参考Envoy的实现。

Dubbo + Istio

服务查询

Dubbo原有方式

Dubbo原有的服务查询是针对接口的查询,每个接口会有版本号和组别。接口名+版本号+组别确定唯一的服务集合,这个服务集下有对应的服务提供者和服务消费者(接口级依赖,服务提供者是一组IP + port列表,服务消费者也是一组IP + port列表。

只支持应用查询

Spring Cloud类似,支持应用维度的查询。查询到具体应用之后,应用详情下包含了IP + port列表,每个IP + port其实就是一个应用的实例。点击开每个应用实例,可以查看每个应用的详细信息,详细信息包含了该实例提供了哪些服务。

接口+应用查询均衡

在原来只支持应用查询的基础上,增加一步:支持查询某个接口对应的应用列表,而大部分接口只属于一个应用。再点击应用列表下具体的应用之后,会跳到应用详情。