Kubernetes如何使用kube-dns实现服务发现

大纲:

?       Kubernetes中如何发现服务

?       如何发现Pod提供的服务

?       如何使用Service发现服务

?       如何使用kube-dns发现服务

?       kube-dns原理

?       组成

?       域名格式

?       配置

注:本次分享内容基于Kubernetes 1.2版本!

下面从一个简单的例子开始讲解。

1.Kubernetes中如何发现服务

◆   发现Pod提供的服务

首先使用nginx-deployment.yaml文件创建一个Nginx Deployment,文件内容如图所示:

首先创建两个运行Nginx服务的Pod:

使用kubectl create -f nginx-deployment.yaml指令创建,这样便可以得到两个运行nginx服务的Pod。待Pod运行之后查看一下它们的IP,并在k8s集群内通过podIP和containerPort来访问Nginx服务:

获取Pod IP:

在集群内访问Nginx服务:

看到这里相信很多人会有以下疑问:

1.  每次收到获取podIP太扯了,总不能每次都要手动改程序或者配置才能访问服务吧,要怎么提前知道podIP呢?

2.  Pod在运行中可能会重建,IP变了怎么解?

3.  如何在多个Pod中实现负载均衡嘞?

这些问题使用k8s Service就可以解决。

◆   使用Service发现服务

下面为两个Nginx Pod创建一个Service。使用nginx-service.yaml文件进行创建,文件内容如下:

创建之后,仍需要获取Service的Cluster-IP,再结合Port访问Nginx服务。

Service可以将pod  IP封装起来,即使Pod发生重建,依然可以通过Service来访问Pod提供的服务。此外,Service还解决了负载均衡的问题,大家可以多访问几次Service,然后通过kubectl logs <Pod Name>来查看两个Nginx Pod的访问日志来确认。

获取IP:

在集群内访问Service:

虽然Service解决了Pod的服务发现和负载均衡问题,但存在着类似的问题:不提前知道Service的IP,还是需要改程序或配置啊。看到这里有没有感觉身体被掏空?

接下来聊聊kube-dns是如何解决上面这个问题的。

◆   使用kube-dns发现服务

kube-dns可以解决Service的发现问题,k8s将Service的名称当做域名注册到kube-dns中,通过Service的名称就可以访问其提供的服务。

可能有人会问如果集群中没有部署kube-dns怎么办?没关系,实际上kube-dns插件只是运行在kube-system命名空间下的Pod,完全可以手动创建它。可以在k8s源码(v1.2)的cluster/addons/dns目录下找到两个模板(skydns-rc.yaml.in和skydns-svc.yaml.in)来创建,为大家准备的完整示例文件会在分享结束后提供获取方式,PPT中只截取了部分内容。

通过skydns-rc.yaml文件创建kube-dns Pod,其中包含了四个containers,这里开始简单过一下文件的主要部分,稍后做详细介绍。

第一部分可以看到kube-dns使用了RC来管理Pod,可以提供最基本的故障重启功能。

创建kube-dns Pod,其中包含了4个containers

接下来是第一个容器  etcd  ,它的用途是保存DNS规则。

第二个容器  kube2sky ,作用是写入DNS规则。

第三个容器是  skydns ,提供DNS解析服务。

最后一个容器是  healthz ,提供健康检查功能。

有了Pod之后,还需要创建一个Service以便集群中的其他Pod访问DNS查询服务。通过skydns-svc.yaml创建Service,内容如下:

创建完kube-dns Pod和Service,并且Pod运行后,便可以访问kube-dns服务。

下面创建一个Pod,并在该Pod中访问Nginx服务:

创建之后等待kube-dns处于运行状态

再新建一个Pod,通过其访问Nginx服务

在curl-util Pod中通过Service名称访问my-nginx Service:

只要知道需要的服务名称就可以访问,使用kube-dns发现服务就是那么简单。

虽然领略了使用kube-dns发现服务的便利性,但相信有很多人也是一头雾水:kube-dns到底怎么工作的?在集群中启用了kube-dns插件,怎么就能通过名称访问Service了呢?

2.kube-dns原理

◆   Kube-dns组成

之前已经了解到kube-dns是由四个容器组成的,它们扮演的角色可以通过下面这张图来理解。

其中:

●  SkyDNS是用于服务发现的开源框架,构建于etcd之上。作用是为k8s集群中的Pod提供DNS查询接口。项目托管于https://github.com/skynetservices/skydns

●  etcd是一种开源的分布式key-value存储,其功能与ZooKeeper类似。在kube-dns中的作用为存储SkyDNS需要的各种数据,写入方为kube2sky,读取方为SkyDNS。项目托管于https://github.com/coreos/etcd。

●   kube2sky是k8s实现的一个适配程序,它通过名为kubernetes的Service(通过kubectl get svc可以查看到该Service,由集群自动创建)调用k8s的list和watch API来监听k8s Service资源的变更,从而修改etcd中的SkyDNS记录。代码可以在k8s源码(v1.2)的cluster/addons/dns/kube2sky/目录中找到。

●   exec-healthz是k8s提供的一种辅助容器,多用于side car模式中。它的原理是定期执行指定的Linux指令,从而判断当前Pod中关键容器的健康状态。在kube-dns中的作用就是通过nslookup指令检查DNS查询服务的健康状态,k8s livenessProbe通过访问exec-healthz提供的Http API了解健康状态,并在出现故障时重启容器。其源码位于https://github.com/kubernetes/contrib/tree/master/exec-healthz。

●  从图中可以发现,Pod查询DNS是通过ServiceName.Namespace子域名来查询的,但在之前的示例中只用了Service名称,什么原理呢?其实当我们只使用Service名称时会默认Namespace为default,而上面示例中的my-nginx Service就是在default Namespace中,因此是可以正常运行的。关于这一点,后续再深入介绍。

●  skydns-rc.yaml中可以发现livenessProbe是设置在kube2sky容器中的,其意图应该是希望通过重启kube2sky来重新写入DNS规则。

◆   域名格式

接下来了解一下kube-dns支持的域名格式,具体为:<service_name>.<namespace>.svc.<cluster_domain>。

其中cluster_domain可以使用kubelet的--cluster-domain=SomeDomain参数进行设置,同时也要保证kube2sky容器的启动参数中--domain参数设置了相同的值。通常设置为cluster.local。那么之前示例中的my-nginx Service对应的完整域名就是my-nginx.default.svc.cluster.local。看到这里,相信很多人会有疑问,既然完整域名是这样的,那为什么在Pod中只通过Service名称和Namespace就能访问Service呢?下面来解释其中原因。

3.配置

◆   域名解析配置

为了在Pod中调用其他Service,kubelet会自动在容器中创建域名解析配置(/etc/resolv.conf),内容为:

感兴趣的可以在网上查找一些resolv.conf的资料来了解具体的含义。之所以能够通过Service名称和Namespace就能访问Service,就是因为search配置的规则。在解析域名时会自动拼接成完整域名去查询DNS。

刚才提到的kubelet --cluster-domain参数与search的具体配置是相对应的。而kube2sky容器的--domain参数影响的是写入到etcd中的域名,kube2sky会获取Service的名称和Namespace,并使用--domain参数拼接完整域名。这也就是让两个参数保持一致的原因。

◆   NS相关配置

kube-dns可以让Pod发现其他Service,那Pod又是如何自动发现kube-dns的呢?在上一节中的/etc/resolv.conf中可以看到nameserver,这个配置就会告诉Pod去哪访问域名解析服务器。

相应的,可以在之前提到的skydns-svc.yaml中看到spec.clusterIP配置了相同的值。通常来说创建一个Service并不需要指定clusterIP,k8s会自动为其分配,但kube-dns比较特殊,需要指定clusterIP使其与/etc/resolv.conf中的nameserver保持一致。

修改nameserver配置同样需要修改两个地方,一个是kubelet的--cluster-dns参数,另一个就是kube-dns Service的clusterIP。

4.总结

接下来重新梳理一下本文的主要内容:

●    在k8s集群中,服务是运行在Pod中的,Pod的发现和副本间负载均衡是我们面临的问题。

●    通过Service可以解决这两个问题,但访问Service也需要对应的IP,因此又引入了Service发现的问题。

●    得益于kube-dns插件,我们可以通过域名来访问集群内的Service,解决了Service发现的问题。

●    为了让Pod中的容器可以使用kube-dns来解析域名,k8s会修改容器的/etc/resolv.conf配置。

有了以上机制的保证,就可以在Pod中通过Service名称和namespace非常方便地访问对应的服务了。

5.Q&A

1. 问: 请问如果公司已有的应用接入的话,那么现有的没有接入的应用就无法访问了,因为这个服务发现是k8s集群内部的,外部无法访问。主要是k8s集群内的服务和集群外的己有的生产的域名访问如何实现,能在kube-dns整合吗?

答:两个问题可以抽象为k8s集群内与集群外服务连通性问题,我们从两个方面讲:

一、集群内访问集群外

这个问题比较简单,集群内的Pod会继承Node上的DNS解析规则。因此只要Node可以访问的服务,Pod中也可以访问到。

另外,在1.4版本中,k8s支持了一种ExternalName类型的Service,可以与一个公网域名绑定,通过该Service可以访问对应公网服务。

二、集群外访问集群内

1. 可以将Service设置为NodePort类型,这样通过任意Node的IP和Service Port便可以访问Service。适合对外的Service比较少的场景。

2. 通过kube-proxy可以对外暴露集群内的服务。

3. 根据实际情况在集群内自定义实现反向代理。

2. 问:我想问下etcd这个容器可以省掉吗?k8s集群有etcd不可以共用吗?

答:理论上可以共用etcd。从隔离性的角度考虑来说还是分开好,这样kube-dns服务不会对整个k8s集群的稳定性产生影响。另外如果把kube-dns看做一个微服务的话,那么应该保证内部组件不依赖外部,可以独立运行。

时间: 2024-10-22 09:57:51

Kubernetes如何使用kube-dns实现服务发现的相关文章

K8s基于DNS的服务发现(转)

原文地址:https://www.oschina.net/question/2657833_2201246 1.Kubernetes中如何发现服务 ◆   发现Pod提供的服务 首先使用nginx-deployment.yaml文件创建一个Nginx Deployment,文件内容如图所示: 首先创建两个运行Nginx服务的Pod: 使用kubectl create -f nginx-deployment.yaml指令创建,这样便可以得到两个运行nginx服务的Pod.待Pod运行之后查看一下它

kubernetes云平台管理实战: 服务发现和负载均衡(五)

一.rc控制器常用命令 1.rc控制器信息查看 [root@k8s-master ~]# kubectl get replicationcontroller NAME DESIRED CURRENT READY AGE myweb 3 3 3 3m [root@k8s-master ~]# kubectl get rc NAME DESIRED CURRENT READY AGE myweb 3 3 3 5m 2.删除rc [root@k8s-master ~]# kubectl delete

Kubernetes+Federation打造跨多云管理服务

Kubernetes日渐普及,在公有云.私有云等多个环境中部署kubernetes集群已是常规做法,而随着环境的复杂多样和集群数量增长,如何高效地管理这些集群成为新的问题.于是跨多云管理服务应运而生. 华为云高级工程师Fisher在Cloud Native Days China 2019杭州站发表了名为<Kubernetes+Federation打造跨多云管理服务>的议题,介绍了基于Federation的多云管理现状及未来计划.本文整理自Fisher现场分享实录. 大家好,我是华为云的Fish

转: 六个问题带你了解服务发现

转自: http://dockone.io/article/509 六个问题带你了解服务发现 [编者的话]四位专家解答了有关服务发现的六个问题:(1)什么是服务发现?(2)服务发现包括哪些关键特性,为什么?(3)服务发现带来的主要好处是什么?(4)哪一种服务发现方案是最可靠的?(5)实施服务发现面临的最大挑战是什么?(6)已有的系统如何集成服务发现的功能? 「不可更改基础设施:六问六专家」很成功,这次我们套用这种形式,向四位专家提问有关服务发现的六个问题. 服务发现不是什么新问题(想想 DNS

Kubernetes之服务发现及负载Services

Service 概述 kubernetes 中的pod是有生生灭灭的,时刻都有可能被新的pod所代替,而不可复活(pod的生命周期).一旦一个pod生命终止,通过ReplicaSets动态创建和销毁pod(Pod的动态扩缩容,滚动升级 等). 每个pod都有自己的IP,这IP随着pod的生生灭灭而变化,不能被依赖.这样导致一个问题,如果这个POD作为后端(backend)提供一些功能供给一些前端POD(frontend),在kubernete集群中是如何实现让这些前台能够持续的追踪到这些后台的?

Docker Kubernetes 服务发现原理详解

Docker Kubernetes  服务发现原理详解 服务发现支持Service环境变量和DNS两种模式: 一.环境变量 (默认) 当一个Pod运行到Node,kubelet会为每个容器添加一组环境变量,Pod容器中程序就可以使用这些环境变量发现Service. 环境变量名格式如下: {SVCNAME}_SERVICE_HOST {SVCNAME}_SERVICE_PORT 注:其中服务名和端口名转为大写,连字符转换为下划线. 限制: 1)Pod和Service的创建顺序是有要求的,Servi

Kubernetes之服务发现Service

目录 Kubernetes之服务发现Service 理解 Service的实现模型 userspace代理模式 iptables代理模式 ipvs代理模式 Service定义 Service配置清单重要字段 创建ClusterIP类型Service 创建NodePort类型Service Pod的会话保持 Headless无头Service Kubernetes之服务发现Service 理解 Service是对一组提供相同功能的Pods的抽象,并为它们提供一个统一的入口.借助Service,应用

k8s DNS 服务发现的一个坑

按照官当文档,以及大家的实践进行k8s dns 服务发现搭建还是比较简单的,但是会有一个因为系统默认dns 配置造成的一个问题 1. linux  默认dns 配置在 /etc/resolv.conf 一般来只会有几个简单的配置信息 比如:  nameserver XXXXXXXXX 但是今天在阿里云服务器上进行按照的时候出现了进行dns 解析测试的pod 能够解析,但是 自己创建的pod 不能使用 很是困惑, 阿里云dns 的配置如下: options timeout:1 attempts:1

【Linux】【Services】【SaaS】Docker+kubernetes(7. 安装consul实现服务注册发现)

1. 简介 1.1. Consul的功能: 服务发现:通过DNS或HTTP接口使得消费者发现服务,应用程序可以轻松找到所依赖的服务. 健康检查:防止将请发转发不健康的主机. 键值存储:可以使用分层键/值存储,比如功能标记.动态配置等. 多数据中心:开箱即用,不需要复杂的配置.这就意味着不用建立抽象的逻辑来扩展多个地区. 1.2. Consul集群介绍: -- Consul agent是Consul核心工作,分为client和server两种工作模式.默认以client模式运行,提供服务注册.健康