随着云原生的推广,越来越多的公司或组织将服务容器化,并将容器化后的服务部署在k8s集群中。
今天这篇文章将会介绍dubbo-go将k8s作为服务注册中心的方案设计,以及具体实现。到目前为止该方案的实现已经被合并到dubbo-go的master分支。具体实现为关于Kubernetes的PullRequest。
k8s作为容器集群化管理方案可以将管理资源的维度可主观的分为服务实例管理和服务接入管理。
为了明确k8s在服务接入管理提供的解决方案,我们以kube-apiserver 提供的API(HTTPS)服务为例。k8s集群为该服务分配了一个集群内有效的ClusterIP,并通过CoreDNS为其分配了唯一的域名 kubernetes 。如果集群内的Pod需要访问该服务时直接通过https://kubernetes:443即可完成。
具体流程如上图所示(红色为客户端,绿色为kube-apiserver):
由此可见,k8s提供的服务发现为域名解析级别。
同样为了明确Dubbo服务发现的模型,以一个简单的Dubbo-Consumer发现并访问Provider的具体流程为例。
具体流程如上图所示:
由此可见,Dubbo当前的服务发现模型是针对Endpoint级别的,并且注册的信息不只IP和端口还包括其他的一些元数据。
通过上述两个小节,答案基本已经比较清晰了。总结一下,无法直接使用k8s的服务发现模型的原因主要为以下几点:
K8s基于Service对象实现服务注册/发现。可是dubbo现有方案为每个dubbo-go进程独立注册,因此dubbo-go选择将该进程具有的独有的元数据写入运行该dubbo-go进程的Pod在k8s中的Pod资源对象的描述信息中。每个运行dubbo进程的Pod将本进程的元数据写入Pod的Annotations字段。为了避免与其他使用Annotations字段的Operator或者其他类型的控制器(istio)的字段冲突。dubbo-go使用Key为 http://dubbo.io/annotation value为具体存储的K/V对的数组的json编码后的base64编码。
样例为:
apiVersion: v1 kind: Pod metadata: annotations: dubbo.io/annotation: W3siayI6Ii9kdWJibyIsInYiOiIifSx7ImsiOiIvZHViYm8vY29tLmlrdXJlbnRvLnVzZXIuVXNlclByb3ZpZGVyIiwidiI6IiJ9LHsiayI6Ii9kdWJiby9jb20uaWt1cmVudG8udXNlci5Vc2VyUHJvdmlkZXIvY29uc3VtZXJzIiwidiI6IiJ9LHsiayI6Ii9kdWJibyIsInYiOiIifSx7ImsiOiIvZHViYm8vY29tLmlrdXJlbnRvLnVzZXIuVXNlclByb3ZpZGVyIiwidiI6IiJ9LHsiayI6Ii9kdWJiby9jb20uaWt1cmVudG8udXNlci5Vc2VyUHJvdmlkZXIvcHJvdmlkZXJzIiwidiI6IiJ9LHsiayI6Ii9kdWJiby9jb20uaWt1cmVudG8udXNlci5Vc2VyUHJvdmlkZXIvY29uc3VtZXJzL2NvbnN1bWVyJTNBJTJGJTJGMTcyLjE3LjAuOCUyRlVzZXJQcm92aWRlciUzRmNhdGVnb3J5JTNEY29uc3VtZXJzJTI2ZHViYm8lM0RkdWJib2dvLWNvbnN1bWVyLTIuNi4wJTI2cHJvdG9jb2wlM0RkdWJibyIsInYiOiIifV0=
由于每个dubbo-go的Pod均只负责注册本进程的元数据,因此Annotations字段长度也不会因为运行dubbo-go进程的Pod数量增加而增加。
依赖kube-apiserver 提供了WATCH的功能。可以观察特定namespace内各Pod对象的变化。dubbo-go为了避免dubbo-go进程WATCH到与dubbo-go进程无关的Pod的变化,dubbo-go将WATCH的条件限制在当前Pod所在的namespace,以及仅WATCH具有Key为 http://dubbo.io/label Value为 dubbo.io-value 的Pod。在WATCH到对应Pod的变化后实时更新本地Cache,并通过Registry提供的Subscribe接口通知建立在注册中心之上的服务集群管理其他模块。
具体流程如上图所示:
本文系作者在时代Java发表,未经许可,不得转载。
如有侵权,请联系nowjava@qq.com删除。