前言
本文首发于公众号【我的小碗汤】本公众号 免费 提供 csdn 下载服务,海量 IT 学习资源,如果你准备入 IT 坑,励志成为优秀的程序猿,那么这些资源很适合你,包括但不限于 java、go、python、springcloud、elk、嵌入式、大数据、面试资料、前端 等资源。扫码关注:
正文
前几天,在 ucloud 上搭建的 k8s 集群(搭建教程后续会发出)。今天发现域名解析不了。
组件版本:k8s 1.15.0,coredns:1.3.1
过程是这样的:
首先用以下 yaml 文件创建了一个 nginx 服务
apiVersion: v1
kind: Service
metadata:
name: nginx-svc-old
labels:
app: nginx-svc
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-old
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
创建好之后:
因只部署了一个 master 节点。在 master 宿主机上直接执行以下命令:
nslookup nginx-svc-old.default.svc
发现不能解析域名。事先也在宿主机上 /etc/resolv.conf 里配置了 nameserver {coredns 的 podIP}
这样一来,就以为可能是 coredns 有问题。。
然后用以下 yaml 创建了一个 busybox 作为调试工具:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: busybox-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: busybox
spec:
restartPolicy: Always
containers:
- name: busybox
command:
- sleep
- "3600"
image: busybox
这里用的是截止 2019/07/20,busybox 的最新镜像。创建好之后,exec 进入容器,执行测试命令
发现解析不了:
/ # nslookup nginx-svc-old.default.svc
Server: 10.96.0.10
Address: 10.96.0.10:53
** server can't find nginx-svc-old.default.svc: NXDOMAIN
*** Can't find nginx-svc-old.default.svc: No answer
根据 coredns 解析集群内域名原理可知:
服务 a 访问服务 b,对于同一个 Namespace 下,可以直接在 pod 中,通过 curl b 来访问。对于跨 Namespace 的情况,服务名后边对应 Namespace 即可,比如 curl b.default。DNS 如何解析,依赖容器内 resolv 文件的配置。
查看 busybox 容器内的 resolve.conf 文件:
[root@liabio nginx]# kubectl exec -ti busybox-deployment-59755c8c6d-rmrfq sh
/ # nslookup nginx-svc-old.default.svc
Server: 10.96.0.10
Address: 10.96.0.10:53
** server can't find nginx-svc-old.default.svc: NXDOMAIN
*** Can't find nginx-svc-old.default.svc: No answer
/ # cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
/ #
这个文件中,配置的 DNS Server,一般就是 K8S 中,kubedns 的 Service 的 ClusterIP,这个 IP 是虚拟 IP,无法 ping,但可以访问。
在容器内发请求时,会根据 /etc/resolv.conf 进行解析流程。选择 nameserver 10.96.0.10 进行解析,然后用 nginx-svc-old,依次带入 /etc/resolve.conf 中的 search 域,进行 DNS 查找,分别是:
search 内容类似如下(不同的 pod,第一个域会有所不同)
search default.svc.cluster.local svc.cluster.local cluster.local
nginx-svc-old.default.svc.cluster.local -> nginx-svc-old.svc.cluster.local -> nginx-svc-old.cluster.local
直到找到为止。所以,我们执行 ping nginx-svc-old,或者执行 ping nginx-svc-old.default,都可以完成 DNS 请求,这 2 个不同的操作,会分别进行不同的 DNS 查找步骤。
根据以上原理,查看到 busybox 内的域名 /etc/resolv.conf 没有问题,nameserver 指向正确的 kube-dns 的 service clusterIP。
这下更加怀疑 core-dns 有问题了。
但查看 coredns 日志,可以看到并没有报错:
那就说明不是 coredns 问题了。。
把 busybox 里报的错误,进行搜索 google
*** Can't find nginx-svc-old.default.svc: No answer
查到了以下两个 issue:
issues1:
https://github.com/kubernetes…
issues2:
https://github.com/easzlab/ku…
发现都说是 busybox 镜像的问题,从 1.28.4 以后的镜像都存在这问题。把镜像换成 1.28.4 试试?修改 yaml 版本号:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: busybox-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: busybox
spec:
restartPolicy: Always
containers:
- name: busybox
command:
- sleep
- "3600"
image: busybox:1.28.4
重新 apply 后,进入容器:
确实可以成功解析域名了。
那为什么宿主机上直接执行测试命令,域名不能解析呢?
继续 google,知道 resolver 域名解析器:
nameserver 关键字,如果没指定 nameserver 就找不到 DNS 服务器,其它关键字是可选的。nameserver 表示解析域名时使用该地址指定的主机为域名服务器。其中域名服务器是按照文件中出现的顺序来查询的,且只有当第一个 nameserver 没有反应时才查询下面的 nameserver,一般不要指定超过 3 个服务器。
而我在宿主上 /etc/resolv.conf 中 nameserver 如下:
且前三个域名解析服务器后可以通。
现在试着把 coredns 的其中一个 podIP:192.168.155.73 放到第一个 nameserver:
可以看到现在可以解析了。
其实最好把 kube-dns service 的 clusterIP 放到 /etc/resolv.conf 中,这样 pod 重启后也可以解析。
参考
Linux 中 /etc/resolv.conf 文件简析
https://blog.csdn.net/lcr_hap…
CoreDNS 系列 1:Kubernetes 内部域名解析原理、弊端及优化方式
https://hansedong.github.io/2…
历史文章
k8s 中负载均衡器【ingress-nginx】部署
k8s 使用 Job 执行任务失败怎么办
从外部访问 Kubernetes 中的 Pod
k8s 负载均衡器配置请求重定向
教你轻松获取 k8s 镜像和安装包
k8s 必学必会知识梳理
docker 基础知识整理
-
- *
本公众号 免费 提供 csdn 下载服务,海量 IT 学习资源,如果你准备入 IT 坑,励志成为优秀的程序猿,那么这些资源很适合你,包括但不限于 java、go、python、springcloud、elk、嵌入式、大数据、面试资料、前端 等资源。同时我们组建了一个技术交流群,里面有很多大佬,会不定时分享技术文章,如果你想来一起学习提高,可以公众号后台回复【2】,免费邀请加技术交流群互相学习提高,会不定期分享编程 IT 相关资源。
-
- *
扫码关注,精彩内容第一时间推给你