随着容器技术的流行,越来越多的微服务技术被使用在云中部署应用和服务,运行在网易云上的各种互联网业务,也越来越多地采用微服务架构建立,这催生出更多细小服务单元,以及更好的服务发现能力的需求。
作为网易云基础服务采用的容器集群管理平台(也是业界最流行的容器编排工具),Kubernetes为了满足各个服务之间或者服务内部的资源访问,提供了两套服务发现的机制:
Kubernetes提供的两套服务发现机制各有优缺点:
目前在Kubernetes上的服务发现应用比较广的还是DNS,因而Kubernetes 1.3正式版把kube-dns作为一个内置的组件合进来,在部署方式上也更方便。所以接下来我们将集中讨论Kubernetes中的DNS服务发现方案的设计。
Kubernetes 1.3之前实现整个DNS服务发现总共涉及到三个组件:kube2sky,skyDNS,etcd。结构图如下:
Kubernetes1.3实现整个DNS服务发现只用到了一个组件:Kube-dns。其结构图如下:
形如etcd,kube2sky,SkyDNS这三个组件实现的功能都包含在了kube-dns上。etcd的功能由Tree-Cache代替,而Tree-cache只不过是kube-dns申请的内存结构。而SkyDNS服务也作为Kubernetes的一种库来供kube-dns来调用,而不需要作为一个组件来单独创建维护。Kube2sky实现的监测和向etcd推送service信息也已完全包含在kube-dns中。由三个完全单独的组件合并到一个组件来实现,维护起来将更方便。
下面将介绍一条正常的DNS记录产生到被DNS请求的过程。
对应图中①。通过yaml文件创建一个名为my-nginx-service的service:
apiVersion: v1
kind: Service
metadata:
name: my-nginx-service
spec:
ports:
– port: 80
name: http
protocol: TCP
selector:
name: service-nginx
执行kubectl create –f my-nginx-service.yaml即可向APIServer请求创建出一个service。APIServer获取到这个请求后调用相应的api创建出一个service对象,并写入etcd保存。
对应图中的②。Kube-dns通过List/Watch操作向APIServer发送Get请求。这时因为有service的创建,所以APIServer会响应这个请求并把service信息回复给kube-dns。
对应图中的③。APIServer将创建的my-nginx-service信息回复给kube-dns,这时还会附带一个APIServer分配给service的portal IP(这个IP是从配置中的clusterIP范围中给出的)。
对应图中的④。Kube-dns通过监测并得到APIServer回复的service信息,会生成类似这样的DNS条目:{my-nginx-service.default.svc.cluster.local,x.x.x.x,port}。并把这个DNS条目存储在Tree-Cache中。
对应图中的⑤。Kunernetes集群中需要访问该my-nginx-service的服务只需要通过http://my-niginx-service或者添加该service对应的端口即可访问。当提交该访问请求的时候会首先向kube-dns中的skyDNS server请求该域名对应的IP地址。而skyDNS server的IP:Port则是通过在kubelet启动的时候配置的,随后kubelet会在每个pod容器创建的时候把相应的skyDNS server和cluster domain注入到容器系统的/etc/resolv.conf文件中。
对应图中的⑥。skyDNS server接收到了DNS请求,根据相应的DNS-lib库对请求进行解析。然后根据解析出的域名向Tree-Cache中进行查找。因为my-nginx-service已经存入Tree-Cache,所以这里会返回my-nginx-service对应的IP地址。
对应图中的⑦。skyDNS server根据查找的my-nginx-service对应的DNS记录,返回相应的IP地址给请求方。这时即可完成后面的http://my-nginx-service的实际服务请求。
kube-dns核心原理一直没变,只是现在在Kubernetes 1.6版本中被单独弄成Addon了,即把代码抽离出来弄成另外一个项目。
将kube-dns独立出来,主要基于如下三个方面的考虑:
作者丨毛迎春,赖冬林 网易云工程师
网易云原创投稿,未经许可,谢绝转载!