k8s master机器环境
- 宿主机resolv.conf
# cat /etc/resolv.conf
nameserver 172.16.100.1
- pod中的resolv.conf文件如下
$ cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 10.96.0.10 # 此ip为coredns的IP地址
排查过程
当pod需要解析一个域名时,如果域名是k8s集群内部的pod,那么coredns就会返回ip信息,至此解析结束,那如果是公网的域名呢?
比如说是www.baidu.com,那么此时coredns根据它自己的配置是无法解析的,怎么办呢?在coredns容器启动时,它会将宿主机的/etc/resolv.conf文件挂载到自己内部使用,也就是说coredns的/etc/resolv.conf文件和宿主机的是一致的,然后通过此文件指定的nameserver进行解析外网域名。
# kubectl get pod -n kube-system # 获取到coredns-name
# kubectl edit coredns-name -n kube-system # 查看coredns的yaml文件内容
我在coredns的yml文件中,看到了它的volumes挂载了一个名为coredns的configmap,然后使用下面的指令去查看了下这个configmap,如下:
[root@k8s-master-001 sysctl.d]# kubectl describe configmap/coredns -n kube-system
Name: coredns
Namespace: kube-system
Labels: <none>
Annotations: <none>
Data
====
Corefile:
----
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
关于上面configmap的解释如下:
- errors: 输出错误信息到控制台。
- health:CoreDNS 进行监控检测,检测地址为 http://localhost:8080/health 如果状态为不健康则让 Pod 进行重启。
- ready: 全部插件已经加载完成时,将通过 endpoints 在 8081 端口返回 HTTP 状态 200。
- kubernetes:CoreDNS 将根据 Kubernetes 服务和 pod 的 IP 回复 DNS 查询。
- prometheus:是否开启 CoreDNS Metrics 信息接口,如果配置则开启,接口地址为 http://localhost:9153/metrics
- forward:任何不在Kubernetes 集群内的域名查询将被转发到预定义的解析器 (/etc/resolv.conf)。
- cache:启用缓存,30 秒 TTL。
- loop:检测简单的转发循环,如果找到循环则停止 CoreDNS 进程。
- reload:监听 CoreDNS 配置,如果配置发生变化则重新加载配置。
- loadbalance:DNS 负载均衡器,默认 round_robin。
好,我的注意点落在了loadbalance这个配置上,然后在宿主机上,使用dig指令,/etc/resolv.conf文件中的三个nameserver分别解析我们的公网域名。发现后面两个nameserver是无法解析我们的公网域名的,然后啥也不说了,把宿主机上的/etc/resolv.conf文件中指定的两个内网dns服务器干掉,就剩下一个114.114.114.114,然后删除coredns这个pod的(然后它会自动重启新的pod,相当于重启coredns了),再次进入应用pod中多次解析验证,问题解决,ok。
问题总结
宿主机本地的/etc/resolv.conf文件中有两个nameserver是指定的内网的dns,这两个dns解析不到公网域名,coredns又是以轮询的方式去找那几个nameserver的,解析记录的缓存是30s(也就是说,如果你解析到了,那么未来30s的解析都是成功的),30s后再解析,解析请求就会落到那两个内网dns服务器上,所以就出现了我这种情况
--------------------------------------------------------------------------------------------------------------------------------
经过上面的 ping
测试和 nslookup
测试,分析发现 k8s
集群内部 pod
解析外部域名,先走 coredns
内部域名解析,再走局域网 dns
解析。而无法解析的时候问题原因是:coredns
解析就返回报错了,定位问题为 coredns
解析外部域名存在问题。
网上查看问题,发现可能是 coredns
解析问题导致
- 查看
coredns
的配置文件如下
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
reload
loadbalance
}
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
其中 forward . /etc/resolv.conf 配置表示使用当coredns内部不能解析的时候,向宿主机上的resolv.conf文件中配置的nameserver转发dns解析请求,当宿主机上namserver有多个时,默认采用的时random的方式随机转发,失败后就返回错误。
- 宿主机
/etc/resolv.conf
$ cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 172.16.0.50
nameserver 114.114.114.114
- 将其 forward 的 policy 设置为 sequential
forward . /etc/resolv.conf {
max_concurrent 1000 # 新增配置
policy sequential # 新增配置
}
解决方案
- 编辑
coredns
配置文件,修改配置,并重启POD
$ kubectl -n kube-system edit cm coredns
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000 # 新增配置
policy sequential # 新增配置
}
cache 30
reload
loadbalance
}
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
$ kubectl -n kube-system delete pods coredns-xxxxxx
----------------------------------------------------------------------------------------------------------------------
自己排查如下:
[root@k8s-pre-m01 ~]# kubectl logs coredns-7f8ff9c97-6tlln -n kube-system -f
.:53
[INFO] plugin/reload: Running configuration SHA512 = 676a3d7c6fa16eff8b618d85b13f15775f15fabfbb23dbec6f9beecc102ad51e0663f9f30fd8b93736d0e9564d8e452bd51d530094547764b7e5fab04763519d
CoreDNS-1.9.3
linux/amd64, go1.18.2, 45b0a11
[ERROR] plugin/errors: 2 jmenv.tbsite.net. AAAA: read udp 10.196.129.208:42449->10.196.17.210:53: i/o timeout
failed to create fsnotify watcher: too many open files[root@k8s-pre-m01 ~]# kubectl logs coredns-7f8ff9c97-wqmw8 -n kube-system -f
.:53
[INFO] plugin/reload: Running configuration SHA512 = 676a3d7c6fa16eff8b618d85b13f15775f15fabfbb23dbec6f9beecc102ad51e0663f9f30fd8b93736d0e9564d8e452bd51d530094547764b7e5fab04763519d
CoreDNS-1.9.3
linux/amd64, go1.18.2, 45b0a11
master节点和node节点对dns的访问权限是不一样的,master和node在不同网段,对10.196.17.210访问结果不一样,如果coredns调度在master上面,那么coredns就报错,如果是node节点正常。
[root@k8s-pre-m01 ~]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 10.196.17.210
[root@k8s-pre-n02 ~]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 10.196.17.210