设为首页 收藏本站
查看: 1070|回复: 0

[经验分享] Kubernetes DNS 简介

[复制链接]

尚未签到

发表于 2018-1-4 12:46:13 | 显示全部楼层 |阅读模式
环境
  

$ sudo lsb_release -a  
No LSB modules are available.

  
Distributor>  
Description:    Ubuntu 16.04.2 LTS
  
Release:    16.04
  
Codename:   xenial
  

  
$ kubectl version
  
Client Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.4", GitCommit:"7243c69eb523aa4377bce883e7c0dd76b84709a1", GitTreeState:"clean", BuildDate:"2017-03-07T23:53:09Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}
  
Server Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.4", GitCommit:"7243c69eb523aa4377bce883e7c0dd76b84709a1", GitTreeState:"clean", BuildDate:"2017-03-07T23:34:32Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}
  

介绍
  从Kubernetes 1.3开始,DNS通过使用插件管理系统cluster add-on,成为了一个内建的自启动服务。
  
  Kubernetes DNS在Kubernetes集群上调度了一个DNS Pod和Service,并配置kubelet,使其告诉每个容器使用DNS Service的Ip来解析DNS名称。

什么是DNS名称
  集群中定义的每个Service(包括DNS Service它自己)都被分配了一个DNS名称。默认的,Pod的DNS搜索列表中会包含Pod自己的命名空间和集群的默认域,下面我们用示例来解释以下。
  
  假设有一个名为foo的Service,位于命名空间bar中。运行在bar命名空间中的Pod可以通过DNS查找foo关键字来查找到这个服务,而运行在命名空间quux中的Pod可以通过关键字foo.bar来查找到这个服务。

支持的DNS模式
  下面的章节详细的描述了支持的记录(record)类型和layout。

Services
  普通(非headless)的Service都被分配了一个DNS记录,该记录的名称格式为my-svc.my-namespace.svc.cluster.local,通过该记录可以解析出服务的集群IP。
  
  Headless(没有集群IP)的Service也被分配了一个DNS记录,名称格式为my-svc.my-namespace.svc.cluster.local。与普通Service不同的是,它会解析出Service选择的Pod的IP列表。

SRV records
  SRV records用于为命名端口服务,这些端口是headless或者普通Service的一部分。对于每个命名端口,SRV record的格式为:_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster.local。对于普通服务来说,这会解析出端口号和CNAMEmy-svc.my-namespace.svc.cluster.local。对于headless服务来说,这会解析出多个结果,一个是service后端的每个pod,一个是包含端口号,和格式为auto-generated-name.my-svc.my-namespace.svc.cluster.local的pod的CNAME。

向后兼容性
  kube-dns的之前版本,使用了格式为my-svc.my-namespace.cluster.local(svc这一层是后面加上的)的名称。但这种格式不再被支持了。

Pods
  pod会被分配一个DNS记录,名称格式为pod-ip-address.my-namespace.pod.cluster.local。
  
  比如,一个pod,它的IP地址为1.2.3.4,命名空间为default,DNS名称为cluster.local,那么它的记录就是:1-2-3-4.default.pod.cluster.local。
  
  当pod被创建时,它的hostname设置在Pod的metadata.name中(写yaml的时候应该很清楚这点)。
  
  在v1.2版本中,用户可以指定一个Pod注解,pod.beta.kubernetes.io/hostname,用于指定Pod的hostname。这个Pod注解,一旦被指定,就将优先于Pod的名称,成为pod的hostname。比如,一个Pod,其注解为pod.beta.kubernetes.io/hostname: my-pod-name,那么该Pod的hostname会被设置为my-pod-name。
  
  v1.2中还引入了一个beta特性,用户指定Pod注解,pod.beta.kubernetes.io/subdomain,来指定Pod的subdomain。比如,一个Pod,其hostname注解设置为“foo”,subdomain注解为“bar”,命名空间为“my-namespace”,那么它最终的FQDN就是“foo.bar.my-namespace.svc.cluster.local”。
  
  在v1.3版本中,PodSpec有了hostname和subdomain字段,用于指定Pod的hostname和subdomain。它的优先级则高于上面提到的pod.beta.kubernetes.io/hostname和pod.beta.kubernetes.io/subdomain。
  
  示例:
  

apiVersion: v1  
kind: Service
  
metadata:
  name: default-subdomain
  
spec:
  selector:
  name: busybox
  clusterIP: None
  ports:
  - name: foo # Actually, no port is needed.
  port: 1234
  targetPort: 1234
  
---
  
apiVersion: v1
  
kind: Pod
  
metadata:
  name: busybox1
  labels:
  name: busybox
  
spec:
  hostname: busybox-1
  subdomain: default-subdomain
  containers:
  - image: busybox
  command:
  - sleep
  - "3600"
  name: busybox
  
---
  
apiVersion: v1
  
kind: Pod
  
metadata:
  name: busybox2
  labels:
  name: busybox
  
spec:
  hostname: busybox-2
  subdomain: default-subdomain
  containers:
  - image: busybox
  command:
  - sleep
  - "3600"
  name: busybox
  

  如果一个headless service中,多个pod都在同一个命名空间里,并且subdomain名称也相同,集群的KubeDNS还是会为每个Pod返回完整而合格的hostname。给定一个Pod,其hostname设置为busybox-1,subdomain设置为default-subdomain,同一个命名空间中的headless Service名为default-subdomain,那么pod自己的FQDN就是“busybox-1.default-subdomain.my-namespace.svc.cluster.local”。
  
  在Kubernetes v1.2里,Endpoint对象还使用了注解endpoints.beta.kubernetes.io/hostnames-map。它的值就是json格式中的map[string(IP)][endpoints.HostRecord], 比如 ‘{“10.245.1.6”:{HostName: “my-webserver”}}’。如果Endpoint是用于headless service的,就会为其创建一个格式为...svc的记录。以json格式为例,如果Endpoint用于名为“bar”的headless service,其中一个Endpoint的ip为“10.245.1.6”,就会创建一个名为“my-webserver.bar.my-namespace.svc.cluster.local”的记录,查询该记录就会得到“10.245.1.6”。这个Endpoint注解一般不需要终端用户来指定,但可以被内部服务控制器使用,来实现上面的特性。
  
  在v1.3中,Endpoint对象可以为任何一个Endpoint指定hostname和IP。hostname字段会覆盖endpoints.beta.kubernetes.io/hostnames-map注解的值。
  
  在v1.3中,以下注解被弃用了:pod.beta.kubernetes.io/hostname,pod.beta.kubernetes.io/subdomain, endpoints.beta.kubernetes.io/hostnames-map。

如何测试DNS是否工作

创建一个简单地Pod,使用测试环境
  创建一个名为busybox.yaml文件,使用下面的内容:
  

apiVersion: v1  
kind: Pod
  
metadata:
  name: busybox
  namespace: default
  
spec:
  containers:
  - image: busybox
  command:
  - sleep
  - "3600"
  imagePullPolicy: IfNotPresent
  name: busybox
  restartPolicy: Always
  

  使用该文件创建pod:
  

kubectl create -f busybox.yaml  

等待pod进入running状态
  获取pod状态:
  

$ kubectl get pods busybox  

  你会看到:
  

NAME      READY     STATUS    RESTARTS   AGE  
busybox   1/1       Running   0          7m
  

  

确认DNS是否工作
  一旦pod处于running状态时,可以使用exec nslookup来查询状态:
  

$ kubectl exec -ti busybox -- nslookup kubernetes.default  

  你应该看到类似的结果:
  

Server:    10.0.0.10  
Address 1: 10.0.0.10
  

  
Name:      kubernetes.default
  
Address 1: 10.0.0.1
  

  如果出现上述结果,则说明DNS正常工作。

故障排查
  如果nslookup失败,检查以下选项:

检查本地DNS配置
  检查pod的resolv.conf文件。
  

$ kubectl exec busybox cat /etc/resolv.conf  

  确认搜索路径和name sever被设置成类似下面的样子(注意搜索路径可能因云提供商不同而有所差异):
  

search default.svc.cluster.local svc.cluster.local cluster.local google.internal c.gce_project_id.internal  
nameserver 10.0.0.10
  
options ndots:5
  

快速诊断
  如下的错误表明kube-dns add-on或者相关服务有问题:
  

$ kubectl exec -ti busybox -- nslookup kubernetes.default  
Server:    10.0.0.10
  
Address 1: 10.0.0.10
  

  
nslookup: can't resolve 'kubernetes.default'
  

  或者
  

$ kubectl exec -ti busybox -- nslookup kubernetes.default  
Server:    10.0.0.10
  
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
  

  
nslookup: can't resolve 'kubernetes.default'
  

检查DNS pod是否运行
  使用kubectl get pods命令来确认DNS pod是否正在运行。
  

$ kubectl get pods --namespace=kube-system -l k8s-app=kube-dns  

  应该会有如下的结果:
  

NAME                                                       READY     STATUS    RESTARTS   AGE  
...
  
kube-dns-v19-ezo1y                                         3/3       Running   0           1h
  
...
  

  如果没有相关的pod运行,或者pod状态为failed/completed,那么就说明你的环境下,没有默认部署DNS add-on,你需要手动部署它。

检查DNS pod中的错误
  使用kubectl log命令来查看DNS守护程序的日志。
  

$ kubectl logs --namespace=kube-system $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name) -c kubedns  
$ kubectl logs --namespace=kube-system $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name) -c dnsmasq
  
$ kubectl logs --namespace=kube-system $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name) -c healthz
  

  如果有任何可疑的日志,每一行开头的W,E,F字母分别表示警告、错误和故障。请搜索这些错误日志的条目,或者通过kubernetes issues页面来报错非预期的错误。

DNS服务是否启动
  使用kubectl get service命令来查看DNS服务是否已经启动。
  

$ kubectl get svc --namespace=kube-system  

  你会看到:
  

NAME                    CLUSTER-IP     EXTERNAL-IP   PORT(S)             AGE  
...
  
kube-dns                10.0.0.10      <none>        53/UDP,53/TCP        1h
  
...
  

  该服务会默认地被创建,或者如果你手动创建了该服务,但是该服务却并没有在上述命令中出现,请查看 debugging services page页面获取更多信息。

是否暴露了DNS Endpoint?
  可通过kubectl get endpoints命令来确认是否暴露了DNS Endpoint。
  

$ kubectl get ep kube-dns --namespace=kube-system  

  你应该会看到下面的结果:
  

NAME       ENDPOINTS                       AGE  
kube-dns   10.180.3.17:53,10.180.3.17:53    1h
  

  如果没有看到Endpoint,那么请查看debugging services page页面。
  
  若要查看更多的Kubernetes DNS示例,请在Kubernetes Github仓库中查看cluster-dns examples。

如何工作
  运行的Kubernetes DNS pod包含3个容器——kubedns、dnsmasq和一个叫做healthz的健康检查容器。kubedns进程监视Kubernetes master上Service和Endpoint的改变,并在内存中维护lookup 结构用于服务DNS请求。dnsmasq容器增加DNS缓存,从而提升性能。healthz容器提供一个单点的健康检查Endpoint,检查dnsmasq和kubedns的健康程度。
  
  DNS pod以服务的形式暴露出来,它拥有一个静态IP。一旦被创建,kubelet就使用--cluster-dns=10.0.0.10标识,将DNS配置信息传递给每个容器。
  
  DNS名称也需要域。本地域是可以配置的,在kubelet中,使用--cluster-domain=<default local domain>参数。
  
  Kubernetes集群的DNS服务(基于SkyDNS库)支持forward lookup(A recoreds),service lookup(SRV records)和反向IP地址查找(PTR recoreds)。

从node继承DNS
  当运行pod时,kubelet会预先考虑集群的DNS服务,并在node本地的DNS设置中搜索路径。如果node能够解析DNS名称,那么pod也可以做到。
  
  如果你希望在pod中使用不同的DNS,那么你可以使用kubelet的--resolv-conf参数。该设置意味着pod不会从node继承DNS。设置该值为其他的文件路径,意味着会使用该文件来配置DNS,而不是/etc/resolv.conf。

已知的问题
  Kubernetes安装默认并不会使用集群的DNS配置来设置Kubernetes node的resolv.conf文件,因为该进程依赖于发行版的配置。
  
  Linux的libc有着3个DNS nameserver和6个DNS搜索记录的限制,Kubernetes需要消耗一个nameserver和3个搜索记录。这意味着如果一个本地配置已经使用了3个nameserver或者使用了3个以上的搜索记录,那么这些配置可能会丢失。有一个临时方案,node可以运行dnsmasq,它可以提供更多的nameserver选项,但不能提供更多的搜索选项。你也可以使用kubelet的--resolv-conf选项。
  
  如果你使用的是Alpine 3.3或更早的版本,DNS可能不能正常的工作,这是已知的问题。可以查看这里获取更多信息。

References
  Docs for the DNS cluster addon

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-431497-1-1.html 上篇帖子: Hello,Kubernetes 下篇帖子: 配置kubernetes UI图形化界面
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表