date: 2020-05-11title: k8s踩坑记——pod解析外网域名 #标题
tags: pod解析外网域名 #标签
categories: k8s # 分类
今天一早,开发小姐姐找来,一个应用pod需要解析一个外网的域名,但是时而可以解析到,时而解析不到,很是神奇。
这个问题是上周遗留的问题,当时是完全解析不到,具体是怎么回事,也没有深入研究,在组长的建议下,将集群内部的coredns容器由原来的2个副本改成了一个副本,当时再解析就好了,但是周一上班,发现并没有好,只是有时能解析到,有时解析不到。
这个k8s集群并不是我部署的,本人对于k8s里深奥的原理也是一知半解,所以并没有什么排查思路,这里也不说废话了,直接说解决办法吧。
环境描述
$ cat /etc/resolv.conf # k8s各个宿主机节点的resolv.conf文件如下
# Generated by NetworkManager
nameserver 114.114.114.114
nameserver 10.252.201.134
nameserver 10.252.201.125
$ cat /etc/resolv.conf # pod中的resolv.conf文件如下
# Generated by NetworkManager
nameserver 10.96.0.20 # 此ip为coredns的IP地址
排查过程
配置文件就先来上面那两个,现在我们来了解下一个pod需要域名解析时是怎样一个工作流程(以下流程全是自己的理解,可能不太准确)。
当pod需要解析一个域名时,如果域名是k8s集群内部的pod,那么coredns就会返回ip信息,至此解析结束,那如果是公网的域名呢?比如说是www.baidu.com
,那么此时coredns根据它自己的配置是无法解析的,怎么办呢?在coredns容器启动时,它会将宿主机的/etc/resolv.conf文件挂载到自己内部使用,也就是说coredns的/etc/resolv.conf文件和宿主机的是一致的,然后通过此文件指定的nameserver进行解析外网域名。
当时我也查看过coredns的日志,可以没有什么东西,只有短短几行记录,so….看coredns的yml文件,命令如下:
$ 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 k8s]# kubectl describe configmap/coredns -n kube-system
Name: coredns
Namespace: kube-system
Labels: <none>
Annotations: <none>
Data
====
Corefile:
----
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
proxy . /etc/resolv.conf
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服务器上,所以就出现了我这种情况。