搭建Kubernetes集群时DNS无法解析问题的处理过程 k8s

摘要:
在Kubernetes集群中,kubelet是负责管理Pod的工作组件。根据kubernetes文档,kubelet将默认为/etc/resolv。conf文件读取DNS服务器地址,以便dnsPolicy从DefaultPod继承。kubelet中的--resolv conf参数可以指定此配置文件的地址。摘要还通过对问题的探索了解了Kubernetes集群中DNS解析的完整过程,如图所示。

作者:simpleapples ,来源:简书,原文链接

问题描述

在搭建Kubernetes集群过程中,安装了kube-dns插件后,运行一个ubuntu容器,发现容器内无法解析集群外域名,一开始可以解析集群内域名,一段时间后也无法解析集群内域名。

$ nslookup kubernetes.default
Server:    10.99.0.2
Address 1: 10.99.0.2 kube-dns.kube-system.svc.cluster.local

nslookup: can't resolve 'kubernetes.default'

排查过程

在排查问题前,先思考一下Kubernetes集群中的DNS解析过程,在安装好kube-dns的集群中,普通Pod的dnsPolicy属性是默认值ClusterFirst,也就是会指向集群内部的DNS服务器,kube-dns负责解析集群内部的域名,kube-dns Pod的dnsPolicy值是Default,意思是从所在Node继承DNS服务器,对于无法解析的外部域名,kube-dns会继续向集群外部的dns进行查询,过程如图。

搭建Kubernetes集群时DNS无法解析问题的处理过程 k8s第1张

Ubuntu容器是一个普通的Pod,在Linux系统中,/etc/resolv.conf是存储DNS服务器的文件,普通Pod的/etc/resolv.conf文件应该存储的是kube-dns的Service IP。

nameserver 10.99.0.2  # 这里存储的是kube-dns的Service IP
search default.svc.cluster.local. svc.cluster.local. cluster.local.
options ndots:5

查看后发现 /etc/resolv.conf 文件中存储的是kube-dns的Service IP,证明这一步没有问题,接下来查看一下 kube-dns 的Pod,先进入kube-dns的Pod中检查一下 /etc/resolv.conf 文件,这里存储的应该是集群外部的DNS服务器地址,查看后发现,这里存储的地址是127.0.0.53,进一步查看kube-dns Pod的log,发现出现了非常多的i/o timeout错误。

2018/07/11 07:12:47 [ERROR] 2 [www.baidu.com](http://www.baidu.com/). A: unreachable backend: read udp 127.0.0.1:57567->127.0.0.53:53: i/o timeout

现在基本上可以发现问题的原因了,kube-dns只能解析集群内部地址,而集群外部地址应该发给外部DNS服务器进行解析,由于kube-dns Pod中的 /etc/resolv.conf 文件存储的DNS服务器地址是127.0.0.53,127...*都是回环地址,也就是集群外域名的DNS解析请求会再次发送回kube-dns,导致形成一个循环,这也是一秒钟会出现几十次 i/o timeout 日志的原因,请求会不断的在kube-dns中循环,kube-dns就像一个黑洞一样,吃掉了所有dns解析请求,不断累积的请求最终会导致整个集群的网络出现卡顿。

搭建Kubernetes集群时DNS无法解析问题的处理过程 k8s第2张

为什么

虽然问题的原因找到了,但是为什么kube-dns Pod中/etc/resolv.conf文件存储的DNS服务器是127.0.0.53?

kube-dns Pod的dnsPolicy值是Default,查看一下Kubernetes文档。

"Default": The Pod inherits the name resolution configuration from the node that the pods run on. See related discussion for more details.

所以kube-dns的 /etc/resolv.conf 文件是从Node中继承来的,查看Node中的 /etc/resolv.conf 文件,存储的DNS服务器地址确实是 127.0.0.53 ,那么下一个问题出现了,在Node中发送DNS解析请求为什么不会产生回环的问题呢?

Node使用的是Ubuntu 18.04 Server,在这个版本的系统中,DNS解析请求并不是直接发给所在网络的DNS服务器的,Ubuntu 18.04中有一个systemd-resolved服务,为本地应用程序提供了DNS解析服务,例如 nslookup localhost ,解析程序从 /etc/resolv.conf 文件中找到DNS服务器127.0.0.53,发送解析请求,systemd-resolved会监听在53端口上,捕获到解析请求后,如果是自己可以解析的,例如localhost,会直接返回127.0.0.1,如果不能解析,才会发送给外部服务器,而外部服务器的地址存储在 /run/systemd/resolve/resolv.conf 文件中,这个文件是systemd-resolved服务器的配置文件,过程如图。

搭建Kubernetes集群时DNS无法解析问题的处理过程 k8s第3张

怎么破

理解了问题的来龙去脉,解决问题的办法也就应运而生。在Kubernetes集群中,kubelet是worker组建,负责管理Pod,根据kubernetes文档,kubelet默认会从Node的 /etc/resolv.conf 文件读取DNS服务器地址,使得dnsPolicy是Default的Pod得以继承,kubelet中的--resolv-conf参数可以指定这个配置文件的地址。在Ubuntu 18.04中,将这个参数设置为systemd-resolved的DNS服务器配置文件/run/systemd/resolve/resolv.conf,Pod就会继承真正的外部DNS服务器。

总结

通过对问题的探究,也理解了Kubernetes集群中DNS解析的完整过程,如图。

搭建Kubernetes集群时DNS无法解析问题的处理过程 k8s第4张

* 在Ubuntu 16.04中也是类似的逻辑,只不过systemd-resolved换成了dnsmasq,监听地址是127.0.1.1
* 在具体实践过程中,也顺便探究了CoreDNS和KubeDNS架构和解析逻辑上的区别,不过不在此问题的讨论范围,有兴趣的朋友可以自己看一下。
* 如果Kubernetes集群是安装在NAT网络下的虚拟机上,虚拟机(也就是Kubernetes集群中的Node)中/etc/resolv.conf文件可能被修改为NAT的地址,也就不会出现上面这个问题。

参考内容

https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/
https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/
https://www.freedesktop.org/software/systemd/man/systemd-resolved.service.html
https://github.com/kubernetes/kubernetes/issues/49411
https://github.com/kubernetes/kubernetes/issues/45828 

免责声明:文章转载自《搭建Kubernetes集群时DNS无法解析问题的处理过程 k8s》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇微信小程序 授权登录详解(附完整源码)Windows中的时间(SYSTEMTIME和FILETIME) (转载)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Install Docker on Ubuntu

目前支持的 Ubuntu 版本: Ubuntu Xenial 16.04 (LTS) Ubuntu Wily 15.10 Ubuntu Trusty 14.04 (LTS) Ubuntu Precise 12.04 (LTS) Prerequisites 内核版本不能低于 3.10 $ uname -r 3.11.0-15-generic 如果之前使...

(转)Ubuntu中启用关闭Networkmanager网络设置问题!

【Server版本】 在UbuntuServer版本中,因为只存有命令行模式,所以要想进行网络参数设置,只能通过修改/etc/network/interfaces。具体设置方法如下: (1) UbuntuServer 修改 IP地址 打开/etc/network/interfaces sudo vim/etc/network/interfaces 加入以...

dcos的问题汇总

. group 'docker' does not exist  需要手工创建docker组,这一步本来应该是在安装docker的时候来完成的,但是采用yum install的方式不行,需要添加一个docker的repo然后才能够安装。 2. ssh: connect to host 10.1.108.64 port 22: Operation timed...

Centos7永久修改hostname

hostnamectl set-hostname hdp-01 centos7中除了修改hosts文件和network文件后,还需修改etc/hostname文件,具体步骤如下第一步:修改/etc/sysconfig/network文件#>vi /etc/sysconfig/network添加或修改:NETWORKING=yesHOSTNAME=sl...

大数据的那些面试题及答案(一) ---阿善有用

文章目录 1. Flume系列: 2. zookeeper系列 3.spark系列 4.Mysql系列 5.其他大数据面试题 1. Flume系列: 1.Channel Selectors有几种类型,它们的区别是什么?答:有两种。Replicating Channel Selector(默认的)和Multiplexing Channel Sele...

kubernetes命令(一)

版权声明:本文为博主原创文章,支持原创,转载请附上原文出处链接和本声明。 本文链接地址:https://www.cnblogs.com/wannengachao/p/12073552.html 1、查看pod 格式:kubectl get pod 2、查看node 格式:kubectl get node 3、查看pod详细信息 格式:kubectl des...