采坑指南——k8s域名解析coredns问题排查过程
正文
前几天,在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/kubernetes/issues/66924
issues2:
https://github.com/easzlab/kubeasz/issues/260
发现都说是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_happy/article/details/54867510
CoreDNS系列1:Kubernetes内部域名解析原理、弊端及优化方式
https://hansedong.github.io/2018/11/20/9/
历史文章
本公众号免费提供csdn下载服务,海量IT学习资源,如果你准备入IT坑,励志成为优秀的程序猿,那么这些资源很适合你,包括但不限于java、go、python、springcloud、elk、嵌入式 、大数据、面试资料、前端 等资源。同时我们组建了一个技术交流群,里面有很多大佬,会不定时分享技术文章,如果你想来一起学习提高,可以公众号后台回复【2】,免费邀请加技术交流群互相学习提高,会不定期分享编程IT相关资源。
扫码关注,精彩内容第一时间推给你
采坑指南——k8s域名解析coredns问题排查过程的更多相关文章
- 小程序:web-view采坑指南
最近负责开发的[广州医保查询]小程序已经发布上线,其中使用web-view组件完成的[在线绑定社保卡]核心流程,遇到了一些坑,现总结如下: 首先,让我们一起看看什么是web-view ? 小程序api ...
- shiro采坑指南—基础概念与实战
说明 代码及部分相关资料根据慕课网Mark老师的视频进行整理. 其他资料: shiro官网 基础概念 Authenticate/Authentication(认证) 认证是指检查用户身份合 ...
- k8s采坑记 - 解决二进制安装环境下证书过期问题
前言 上一篇k8s采坑记 - 证书过期之kubeadm重新生成证书阐述了如何使用kubeadm解决k8s证书过期问题. 本篇阐述使用二进制安装的kubernetes环境,如何升级过期证书? k8s配置 ...
- 一次压力测试Bug排查-epoll使用避坑指南
Bug复现 使用Webbench对服务器进行压力测试,创建1000个客户端,并发访问服务器10s,正常情况下有接近8万个HTTP请求访问服务器. 结果显示仅有7个请求被成功处理,0个请求处理失败,服务 ...
- ERP新人防坑指南
本文作为初入ERP行业的新人的防坑指南,讲解了一些常见犯的错,这样也少走一些弯路,如果你是老鸟,请绕过 :-) 本文关联的代码使用kotlin编写,请自行转换为c#.java等你熟悉的语言,表述的坑在 ...
- Hadoop环境搭建--Docker完全分布式部署Hadoop环境(菜鸟采坑吐血整理)
系统:Centos 7,内核版本3.10 本文介绍如何从0利用Docker搭建Hadoop环境,制作的镜像文件已经分享,也可以直接使用制作好的镜像文件. 一.宿主机准备工作 0.宿主机(Centos7 ...
- Kubernetes Fluentd+Elasticsearch+Kibana统一日志管理平台搭建的填坑指南
在初步完成Kubernetes集群架构的建立后,通过搭建一些监控组件,我们已经能够实现 图形化的监控每个node,pod的状态信息和资源情况 通过scale进行replicateSet的扩展和伸缩 通 ...
- 实现万行级excel导出---poi--ooxm的应用和采坑
xl_echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!! - ...
- java采坑之路
判断相等 字符串判断相等 String str1 = null; String str2 = "java金融"; // str1.eq ...
随机推荐
- GraphQL Java-入门指南
GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时. GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任 ...
- Erlcron分析学习
介绍 Erlcron实现类似Linux下面的cron的计划任务. 源码下载地址:https://github.com/erlware/erlcron 原理 Erlcron进程监控树 ecrn_cron ...
- 学习笔记-Unity3d代码实现Windows10加载圈圈的效果
最近在写一个Unity3d的模仿windows10的桌面的程序,由于Unity3d本身不支持Gif图片,所以突发奇想使用代码来实现接近的. 接下来是代码部分:不一一解析,很简单,看的懂原理就Okly了 ...
- docker-将自己的Linux打包为镜像
基于原始文件和目录从0开始制作镜像: 1).基于CentOS7 Linux纯净系统(初始化安装完成),将Linux整个系统打包成tar文件即可: cd /root/ tar --numeric-own ...
- C++11部分特性
初识C++的时候,觉得会个STL就差不多了,后来发现了C++11这个东西,以及C++14,C++17QAQ,看了一下,好高深不学,emmmm真香= = 这里就只讲一下对ACM写代码有很高帮助的部分特性 ...
- Dart类型变量-表示信息
Dart执行入口 Dart要求以main函数作为执行的入口 Dart的变量和类型 在Dart中可以用var或者具体的类型来声明一个变量.当使用var定义变量时,表示类型是由编译器推断决定.使用静态类型 ...
- Angular4+Koa2+MongoDB开发个人博客
**文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号.** ![file](https://img2018.cnblogs.com/blog/830272/201 ...
- MySQL索引&&开发规范
规范总结 索引规范 默认添加的索引都是BTree索引.Innodb只支持BTree索引. 设计索引原则 - 最适合索引的列是WHERE子句中的列,而不是SELECT中的列. - 如果索引的字段很长,使 ...
- HTML定位——绝对定位和相对定位、固定定位
1.绝对定位 绝对定位指的是通过规定HTML元素在水平和垂直方向上的位置来固定元素,基于绝对定位的元素不会占据空间. 绝对定位的位置声明是相对于已定位的并且包含关系最近的祖先元素.如果当前需要被定为的 ...
- Spark学习之Scala的基础知识
Scala的变量声明 在Scala创建变量的时候,必须使用val或者var val,变量值不可修改,一旦分配不能重新指向别的值 var,分配后,可重新指向类型相同的值 举例 val lines = s ...