开发者社区> 中间件小哥> 正文

dubbo-go K8s 注册中心的设计方案与实现

简介:
+关注继续查看

Dubbo-go k8s注册中心设计方案与实现

随着云原生的推广,越来越多的公司或组织将服务容器化,并将容器化后的服务部署在k8s集群中。

今天这篇文章将会介绍dubbo-go将k8s作为服务注册中心的方案设计,以及具体实现。到目前为止该方案的实现已经被合并到dubbo-go的master分支。具体实现为关于Kubernetes的PullRequest

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 。如果集群内的Pod需要访问该服务时直接通过https://kubernetes:443即可完成。

lADPD2eDMWswXhPNBEXNBEs_1099_1093_jpg_720x720q90g

具体流程如上图所示(红色为客户端,绿色为kube-apiserver):

  1. 首先客户端通过CoreDNS解析域名为kubernetes的服务获得对应的ClusterIP为10.96.0.1。
  2. 客户端向10.96.0.1发起HTTPS请求。
  3. HTTPS之下的TCP连接被kube-proxy创建的iptables的PREROUTING链拦截并DNAT 为 10.0.2.16或10.0.2.15。
  4. Client与最终提供服务的Pod建立连接并交互。

由此可见,k8s提供的服务发现为域名解析级别。

Dubbo服务发现模型

同样为了明确Dubbo服务发现的模型,以一个简单的Dubbo-Consumer发现并访问Provider的具体流程为例。

lALPD4Bhp_yd3sTNAarNA_A_992_426_png_720x720q90g

具体流程如上图所示:

  1. Provider将本进程的元数据注册到Registry中,包括IP,Port,以及服务名称等。
  2. Consumer通过Registry获取Provider的接入信息,直接发起请求

由此可见,Dubbo当前的服务发现模型是针对Endpoint级别的,并且注册的信息不只IP和端口还包括其他的一些元数据。

K8s service vs dubbo-go 服务

通过上述两个小节,答案基本已经比较清晰了。总结一下,无法直接使用k8s的服务发现模型的原因主要为以下几点:

  1. k8s的Service标准的资源对象具有的服务描述字段 中并未提供完整的Dubbo进程元数据字段因此,无法直接使用该标准对象进行服务注册与发现。
  2. dubbo-do的服务注册是基于每个进程的,每个Dubbo进程均需进行独立的注册。
  3. k8s的Service默认为服务创建VIP,提供round-robin的负载策略也与Dubbo-go自有的Cluster模块的负载策略形成了冲突。

Dubbo-go 当前的方案

服务注册

K8s基于Service对象实现服务注册/发现。可是dubbo现有方案为每个dubbo-go进程独立注册,因此dubbo-go选择将该进程具有的独有的元数据写入运行该dubbo-go进程的Pod在k8s中的Pod资源对象的描述信息中。每个运行dubbo进程的Pod将本进程的元数据写入Pod的Annotations字段。为了避免与其他使用Annotations字段的Operator或者其他类型的控制器(istio)的字段冲突。dubbo-go使用Key为 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为 dubbo.io/label Value为 dubbo.io-value 的Pod。在WATCH到对应Pod的变化后实时更新本地Cache,并通过Registry提供的Subscribe接口通知建立在注册中心之上的服务集群管理其他模块。

总体设计图

lALPD4d8pTZEENfNA1PNBQA_1280_851_png_720x720q90g

具体流程如上图所示:

  1. 启动dubbo-go的Deployment或其他类型控制器使用k8s Downward-Api将本Pod所在namespace通过环境变量的形式注入dubbo-go进程。
  2. Consumer/Provider进程所在的Pod启动后通过环境变量获得当前的namespace以及该Pod名称, 调用kube-apiserver PATCH 功能为本Pod添加Key为dubbo.io/label Value为 dubbo.io-value 的label。
  3. Consumer/Provider进程所在的Pod启动后调用kube-apiserver将本进程的元数据通过PATCH接口写入当前Pod的Annotations字段。
  4. Consumer进程通过kube-apiserver LIST 当前namespace下其他具有同样标签的Pod,并解码对应的Annotations字段获取Provider的信息。
  5. Consumer进程通过kube-apiserver WATCH 当前namespace下其他具有同样label的Pod的Annotations的字段变化,动态更新本地Cache。

总结

k8s已经为其承载的服务提供了一套服务发现,服务注册,以及服务集群管理机制。而dubbo-go的同时也拥有自成体系的服务集群管理。这两个功能点形成了冲突,在无法调谐两者的情况,dubbo-go团队决定保持dubbo自有的服务集群管理系,而选择性的放弃了Service功能,将元数据直接写入到Pod对象的Annotations中。

当然这只是dubbo-go在将k8s作为服务注册中心的方案之一,后续社区会以更加“云原生”的形式对接k8s,让我们拭目以待吧。

dubbo-go 社区钉钉群 :23331795 ,欢迎你的加入。

作者信息:王翔,GithubID: sxllwx,就职于成都达闼科技有限公司,golang开发工程师。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Kubeadm 升级 k8s 至 v1.17.4及运行 nginx+tomcat 并实现动静分离 | 学习笔记
快速学习 Kubeadm 升级 k8s 至 v1.17.4及运行 nginx+tomcat 并实现动静分离
148 0
《EDAS4.0 助力企业一站实现微服务架构转型与 K8s 容器化升级》电子版地址
EDAS4.0 助力企业一站实现微服务架构转型与 K8s 容器化升级.ppt
53 0
K8S自定义webhook实现认证管理
K8S自定义webhook实现认证管理
213 0
【k8s系列3】kubernetes(k8s) scheduler backend 调度的实现
【k8s系列3】kubernetes(k8s) scheduler backend 调度的实现
126 0
SpringCloud微服务实战——搭建企业级开发框架(三十五):SpringCloud + Docker + k8s实现微服务集群打包部署-集群环境部署【下】
• sonarqube默认用户名密码: admin/admin • 卸载命令:docker-compose -f jenkins-compose.yml down -v 六、Jenkins自动打包部署配置   项目部署有多种方式,从最原始的可运行jar包直接部署到JDK环境下运行,到将可运行的jar包放到docker容器中运行,再到现在比较流行的把可运行的jar包和docker放到k8s的pod环境中运行。每一种新的部署方式都是对原有部署方式的改进和优化,这里不着重介绍每种方式的优缺点,只简单说明一下使用Kubernetes 的原因:Kubernetes 主要提供弹性伸缩、服务发现、自我修复,
231 0
SpringCloud微服务实战——搭建企业级开发框架(三十五):SpringCloud + Docker + k8s实现微服务集群打包部署-集群环境部署【上】
一、集群环境规划配置 生产环境不要使用一主多从,要使用多主多从。这里使用三台主机进行测试一台Master(172.16.20.111),两台Node(172.16.20.112和172.16.20.113) 1、设置主机名 CentOS7安装完成之后,设置固定ip,三台主机做相同设置 vi /etc/sysconfig/network-scripts/ifcfg-ens33 #在最下面ONBOOT改为yes,新增固定地址IPADDR,172.16.20.111,172.16.20.112,172.16.20.113 ONBOOT=yes IPADDR=172.16.20.111
359 0
SpringCloud微服务实战——搭建企业级开发框架(三十四):SpringCloud + Docker + k8s实现微服务集群打包部署-打包配置
SpringCloud微服务包含多个SpringBoot可运行的应用程序,在单应用程序下,版本发布时的打包部署还相对简单,当有多个应用程序的微服务发布部署时,原先的单应用程序部署方式就会显得复杂且不可控。那么我们就会思考使用简单的部署方式,解决自动化发布、自动化部署、微服务监控等问题。
379 0
6. k8s + jenkins 实现持续集成(完)
一. 在node节点上安装软件. 具体软件内容如下
278 0
编写一个k8s的webhook来实现deployment的拦截
admission webhook是k8s一个很强的对外扩展性的体验,基于admission webhook,我们可以自由都控制其他控制器对k8s的修改和对资源类型做限制校验,这里编写一个对deployment资源的修改器作为webhook的入门教学提供给大家学习。
898 0
k8s 上 go 微服务实战: go 实现 istio bookinfo 微服务
在完成 `k8s 上快速部署 go 服务` 和 `k8s: istio 入门` 后, 继续 **膨胀**, 使用 go 来实现 istio 提供的 bookinfo 微服务 demo
373 0
+关注
中间件小哥
阿里中间件(Aliware)官方账号
文章
问答
来源圈子
更多
阿里云中间件主要有包含这么几个: 分布式关系型数据库DRDS_水平拆分 做数据库扩展性的 、消息队列MQ 是做消息的中间件、企业级分布式应用服务EDAS 做分布式服务的、还有一些其他的中间件,比如配置服务、缓存等等。
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
EDAS4.0 助力企业一站实现微服务架构转型与 K8s 容器化升级
立即下载
如何让k8s集群30s扩容3000个Pod
立即下载
七牛AI训练业务的K8S实践
立即下载