Dubbo-go k8s注册中心设计方案与实现
Dubbo-go k8s注册中心设计方案与实现
随着云原生的推广,越来越多的公司或组织将服务容器化,并将容器化后的服务部署在k8s集群中。
k8s管理资源的哲学
k8s管理资源的哲学
k8s作为容器集群化管理方案可以将管理资源的维度可主观的分为服务实例管理和服务接入管理。
服务实例管理,主要体现方式为Pod设计模式加控制器模式。控制器保证具有特定标签(Label)的Pod保持在恒定的数量(多删,少补)。
服务接入管理,主要为Service,该Service默认为具有特定标签(Label)的一批Pod提供一个VIP(ClusterIP)作为服务的接入点,默认会按照round-robin的负载均衡策略将请求转发到真正提供服务的Pod。并且CoreDNS为该Service提供集群内唯一的域名。
k8s服务发现模型
为了明确k8s在服务接入管理提供的解决方案,我们以kube-apiserver 提供的API(HTTPS)服务为例。k8s集群为该服务分配了一个集群内有效的ClusterIP,并通过CoreDNS为其分配了唯一的域名 kubernetes 。

-
首先客户端通过CoreDNS解析域名为kubernetes的服务获得对应的ClusterIP为10.96.0.1。 -
客户端向10.96.0.1发起HTTPS请求。 -
HTTPS之下的TCP连接被kube-proxy创建的iptables的PREROUTING链拦截并DNAT 为 10.0.2.16或10.0.2.15。 -
Client与最终提供服务的Pod建立连接并交互。
Dubbo服务发现模型
Dubbo服务发现模型
-
Provider将本进程的元数据注册到Registry中,包括IP,Port,以及服务名称等。 -
Consumer通过Registry获取Provider的接入信息,直接发起请求
K8s service vs dubbo-go 服务
K8s service vs dubbo-go 服务
-
k8s的Service标准的资源对象具有的服务描述字段 中并未提供完整的Dubbo进程元数据字段因此,无法直接使用该标准对象进行服务注册与发现。 -
dubbo-do的服务注册是基于每个进程的,每个Dubbo进程均需进行独立的注册。 -
k8s的Service默认为服务创建VIP,提供round-robin的负载策略也与Dubbo-go自有的Cluster模块的负载策略形成了冲突。
Dubbo-go 当前的方案
Dubbo-go 当前的方案
服务注册
apiVersion: v1
kind: Pod
metadata:
annotations:
dubbo.io/annotation: W3siayI6Ii9kdWJibyIsInYiOiIifSx7ImsiOiIvZHViYm8vY29tLmlrdXJlbnRvLnVzZXIuVXNlclByb3ZpZGVyIiwidiI6IiJ9LHsiayI6Ii9kdWJiby9jb20uaWt1cmVudG8udXNlci5Vc2VyUHJvdmlkZXIvY29uc3VtZXJzIiwidiI6IiJ9LHsiayI6Ii9kdWJibyIsInYiOiIifSx7ImsiOiIvZHViYm8vY29tLmlrdXJlbnRvLnVzZXIuVXNlclByb3ZpZGVyIiwidiI6IiJ9LHsiayI6Ii9kdWJiby9jb20uaWt1cmVudG8udXNlci5Vc2VyUHJvdmlkZXIvcHJvdmlkZXJzIiwidiI6IiJ9LHsiayI6Ii9kdWJiby9jb20uaWt1cmVudG8udXNlci5Vc2VyUHJvdmlkZXIvY29uc3VtZXJzL2NvbnN1bWVyJTNBJTJGJTJGMTcyLjE3LjAuOCUyRlVzZXJQcm92aWRlciUzRmNhdGVnb3J5JTNEY29uc3VtZXJzJTI2ZHViYm8lM0RkdWJib2dvLWNvbnN1bWVyLTIuNi4wJTI2cHJvdG9jb2wlM0RkdWJibyIsInYiOiIifV0=
服务发现
总体设计图
-
启动dubbo-go的Deployment或其他类型控制器使用k8s Downward-Api将本Pod所在namespace通过环境变量的形式注入dubbo-go进程。 -
Consumer/Provider进程所在的Pod启动后通过环境变量获得当前的namespace以及该Pod名称, 调用kube-apiserver PATCH 功能为本Pod添加Key为dubbo.io/label Value为 dubbo.io-value 的label。 -
Consumer/Provider进程所在的Pod启动后调用kube-apiserver将本进程的元数据通过PATCH接口写入当前Pod的Annotations字段。 -
Consumer进程通过kube-apiserver LIST 当前namespace下其他具有同样标签的Pod,并解码对应的Annotations字段获取Provider的信息。 -
Consumer进程通过kube-apiserver WATCH 当前namespace下其他具有同样label的Pod的Annotations的字段变化,动态更新本地Cache。
总结
总结

