请选择 进入手机版 | 继续访问电脑版
 找回密码
 立即注册
搜索

kubernetes 1.18+ 使用ipvs后coredns无法解析域名web问题

[复制链接]
2160 abc 发表于 2020-11-30 10:39:26
  1. 环境现象
  2. CoreDNS 版本:1.6.7
  3. Docker 版本:18.06.3-ce
  4. Kubernetes 版本:1.18.1
  5. 操作系统版本:CentOS 7.x
  6. CentOS 内核版本:3.10.0-693.2.2.el7.x86_64

  7. 问题现象
  8. 由于最近要向组内演示 Istio 1.5,故在云服务器上安装了kubernetes 1.18.1 (使用ipvs) 来配合 Istio 1.5 的演示,kubernetes 与 istio 安装完后一切顺利,bookinfo demo跑的也非常的顺利。但在一次重启整个集群后,一切都变的不那么美好了。istio-proxy起不来了,提示pilot not ready,更可悲的是service name 无法解析了,导致很多服务之间的调用都没法正常工作,有依赖的服务都不能正常启动了,为了更好的定位问题,于是卸载 Istio 1.5,重新回到k8s 1.18.1上,在一步步排查中发现,在pod中使用pod ip相互访问是可以的,由此判断,初步怀疑很可能是 DNS 出现了问题,后来慢慢发现 kube-proxy 中的错误,再定位到 IPVS parseIP Error 错误,再到解决问题。以下是整个问题定位分析

  9. 问题定位
  10. 为了更好的重现问题,我重新安装了一套新的 kubernetes 1.18.1,安装完后验证一切都是ok,接下来我就重启整个集群,问题就产生了,在pod中无法解析service name了,所有的pod运行都是ok的,一切都变的”很神奇”,好吧,开启定位之旅。

  11. 部署DNS调试工具
  12. 为了探针是否为 DNS 问题,这里需要提前部署用于测试 DNS 问题的 dnsutils 镜像,该镜像中包含了用于测试 DNS 问题的工具包,非常利于我们分析与发现问题。

  13. 部署 ndsutils.yaml

  14. 1
  15. 2
  16. 3
  17. 4
  18. 5
  19. 6
  20. 7
  21. 8
  22. 9
  23. 10
  24. apiVersion: v1
  25. kind: Pod
  26. metadata:
  27.   name: dnsutils
  28. spec:
  29.   containers:
  30.   - name: dnsutils
  31.     image: mydlqclub/dnsutils:1.3
  32.     imagePullPolicy: IfNotPresent
  33.     command: ["sleep","3600"]
  34. 问题分析
  35. 1. 进入 DNS 工具 Pod 的命令行
  36. 1
  37. kubectl exec -it dnsutils sh
  38. 2. 通过 Ping 和 Nsloopup 命令测试
  39. 1
  40. 2
  41. 3
  42. 4
  43. 5
  44. 6
  45. 7
  46. 8
  47. 9
  48. 10
  49. 11
  50. 12
  51. 13
  52. 14
  53. 15
  54. 16
  55. 17
  56. 18
  57. 19
  58. 20
  59. 21
  60. # Ping 集群外部,例如这里 ping 一下百度
  61. $ ping www.baidu.com
  62. ping: bad address 'www.baidu.com'

  63. # Ping 集群内部 kube-apiserver 的 Service 地址
  64. $ ping kubernetes.default
  65. ping: bad address 'kubernetes.default'

  66. # 使用 nslookup 命令查询域名信息
  67. $ nslookup kubernetes.default
  68. ;; connection timed out; no servers could be reached

  69. # 直接 Ping 集群内部 kube-apiserver 的 IP 地址
  70. $ ping 10.96.0.1
  71. PING 10.96.0.1 (10.96.0.1): 56 data bytes
  72. 64 bytes from 10.96.0.1: seq=0 ttl=64 time=0.096 ms
  73. 64 bytes from 10.96.0.1: seq=1 ttl=64 time=0.050 ms
  74. 64 bytes from 10.96.0.1: seq=2 ttl=64 time=0.068 ms

  75. # 退出 dnsutils Pod 命令行
  76. $ exit
  77. 可以观察到两次 ping 域名都不能 ping 通,且使用 nsloopup 分析域名信息时超时。然而,使用 ping kube-apiserver 的 IP 地址 “10.96.0.1” 则可以正常通信,所以,排除网络插件(flannel、calico 等)的问题。初步判断,很可能是 CoreDNS 组件的错误引起的某些问题,所以接下来我们测试 CoreDNS 是否正常。

  78. 3. 检测 CoreDNS 应用是否正常运行
  79. 1
  80. 2
  81. 3
  82. 4
  83. $ kubectl get pods -l k8s-app=kube-dns -n kube-system
  84. NAME                       READY   STATUS    RESTARTS   AGE
  85. coredns-669f77d7cc-8pkpw   1/1     Running   2          6h5m
  86. coredns-669f77d7cc-jk9wk   1/1     Running   2          6h5m
  87. 可也看到 CoreDNS 两个 Pod 均正常启动,所以再查看两个 Pod 中的日志信息,看看有无错误日志:

  88. 1
  89. 2
  90. 3
  91. 4
  92. 5
  93. 6
  94. 7
  95. 8
  96. 9
  97. 10
  98. 11
  99. $ for p in $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name); \
  100.   do kubectl logs --namespace=kube-system $p; done

  101. .:53
  102. [INFO] plugin/reload: Running configuration MD5 = 4e235fcc3696966e76816bcd9034ebc7
  103. CoreDNS-1.6.7
  104. linux/amd64, go1.13.6, da7f65b
  105. .:53
  106. [INFO] plugin/reload: Running configuration MD5 = 4e235fcc3696966e76816bcd9034ebc7
  107. CoreDNS-1.6.7
  108. linux/amd64, go1.13.6, da7f65b
  109. 通过上面信息可以观察到,日志中信息也是正常启动没有问题。再接下来,查看下 CoreDNS 的入口 Service “kube-dns” 是否存在:

  110. kube-dns 的 IP 为 10.96.0.10,集群内的 Pod 都是通过该 IP 与 DNS 组件进行交互,查询 DNS 信息。

  111. 1
  112. 2
  113. 3
  114. $ kubectl get service -n kube-system | grep kube-dns
  115. NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)               
  116. kube-dns                    ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP,9153/TCP
  117. 上面显示 Service “kube-dns” 也存在,但是 Service 是通过 endpoints 和 Pod 进行绑定的,所以看看这个 CoreDNS 的 endpoints 是否存在,及信息是否正确:

  118. 1
  119. 2
  120. 3
  121. $ kubectl get endpoints kube-dns -n kube-system
  122. NAME       ENDPOINTS                                      
  123. kube-dns   10.244.0.21:53,d10.244.2.82:53,10.244.0.21:9153
  124. 可以看到 endpoints 配置也是正常的,正确的与两个 CporeDNS Pod 进行了关联。

  125. 经过上面一系列检测 CoreDNS 组件确实是正常运行。接下来,观察 CoreDNS 域名解析日志,进而确定 Pod 中的域名解析请求是否能够正常进入 CoreDNS。

  126. 4. 观察 CoreDNS 域名解析日志信息
  127. 使用 kubectl edit 命令来修改存储于 Kubernetes ConfigMap 中的 CoreDNS 配置参数信息,添加 log 参数,让 CoreDNS 日志中显示域名解析信息:

  128. CoreDNS 配置参数说明:

  129. errors: 输出错误信息到控制台。
  130. health:CoreDNS 进行监控检测,检测地址为 http://localhost:8080/health 如果状态为不健康则让 Pod 进行重启。
  131. ready: 全部插件已经加载完成时,将通过 endpoints 在 8081 端口返回 HTTP 状态 200。
  132. kubernetes:CoreDNS 将根据 Kubernetes 服务和 pod 的 IP 回复 DNS 查询。
  133. prometheus:是否开启 CoreDNS Metrics 信息接口,如果配置则开启,接口地址为 http://localhost:9153/metrics
  134. forward:任何不在Kubernetes 集群内的域名查询将被转发到预定义的解析器 (/etc/resolv.conf)。
  135. cache:启用缓存,30 秒 TTL。
  136. loop:检测简单的转发循环,如果找到循环则停止 CoreDNS 进程。
  137. reload:监听 CoreDNS 配置,如果配置发生变化则重新加载配置。
  138. loadbalance:DNS 负载均衡器,默认 round_robin。
  139. 1
  140. 2
  141. 3
  142. 4
  143. 5
  144. 6
  145. 7
  146. 8
  147. 9
  148. 10
  149. 11
  150. 12
  151. 13
  152. 14
  153. 15
  154. 16
  155. 17
  156. 18
  157. 19
  158. 20
  159. 21
  160. 22
  161. 23
  162. 24
  163. 25
  164. # 编辑 coredns 配置
  165. $ kubectl edit configmap coredns -n kube-system

  166. apiVersion: v1
  167. data:
  168.   Corefile: |
  169.     .:53 {
  170.         log            #添加log
  171.         errors
  172.         health {
  173.            lameduck 5s
  174.         }
  175.         ready
  176.         kubernetes cluster.local in-addr.arpa ip6.arpa {
  177.            pods insecure
  178.            fallthrough in-addr.arpa ip6.arpa
  179.            ttl 30
  180.         }
  181.         prometheus :9153
  182.         forward . /etc/resolv.conf
  183.         cache 30
  184.         loop
  185.         reload
  186.         loadbalance
  187.     }
  188. 保存更改后 CoreDNS 会自动重新加载配置信息,不过可能需要等上一两分钟才能将这些更改传播到 CoreDNS Pod。等一段时间后,再次查看 CoreDNS 日志:

  189. 1
  190. 2
  191. 3
  192. 4
  193. 5
  194. 6
  195. 7
  196. 8
  197. 9
  198. 10
  199. 11
  200. 12
  201. 13
  202. 14
  203. 15
  204. 16
  205. 17
  206. 18
  207. 19
  208. 20
  209. 21
  210. 22
  211. 23
  212. 24
  213. $ for p in $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name); \
  214.   do kubectl logs --namespace=kube-system $p; done

  215. .:53
  216. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  217. CoreDNS-1.6.7
  218. linux/amd64, go1.13.6, da7f65b
  219. [INFO] Reloading
  220. [INFO] plugin/health: Going into lameduck mode for 5s
  221. [INFO] 127.0.0.1:47278 - 55171 "HINFO IN 4940754309314083739.5160468069505858354. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.040844011s
  222. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  223. [INFO] Reloading complete

  224. .:53
  225. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  226. CoreDNS-1.6.7
  227. linux/amd64, go1.13.6, da7f65b
  228. [INFO] Reloading
  229. [INFO] plugin/health: Going into lameduck mode for 5s
  230. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  231. [INFO] Reloading complete
  232. [INFO] 127.0.0.1:32896 - 49064 "HINFO IN 1027842207973621585.7098421666386159336. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.044098742s
  233. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  234. [INFO] Reloading complete
  235. 可以看到 CoreDNS 已经重新加载了配置,我们再次进入 dnsuitls Pod 中执行 ping 命令:

  236. 1
  237. 2
  238. 3
  239. 4
  240. 5
  241. 6
  242. 7
  243. 8
  244. # 进入 DNSutils Pod 命令行
  245. $ kubectl exec -it dnsutils sh

  246. # 执行 ping 命令
  247. $ ping www.baidu.com

  248. # 退出 dnsutils Pod 命令行
  249. $ exit
  250. 然后,再次查看 CoreDNS 的日志信息:

  251. 1
  252. 2
  253. 3
  254. 4
  255. 5
  256. 6
  257. 7
  258. 8
  259. 9
  260. 10
  261. 11
  262. 12
  263. 13
  264. 14
  265. 15
  266. 16
  267. 17
  268. 18
  269. 19
  270. 20
  271. 21
  272. 22
  273. 23
  274. 24
  275. $ for p in $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name); \
  276.   do kubectl logs --namespace=kube-system $p; done

  277. .:53
  278. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  279. CoreDNS-1.6.7
  280. linux/amd64, go1.13.6, da7f65b
  281. [INFO] Reloading
  282. [INFO] plugin/health: Going into lameduck mode for 5s
  283. [INFO] 127.0.0.1:47278 - 55171 "HINFO IN 4940754309314083739.5160468069505858354. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.040844011s
  284. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  285. [INFO] Reloading complete

  286. .:53
  287. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  288. CoreDNS-1.6.7
  289. linux/amd64, go1.13.6, da7f65b
  290. [INFO] Reloading
  291. [INFO] plugin/health: Going into lameduck mode for 5s
  292. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  293. [INFO] Reloading complete
  294. [INFO] 127.0.0.1:32896 - 49064 "HINFO IN 1027842207973621585.7098421666386159336. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.044098742s
  295. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  296. [INFO] Reloading complete
  297. 发现和之前没有执行 ping 命令时候一样,没有 DNS 域名解析的日志信息,说明 Pod 执行域名解析时,请求并没有进入 CoreDNS 中。接下来在查看 Pod 中 DNS 配置信息,进而分析问题。

  298. 5. 查看 Pod 中的 DNS 配置信息
  299. 一般 Pod 中的 DNS 策略默认为 ClusterFirst,该参数起到的作用是,优先从 Kubernetes DNS 插件地址读取 DNS 配置。所以,我们正常创建的 Pod 中,DNS 配置 DNS 服务器地址应该指定为 Kubernetes 集群的 DNS 插件 Service 提供的虚拟 IP 地址。

  300. 注:其中 DNS 策略(dnsPolicy)支持四种类型:

  301. Default: 从 DNS 所在节点继承 DNS 配置,即该 Pod 的 DNS 配置与宿主机完全一致。
  302. ClusterFirst:预先从 Kubenetes 的 DNS 插件中进行 DNS 解析,如果解析不成功,才会使用宿主机的 DNS 进行解析。
  303. ClusterFirstWithHostNet:Pod 是用 HOST 模式启动的(hostnetwork),用 HOST 模式表示 Pod 中的所有容器,都使用宿主机的 /etc/resolv.conf 配置进行 DNS 解析,但如果使用了 HOST 模式,还继续使用 Kubernetes 的 DNS 服务,那就将 dnsPolicy 设置为 ClusterFirstWithHostNet。
  304. None:完全忽略 kubernetes 系统提供的 DNS,以 Pod Spec 中 dnsConfig 配置为主。
  305. 为了再分析原因,我们接着进入 dnsutils Pod 中,查看 Pod 中 DNS 配置文件 /etc/resolv.conf 配置参数是否正确:

  306. resolv.conf 配置参数说明:

  307. search: 指明域名查询顺序。
  308. nameserver: 指定 DNS 服务器的 IP 地址,可以配置多个 nameserver。
  309. 1
  310. 2
  311. 3
  312. 4
  313. 5
  314. 6
  315. 7
  316. 8
  317. 9
  318. 10
  319. 11
  320. 12
  321. # 进入 dnsutils Pod 内部 sh 命令行
  322. $ kubectl exec -it dnsutils sh

  323. # 查看 resolv.conf 配置文件
  324. $ cat /etc/resolv.conf

  325. nameserver 10.96.0.10
  326. search kube-system.svc.cluster.local svc.cluster.local cluster.local
  327. options ndots:5

  328. # 退出 DNSutils Pod 命令行
  329. $ exit
  330. 可以看到 Pod 内部的 resolv.conf 内容,其中 nameserver 指定 DNS 解析服务器 IP 为 “10.96.0.10” ,这个 IP 地址正是本人 Kubernetes 集群 CoreDNS 的 Service “kube-dns” 的 cluterIP,说明当 Pod 内部进行域名解析时,确实是将查询请求发送到 Service “kube-dns” 提供的虚拟 IP 进行域名解析。

  331. 那么,既然 Pod 中 DNS 配置文件没问题,且 CoreDNS 也没问题,会不会是 Pod 本身域名解析不正常呢?或者 Service “kube-dns” 是否能够正常转发域名解析请求到 CoreDNS Pod 中?

  332. 当然,猜想是没有用的,进行一下测试来观察问题到底出在哪里。

  333. 6. 进行观察来定位问题所在
  334. 上面怀疑是 Pod 本身解析域名有问题,不能正常解析域名。或者 Pod 没问题,但是请求域名解析时将请求发送到 Service “kube-dns” 后不能正常转发请求到 CoreDNS Pod。 为了验证这两点,我们可以修改 Pod 中的 /etc/resolv.conf 配置来进行测试验证。

  335. 修改 resolv.conf 中 DNS 解析请求地址为 阿里云 DNS 服务器地址,然后执行 ping 命令验证是否为 Pod 解析域名是否有问题:

  336. 1
  337. 2
  338. 3
  339. 4
  340. 5
  341. 6
  342. 7
  343. 8
  344. 9
  345. 10
  346. 11
  347. 12
  348. 13
  349. 14
  350. 15
  351. 16
  352. 17
  353. 18
  354. 19
  355. 20
  356. # 进入 dnsutils Pod 内部 sh 命令行
  357. $ kubectl exec -it dnsutils /bin/sh -n kube-system

  358. ## 编辑 /etc/resolv.conf 文件,修改 nameserver 参数为阿里云提供的 DNS 服务器地址
  359. $ vi /etc/resolv.conf

  360. nameserver 223.5.5.5
  361. #nameserver 10.96.0.10
  362. search kube-system.svc.cluster.local svc.cluster.local cluster.local
  363. options ndots:5

  364. # 修改完后再进行 ping 命令测试,看看是否能够解析 www.baidu.com 网址
  365. $ ping www.baidu.com

  366. PING www.a.shifen.com (180.101.49.11) 56(84) bytes of data.
  367. 64 bytes from 180.101.49.11 (180.101.49.11): icmp_seq=1 ttl=48 time=14.0 ms
  368. 64 bytes from 180.101.49.11 (180.101.49.11): icmp_seq=2 ttl=48 time=14.0 ms

  369. # 退出 DNSutils Pod 命令行
  370. $ exit
  371. 上面可也观察到 Pod 中更换 DNS 服务器地址后,域名解析正常,说明 Pod 本身域名解析是没有问题的。

  372. 接下来再修改 resolv.conf 中 DNS 解析请求地址为 CoreDNS Pod 的 IP 地址,这样让 Pod 直接连接 CoreDNS Pod 的 IP,而不通过 Service 进行转发,再进行 ping 命令测试,进而判断 Service kube-dns 是否能够正常转发请求到 CoreDNS Pod 的问题:

  373. 1
  374. 2
  375. 3
  376. 4
  377. 5
  378. 6
  379. 7
  380. 8
  381. 9
  382. 10
  383. 11
  384. 12
  385. 13
  386. 14
  387. 15
  388. 16
  389. 17
  390. 18
  391. 19
  392. 20
  393. 21
  394. 22
  395. 23
  396. 24
  397. 25
  398. 26
  399. 27
  400. 28
  401. 29
  402. 30
  403. 31
  404. 32
  405. 33
  406. 34
  407. 35
  408. 36
  409. 37
  410. 38
  411. 39
  412. 40
  413. 41
  414. 42
  415. 43
  416. 44
  417. 45
  418. 46
  419. 47
  420. 48
  421. 49
  422. 50
  423. 51
  424. 52
  425. 53
  426. 54
  427. 55
  428. 56
  429. 57
  430. 58
  431. 59
  432. 60
  433. 61
  434. # 查看 CoreDNS Pod 的 IP 地址
  435. $ kubectl get pods -n kube-system -o wide | grep coredns

  436. coredns-669f77d7cc-rss5f     1/1     Running   0     10.244.2.155   k8s-node-2-13
  437. coredns-669f77d7cc-rt8l6     1/1     Running   0     10.244.1.163   k8s-node-2-12

  438. ## 进入 dnsutils Pod 内部 sh 命令行
  439. $ kubectl exec -it dnsutils /bin/sh -n kube-system

  440. ## 编辑 /etc/resolv.conf 文件,修改 nameserver 参数为阿里云提供的 DNS 服务器地址
  441. $ vi /etc/resolv.conf

  442. nameserver 10.244.2.155
  443. nameserver 10.244.1.163
  444. #nameserver 10.96.0.10
  445. search kube-system.svc.cluster.local svc.cluster.local cluster.local
  446. options ndots:5

  447. # 修改完后再进行 ping 命令测试,看看是否能够解析 www.baidu.com 网址
  448. $ ping www.baidu.com

  449. PING www.baidu.com (39.156.66.18): 56 data bytes
  450. 64 bytes from 39.156.66.18: seq=0 ttl=127 time=6.054 ms
  451. 64 bytes from 39.156.66.18: seq=1 ttl=127 time=4.678 ms

  452. # 退出 DNSutils Pod 命令行
  453. $ exit

  454. # 观察 CoreDNS 日志信息,查看有无域名解析相关日志
  455. $ for p in $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name); \
  456.   do kubectl logs --namespace=kube-system $p; done

  457. .:53
  458. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  459. CoreDNS-1.6.7
  460. linux/amd64, go1.13.6, da7f65b
  461. [INFO] Reloading
  462. [INFO] plugin/health: Going into lameduck mode for 5s
  463. [INFO] 127.0.0.1:47278 - 55171 "HINFO IN 4940754309314083739.5160468069505858354. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.040844011s
  464. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  465. [INFO] Reloading complete
  466. [INFO] 10.244.1.162:40261 - 21083 "AAAA IN www.baidu.com.kube-system.svc.cluster.local. udp 62 false 512" NXDOMAIN qr,aa,rd 155 0.000398875s
  467. [INFO] 10.244.1.162:40261 - 20812 "A IN www.baidu.com.kube-system.svc.cluster.local. udp 62 false 512" NXDOMAIN qr,aa,rd 155 0.000505793s
  468. [INFO] 10.244.1.162:55066 - 53460 "AAAA IN www.baidu.com.svc.cluster.local. udp 50 false 512" NXDOMAIN qr,aa,rd 143 0.000215384s
  469. [INFO] 10.244.1.162:55066 - 53239 "A IN www.baidu.com.svc.cluster.local. udp 50 false 512" NXDOMAIN qr,aa,rd 143 0.000267642s

  470. .:53
  471. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  472. CoreDNS-1.6.7
  473. linux/amd64, go1.13.6, da7f65b
  474. [INFO] Reloading
  475. [INFO] plugin/health: Going into lameduck mode for 5s
  476. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  477. [INFO] Reloading complete
  478. [INFO] 127.0.0.1:32896 - 49064 "HINFO IN 1027842207973621585.7098421666386159336. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.044098742s
  479. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  480. [INFO] Reloading complete
  481. [INFO] 10.244.1.162:40261 - 21083 "AAAA IN www.baidu.com.kube-system.svc.cluster.local. udp 62 false 512" NXDOMAIN qr,aa,rd 155 0.000217299s
  482. [INFO] 10.244.1.162:40261 - 20812 "A IN www.baidu.com.kube-system.svc.cluster.local. udp 62 false 512" NXDOMAIN qr,aa,rd 155 0.000264552s
  483. [INFO] 10.244.1.162:55066 - 53460 "AAAA IN www.baidu.com.svc.cluster.local. udp 50 false 512" NXDOMAIN qr,aa,rd 143 0.000144795s
  484. [INFO] 10.244.1.162:55066 - 53239 "A IN www.baidu.com.svc.cluster.local. udp 50 false 512" NXDOMAIN qr,aa,rd 143 0.000221163s
  485. 经过上面两个测试,已经可以得知,如果 Pod DNS 配置中直接修改 DNS 服务器地址为 CoreDNS Pod 的 IP 地址,DNS 解析确实没有问题,能够正常解析。不过,正常的情况下 Pod 中 DNS 配置的服务器地址一般是 CoreDNS 的 Service 地址,不直接绑定 Pod IP(因为 Pod 每次重启 IP 都会发生变化)。 所以问题找到了,正是在 Pod 向 CoreDNS 的 Service “kube-dns” 进行域名解析请求转发时,出现了问题,一般 Service 的问题都跟 Kube-proxy 组件有关,接下来观察该组件是否存在问题。

  486. 7. 分析 Kube-Proxy 是否存在问题
  487. 观察 Kube-proxy 的日志,查看是否存在问题:

  488. 1
  489. 2
  490. 3
  491. 4
  492. 5
  493. 6
  494. 7
  495. 8
  496. 9
  497. 10
  498. 11
  499. 12
  500. 13
  501. 14
  502. # 查看 kube-proxy Pod 列表
  503. $ kubectl get pods -n kube-system | grep kube-proxy

  504. kube-proxy-6kdj2          1/1     Running   3          9h
  505. kube-proxy-lw2q6          1/1     Running   3          9h
  506. kube-proxy-mftlt          1/1     Running   3          9h
  507. 选择一个 kube-proxy Pod,查看最后 5 条日志内容
  508. $ kubectl logs kube-proxy-6kdj2 --tail=5  -n kube-system

  509. E0326 15:20:23.159364  1 proxier.go:1950] Failed to list IPVS destinations, error: parseIP Error ip=[10 96 0 10 0 0 0 0 0 0 0 0 0 0 0 0]
  510. E0326 15:20:23.159388  1 proxier.go:1192] Failed to sync endpoint for service: 10.8.0.10:53/UPD, err: parseIP Error ip=[10 96 0 16 0 0 0 0 0 0 0 0 0 0 0 0]
  511. E0326 15:20:23.159479  1 proxier.go:1950] Failed to list IPVS destinations, error: parseIP Error ip=[10 96 0 10 0 0 0 0 0 0 0 0 0 0 0 0]
  512. E0326 15:20:23.159501  1 proxier.go:1192] Failed to sync endpoint for service: 10.8.0.10:53/TCP, err: parseIP Error ip=[10 96 0 16 0 0 0 0 0 0 0 0 0 0 0 0]
  513. E0326 15:20:23.159595  1 proxier.go:1950] Failed to list IPVS destinations, error: parseIP Error ip=[10 96 0 10 0 0 0 0 0 0 0 0 0 0 0 0]
  514. 通过 kube-proxy Pod 的日志可以看到,里面有很多 Error 级别的日志信息,根据关键字 IPVS、parseIP Error 可知,可能是由于 IPVS 模块对 IP 进行格式化导致出现问题。

  515. 因为这个问题是升级到 kubernetes 1.18 版本才出现的,所以去 Kubernetes Github 查看相关 issues,发现有人在升级 Kubernetes 版本到 1.18 后,也遇见了相同的问题,经过 issue 中 Kubernetes 维护人员讨论,分析出原因可能为新版 Kubernetes 使用的 IPVS 模块是比较新的,需要系统内核版本支持,本人使用的是 CentOS 系统,内核版本为 3.10,里面的 IPVS 模块比较老旧,缺少新版 Kubernetes IPVS 所需的依赖。

  516. 根据该 issue 讨论结果,解决该问题的办法是,更新内核为新的版本。

  517. 注:该 issues 地址为 https://github.com/kubernetes/kubernetes/issues/89520

  518. 解决问题
  519. 升级系统内核版本
  520. 升级 Kubernetes 集群各个节点的 CentOS 系统内核版本:

  521. 1
  522. 2
  523. 3
  524. 4
  525. 5
  526. 6
  527. 7
  528. 8
  529. 9
  530. 10
  531. 11
  532. 12
  533. 13
  534. 14
  535. 15
  536. 16
  537. 17
  538. 18
  539. 19
  540. 20
  541. 21
  542. 22
  543. 23
  544. 24
  545. # 载入公钥
  546. $ rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org

  547. # 安装 ELRepo 最新版本
  548. $ yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm

  549. # 列出可以使用的 kernel 包版本
  550. $ yum list available --disablerepo=* --enablerepo=elrepo-kernel

  551. # 安装指定的 kernel 版本:
  552. $ yum install -y kernel-lt-4.4.222-1.el7.elrepo --enablerepo=elrepo-kernel

  553. # 查看系统可用内核
  554. $ cat /boot/grub2/grub.cfg | grep menuentry

  555. menuentry 'CentOS Linux (3.10.0-1062.el7.x86_64) 7 (Core)' --class centos (略)
  556. menuentry 'CentOS Linux (4.4.222-1.el7.elrepo.x86_64) 7 (Core)' --class centos ...(略)

  557. # 设置开机从新内核启动
  558. $ grub2-set-default "CentOS Linux (4.4.222-1.el7.elrepo.x86_64) 7 (Core)"

  559. # 查看内核启动项
  560. $ grub2-editenv list
  561. saved_entry=CentOS Linux (4.4.222-1.el7.elrepo.x86_64) 7 (Core)
  562. 重启系统使内核生效,启动完成查看内核版本是否更新:

  563. 1
  564. 2
  565. $ uname -r
  566. 4.4.222-1.el7.elrepo.x86_64
  567. 测试 Pod 中 DNS 是否能够正常解析
  568. 进入 Pod 内部使用 ping 命令测试 DNS 是否能正常解析:

  569. 1
  570. 2
  571. 3
  572. 4
  573. 5
  574. 6
  575. 7
  576. 8
  577. 9
  578. 10
  579. 11
  580. 12
  581. 13
  582. 14
  583. # 进入 dnsutils Pod 内部 sh 命令行
  584. $ kubectl exec -it dnsutils /bin/sh -n kube-system

  585. # Ping 集群外部,例如这里 ping 一下百度
  586. $ ping www.baidu.com
  587. 64 bytes from 39.156.66.14 (39.156.66.14): icmp_seq=1 ttl=127 time=7.20 ms
  588. 64 bytes from 39.156.66.14 (39.156.66.14): icmp_seq=2 ttl=127 time=6.60 ms
  589. 64 bytes from 39.156.66.14 (39.156.66.14): icmp_seq=3 ttl=127 time=6.38 ms

  590. # Ping 集群内部 kube-api 的 Service 地址
  591. $ ping kubernetes.default
  592. 64 bytes from kubernetes.default.svc.cluster.local (10.96.0.1): icmp_seq=1 ttl=64 time=0.051 ms
  593. 64 bytes from kubernetes.default.svc.cluster.local (10.96.0.1): icmp_seq=2 ttl=64 time=0.051 ms
  594. 64 bytes from kubernetes.default.svc.cluster.local (10.96.0.1): icmp_seq=3 ttl=64 time=0.064 ms
  595. 可以看到 Pod 中的域名解析已经恢复正常。环境现象
  596. CoreDNS 版本:1.6.7
  597. Docker 版本:18.06.3-ce
  598. Kubernetes 版本:1.18.1
  599. 操作系统版本:CentOS 7.x
  600. CentOS 内核版本:3.10.0-693.2.2.el7.x86_64

  601. 问题现象
  602. 由于最近要向组内演示 Istio 1.5,故在云服务器上安装了kubernetes 1.18.1 (使用ipvs) 来配合 Istio 1.5 的演示,kubernetes 与 istio 安装完后一切顺利,bookinfo demo跑的也非常的顺利。但在一次重启整个集群后,一切都变的不那么美好了。istio-proxy起不来了,提示pilot not ready,更可悲的是service name 无法解析了,导致很多服务之间的调用都没法正常工作,有依赖的服务都不能正常启动了,为了更好的定位问题,于是卸载 Istio 1.5,重新回到k8s 1.18.1上,在一步步排查中发现,在pod中使用pod ip相互访问是可以的,由此判断,初步怀疑很可能是 DNS 出现了问题,后来慢慢发现 kube-proxy 中的错误,再定位到 IPVS parseIP Error 错误,再到解决问题。以下是整个问题定位分析

  603. 问题定位
  604. 为了更好的重现问题,我重新安装了一套新的 kubernetes 1.18.1,安装完后验证一切都是ok,接下来我就重启整个集群,问题就产生了,在pod中无法解析service name了,所有的pod运行都是ok的,一切都变的”很神奇”,好吧,开启定位之旅。

  605. 部署DNS调试工具
  606. 为了探针是否为 DNS 问题,这里需要提前部署用于测试 DNS 问题的 dnsutils 镜像,该镜像中包含了用于测试 DNS 问题的工具包,非常利于我们分析与发现问题。

  607. 部署 ndsutils.yaml

  608. 1
  609. 2
  610. 3
  611. 4
  612. 5
  613. 6
  614. 7
  615. 8
  616. 9
  617. 10
  618. apiVersion: v1
  619. kind: Pod
  620. metadata:
  621.   name: dnsutils
  622. spec:
  623.   containers:
  624.   - name: dnsutils
  625.     image: mydlqclub/dnsutils:1.3
  626.     imagePullPolicy: IfNotPresent
  627.     command: ["sleep","3600"]
  628. 问题分析
  629. 1. 进入 DNS 工具 Pod 的命令行
  630. 1
  631. kubectl exec -it dnsutils sh
  632. 2. 通过 Ping 和 Nsloopup 命令测试
  633. 1
  634. 2
  635. 3
  636. 4
  637. 5
  638. 6
  639. 7
  640. 8
  641. 9
  642. 10
  643. 11
  644. 12
  645. 13
  646. 14
  647. 15
  648. 16
  649. 17
  650. 18
  651. 19
  652. 20
  653. 21
  654. # Ping 集群外部,例如这里 ping 一下百度
  655. $ ping www.baidu.com
  656. ping: bad address 'www.baidu.com'

  657. # Ping 集群内部 kube-apiserver 的 Service 地址
  658. $ ping kubernetes.default
  659. ping: bad address 'kubernetes.default'

  660. # 使用 nslookup 命令查询域名信息
  661. $ nslookup kubernetes.default
  662. ;; connection timed out; no servers could be reached

  663. # 直接 Ping 集群内部 kube-apiserver 的 IP 地址
  664. $ ping 10.96.0.1
  665. PING 10.96.0.1 (10.96.0.1): 56 data bytes
  666. 64 bytes from 10.96.0.1: seq=0 ttl=64 time=0.096 ms
  667. 64 bytes from 10.96.0.1: seq=1 ttl=64 time=0.050 ms
  668. 64 bytes from 10.96.0.1: seq=2 ttl=64 time=0.068 ms

  669. # 退出 dnsutils Pod 命令行
  670. $ exit
  671. 可以观察到两次 ping 域名都不能 ping 通,且使用 nsloopup 分析域名信息时超时。然而,使用 ping kube-apiserver 的 IP 地址 “10.96.0.1” 则可以正常通信,所以,排除网络插件(flannel、calico 等)的问题。初步判断,很可能是 CoreDNS 组件的错误引起的某些问题,所以接下来我们测试 CoreDNS 是否正常。

  672. 3. 检测 CoreDNS 应用是否正常运行
  673. 1
  674. 2
  675. 3
  676. 4
  677. $ kubectl get pods -l k8s-app=kube-dns -n kube-system
  678. NAME                       READY   STATUS    RESTARTS   AGE
  679. coredns-669f77d7cc-8pkpw   1/1     Running   2          6h5m
  680. coredns-669f77d7cc-jk9wk   1/1     Running   2          6h5m
  681. 可也看到 CoreDNS 两个 Pod 均正常启动,所以再查看两个 Pod 中的日志信息,看看有无错误日志:

  682. 1
  683. 2
  684. 3
  685. 4
  686. 5
  687. 6
  688. 7
  689. 8
  690. 9
  691. 10
  692. 11
  693. $ for p in $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name); \
  694.   do kubectl logs --namespace=kube-system $p; done

  695. .:53
  696. [INFO] plugin/reload: Running configuration MD5 = 4e235fcc3696966e76816bcd9034ebc7
  697. CoreDNS-1.6.7
  698. linux/amd64, go1.13.6, da7f65b
  699. .:53
  700. [INFO] plugin/reload: Running configuration MD5 = 4e235fcc3696966e76816bcd9034ebc7
  701. CoreDNS-1.6.7
  702. linux/amd64, go1.13.6, da7f65b
  703. 通过上面信息可以观察到,日志中信息也是正常启动没有问题。再接下来,查看下 CoreDNS 的入口 Service “kube-dns” 是否存在:

  704. kube-dns 的 IP 为 10.96.0.10,集群内的 Pod 都是通过该 IP 与 DNS 组件进行交互,查询 DNS 信息。

  705. 1
  706. 2
  707. 3
  708. $ kubectl get service -n kube-system | grep kube-dns
  709. NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)               
  710. kube-dns                    ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP,9153/TCP
  711. 上面显示 Service “kube-dns” 也存在,但是 Service 是通过 endpoints 和 Pod 进行绑定的,所以看看这个 CoreDNS 的 endpoints 是否存在,及信息是否正确:

  712. 1
  713. 2
  714. 3
  715. $ kubectl get endpoints kube-dns -n kube-system
  716. NAME       ENDPOINTS                                      
  717. kube-dns   10.244.0.21:53,d10.244.2.82:53,10.244.0.21:9153
  718. 可以看到 endpoints 配置也是正常的,正确的与两个 CporeDNS Pod 进行了关联。

  719. 经过上面一系列检测 CoreDNS 组件确实是正常运行。接下来,观察 CoreDNS 域名解析日志,进而确定 Pod 中的域名解析请求是否能够正常进入 CoreDNS。

  720. 4. 观察 CoreDNS 域名解析日志信息
  721. 使用 kubectl edit 命令来修改存储于 Kubernetes ConfigMap 中的 CoreDNS 配置参数信息,添加 log 参数,让 CoreDNS 日志中显示域名解析信息:

  722. CoreDNS 配置参数说明:

  723. errors: 输出错误信息到控制台。
  724. health:CoreDNS 进行监控检测,检测地址为 http://localhost:8080/health 如果状态为不健康则让 Pod 进行重启。
  725. ready: 全部插件已经加载完成时,将通过 endpoints 在 8081 端口返回 HTTP 状态 200。
  726. kubernetes:CoreDNS 将根据 Kubernetes 服务和 pod 的 IP 回复 DNS 查询。
  727. prometheus:是否开启 CoreDNS Metrics 信息接口,如果配置则开启,接口地址为 http://localhost:9153/metrics
  728. forward:任何不在Kubernetes 集群内的域名查询将被转发到预定义的解析器 (/etc/resolv.conf)。
  729. cache:启用缓存,30 秒 TTL。
  730. loop:检测简单的转发循环,如果找到循环则停止 CoreDNS 进程。
  731. reload:监听 CoreDNS 配置,如果配置发生变化则重新加载配置。
  732. loadbalance:DNS 负载均衡器,默认 round_robin。
  733. 1
  734. 2
  735. 3
  736. 4
  737. 5
  738. 6
  739. 7
  740. 8
  741. 9
  742. 10
  743. 11
  744. 12
  745. 13
  746. 14
  747. 15
  748. 16
  749. 17
  750. 18
  751. 19
  752. 20
  753. 21
  754. 22
  755. 23
  756. 24
  757. 25
  758. # 编辑 coredns 配置
  759. $ kubectl edit configmap coredns -n kube-system

  760. apiVersion: v1
  761. data:
  762.   Corefile: |
  763.     .:53 {
  764.         log            #添加log
  765.         errors
  766.         health {
  767.            lameduck 5s
  768.         }
  769.         ready
  770.         kubernetes cluster.local in-addr.arpa ip6.arpa {
  771.            pods insecure
  772.            fallthrough in-addr.arpa ip6.arpa
  773.            ttl 30
  774.         }
  775.         prometheus :9153
  776.         forward . /etc/resolv.conf
  777.         cache 30
  778.         loop
  779.         reload
  780.         loadbalance
  781.     }
  782. 保存更改后 CoreDNS 会自动重新加载配置信息,不过可能需要等上一两分钟才能将这些更改传播到 CoreDNS Pod。等一段时间后,再次查看 CoreDNS 日志:

  783. 1
  784. 2
  785. 3
  786. 4
  787. 5
  788. 6
  789. 7
  790. 8
  791. 9
  792. 10
  793. 11
  794. 12
  795. 13
  796. 14
  797. 15
  798. 16
  799. 17
  800. 18
  801. 19
  802. 20
  803. 21
  804. 22
  805. 23
  806. 24
  807. $ for p in $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name); \
  808.   do kubectl logs --namespace=kube-system $p; done

  809. .:53
  810. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  811. CoreDNS-1.6.7
  812. linux/amd64, go1.13.6, da7f65b
  813. [INFO] Reloading
  814. [INFO] plugin/health: Going into lameduck mode for 5s
  815. [INFO] 127.0.0.1:47278 - 55171 "HINFO IN 4940754309314083739.5160468069505858354. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.040844011s
  816. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  817. [INFO] Reloading complete

  818. .:53
  819. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  820. CoreDNS-1.6.7
  821. linux/amd64, go1.13.6, da7f65b
  822. [INFO] Reloading
  823. [INFO] plugin/health: Going into lameduck mode for 5s
  824. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  825. [INFO] Reloading complete
  826. [INFO] 127.0.0.1:32896 - 49064 "HINFO IN 1027842207973621585.7098421666386159336. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.044098742s
  827. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  828. [INFO] Reloading complete
  829. 可以看到 CoreDNS 已经重新加载了配置,我们再次进入 dnsuitls Pod 中执行 ping 命令:

  830. 1
  831. 2
  832. 3
  833. 4
  834. 5
  835. 6
  836. 7
  837. 8
  838. # 进入 DNSutils Pod 命令行
  839. $ kubectl exec -it dnsutils sh

  840. # 执行 ping 命令
  841. $ ping www.baidu.com

  842. # 退出 dnsutils Pod 命令行
  843. $ exit
  844. 然后,再次查看 CoreDNS 的日志信息:

  845. 1
  846. 2
  847. 3
  848. 4
  849. 5
  850. 6
  851. 7
  852. 8
  853. 9
  854. 10
  855. 11
  856. 12
  857. 13
  858. 14
  859. 15
  860. 16
  861. 17
  862. 18
  863. 19
  864. 20
  865. 21
  866. 22
  867. 23
  868. 24
  869. $ for p in $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name); \
  870.   do kubectl logs --namespace=kube-system $p; done

  871. .:53
  872. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  873. CoreDNS-1.6.7
  874. linux/amd64, go1.13.6, da7f65b
  875. [INFO] Reloading
  876. [INFO] plugin/health: Going into lameduck mode for 5s
  877. [INFO] 127.0.0.1:47278 - 55171 "HINFO IN 4940754309314083739.5160468069505858354. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.040844011s
  878. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  879. [INFO] Reloading complete

  880. .:53
  881. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  882. CoreDNS-1.6.7
  883. linux/amd64, go1.13.6, da7f65b
  884. [INFO] Reloading
  885. [INFO] plugin/health: Going into lameduck mode for 5s
  886. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  887. [INFO] Reloading complete
  888. [INFO] 127.0.0.1:32896 - 49064 "HINFO IN 1027842207973621585.7098421666386159336. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.044098742s
  889. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  890. [INFO] Reloading complete
  891. 发现和之前没有执行 ping 命令时候一样,没有 DNS 域名解析的日志信息,说明 Pod 执行域名解析时,请求并没有进入 CoreDNS 中。接下来在查看 Pod 中 DNS 配置信息,进而分析问题。

  892. 5. 查看 Pod 中的 DNS 配置信息
  893. 一般 Pod 中的 DNS 策略默认为 ClusterFirst,该参数起到的作用是,优先从 Kubernetes DNS 插件地址读取 DNS 配置。所以,我们正常创建的 Pod 中,DNS 配置 DNS 服务器地址应该指定为 Kubernetes 集群的 DNS 插件 Service 提供的虚拟 IP 地址。

  894. 注:其中 DNS 策略(dnsPolicy)支持四种类型:

  895. Default: 从 DNS 所在节点继承 DNS 配置,即该 Pod 的 DNS 配置与宿主机完全一致。
  896. ClusterFirst:预先从 Kubenetes 的 DNS 插件中进行 DNS 解析,如果解析不成功,才会使用宿主机的 DNS 进行解析。
  897. ClusterFirstWithHostNet:Pod 是用 HOST 模式启动的(hostnetwork),用 HOST 模式表示 Pod 中的所有容器,都使用宿主机的 /etc/resolv.conf 配置进行 DNS 解析,但如果使用了 HOST 模式,还继续使用 Kubernetes 的 DNS 服务,那就将 dnsPolicy 设置为 ClusterFirstWithHostNet。
  898. None:完全忽略 kubernetes 系统提供的 DNS,以 Pod Spec 中 dnsConfig 配置为主。
  899. 为了再分析原因,我们接着进入 dnsutils Pod 中,查看 Pod 中 DNS 配置文件 /etc/resolv.conf 配置参数是否正确:

  900. resolv.conf 配置参数说明:

  901. search: 指明域名查询顺序。
  902. nameserver: 指定 DNS 服务器的 IP 地址,可以配置多个 nameserver。
  903. 1
  904. 2
  905. 3
  906. 4
  907. 5
  908. 6
  909. 7
  910. 8
  911. 9
  912. 10
  913. 11
  914. 12
  915. # 进入 dnsutils Pod 内部 sh 命令行
  916. $ kubectl exec -it dnsutils sh

  917. # 查看 resolv.conf 配置文件
  918. $ cat /etc/resolv.conf

  919. nameserver 10.96.0.10
  920. search kube-system.svc.cluster.local svc.cluster.local cluster.local
  921. options ndots:5

  922. # 退出 DNSutils Pod 命令行
  923. $ exit
  924. 可以看到 Pod 内部的 resolv.conf 内容,其中 nameserver 指定 DNS 解析服务器 IP 为 “10.96.0.10” ,这个 IP 地址正是本人 Kubernetes 集群 CoreDNS 的 Service “kube-dns” 的 cluterIP,说明当 Pod 内部进行域名解析时,确实是将查询请求发送到 Service “kube-dns” 提供的虚拟 IP 进行域名解析。

  925. 那么,既然 Pod 中 DNS 配置文件没问题,且 CoreDNS 也没问题,会不会是 Pod 本身域名解析不正常呢?或者 Service “kube-dns” 是否能够正常转发域名解析请求到 CoreDNS Pod 中?

  926. 当然,猜想是没有用的,进行一下测试来观察问题到底出在哪里。

  927. 6. 进行观察来定位问题所在
  928. 上面怀疑是 Pod 本身解析域名有问题,不能正常解析域名。或者 Pod 没问题,但是请求域名解析时将请求发送到 Service “kube-dns” 后不能正常转发请求到 CoreDNS Pod。 为了验证这两点,我们可以修改 Pod 中的 /etc/resolv.conf 配置来进行测试验证。

  929. 修改 resolv.conf 中 DNS 解析请求地址为 阿里云 DNS 服务器地址,然后执行 ping 命令验证是否为 Pod 解析域名是否有问题:

  930. 1
  931. 2
  932. 3
  933. 4
  934. 5
  935. 6
  936. 7
  937. 8
  938. 9
  939. 10
  940. 11
  941. 12
  942. 13
  943. 14
  944. 15
  945. 16
  946. 17
  947. 18
  948. 19
  949. 20
  950. # 进入 dnsutils Pod 内部 sh 命令行
  951. $ kubectl exec -it dnsutils /bin/sh -n kube-system

  952. ## 编辑 /etc/resolv.conf 文件,修改 nameserver 参数为阿里云提供的 DNS 服务器地址
  953. $ vi /etc/resolv.conf

  954. nameserver 223.5.5.5
  955. #nameserver 10.96.0.10
  956. search kube-system.svc.cluster.local svc.cluster.local cluster.local
  957. options ndots:5

  958. # 修改完后再进行 ping 命令测试,看看是否能够解析 www.baidu.com 网址
  959. $ ping www.baidu.com

  960. PING www.a.shifen.com (180.101.49.11) 56(84) bytes of data.
  961. 64 bytes from 180.101.49.11 (180.101.49.11): icmp_seq=1 ttl=48 time=14.0 ms
  962. 64 bytes from 180.101.49.11 (180.101.49.11): icmp_seq=2 ttl=48 time=14.0 ms

  963. # 退出 DNSutils Pod 命令行
  964. $ exit
  965. 上面可也观察到 Pod 中更换 DNS 服务器地址后,域名解析正常,说明 Pod 本身域名解析是没有问题的。

  966. 接下来再修改 resolv.conf 中 DNS 解析请求地址为 CoreDNS Pod 的 IP 地址,这样让 Pod 直接连接 CoreDNS Pod 的 IP,而不通过 Service 进行转发,再进行 ping 命令测试,进而判断 Service kube-dns 是否能够正常转发请求到 CoreDNS Pod 的问题:

  967. 1
  968. 2
  969. 3
  970. 4
  971. 5
  972. 6
  973. 7
  974. 8
  975. 9
  976. 10
  977. 11
  978. 12
  979. 13
  980. 14
  981. 15
  982. 16
  983. 17
  984. 18
  985. 19
  986. 20
  987. 21
  988. 22
  989. 23
  990. 24
  991. 25
  992. 26
  993. 27
  994. 28
  995. 29
  996. 30
  997. 31
  998. 32
  999. 33
  1000. 34
  1001. 35
  1002. 36
  1003. 37
  1004. 38
  1005. 39
  1006. 40
  1007. 41
  1008. 42
  1009. 43
  1010. 44
  1011. 45
  1012. 46
  1013. 47
  1014. 48
  1015. 49
  1016. 50
  1017. 51
  1018. 52
  1019. 53
  1020. 54
  1021. 55
  1022. 56
  1023. 57
  1024. 58
  1025. 59
  1026. 60
  1027. 61
  1028. # 查看 CoreDNS Pod 的 IP 地址
  1029. $ kubectl get pods -n kube-system -o wide | grep coredns

  1030. coredns-669f77d7cc-rss5f     1/1     Running   0     10.244.2.155   k8s-node-2-13
  1031. coredns-669f77d7cc-rt8l6     1/1     Running   0     10.244.1.163   k8s-node-2-12

  1032. ## 进入 dnsutils Pod 内部 sh 命令行
  1033. $ kubectl exec -it dnsutils /bin/sh -n kube-system

  1034. ## 编辑 /etc/resolv.conf 文件,修改 nameserver 参数为阿里云提供的 DNS 服务器地址
  1035. $ vi /etc/resolv.conf

  1036. nameserver 10.244.2.155
  1037. nameserver 10.244.1.163
  1038. #nameserver 10.96.0.10
  1039. search kube-system.svc.cluster.local svc.cluster.local cluster.local
  1040. options ndots:5

  1041. # 修改完后再进行 ping 命令测试,看看是否能够解析 www.baidu.com 网址
  1042. $ ping www.baidu.com

  1043. PING www.baidu.com (39.156.66.18): 56 data bytes
  1044. 64 bytes from 39.156.66.18: seq=0 ttl=127 time=6.054 ms
  1045. 64 bytes from 39.156.66.18: seq=1 ttl=127 time=4.678 ms

  1046. # 退出 DNSutils Pod 命令行
  1047. $ exit

  1048. # 观察 CoreDNS 日志信息,查看有无域名解析相关日志
  1049. $ for p in $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name); \
  1050.   do kubectl logs --namespace=kube-system $p; done

  1051. .:53
  1052. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  1053. CoreDNS-1.6.7
  1054. linux/amd64, go1.13.6, da7f65b
  1055. [INFO] Reloading
  1056. [INFO] plugin/health: Going into lameduck mode for 5s
  1057. [INFO] 127.0.0.1:47278 - 55171 "HINFO IN 4940754309314083739.5160468069505858354. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.040844011s
  1058. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  1059. [INFO] Reloading complete
  1060. [INFO] 10.244.1.162:40261 - 21083 "AAAA IN www.baidu.com.kube-system.svc.cluster.local. udp 62 false 512" NXDOMAIN qr,aa,rd 155 0.000398875s
  1061. [INFO] 10.244.1.162:40261 - 20812 "A IN www.baidu.com.kube-system.svc.cluster.local. udp 62 false 512" NXDOMAIN qr,aa,rd 155 0.000505793s
  1062. [INFO] 10.244.1.162:55066 - 53460 "AAAA IN www.baidu.com.svc.cluster.local. udp 50 false 512" NXDOMAIN qr,aa,rd 143 0.000215384s
  1063. [INFO] 10.244.1.162:55066 - 53239 "A IN www.baidu.com.svc.cluster.local. udp 50 false 512" NXDOMAIN qr,aa,rd 143 0.000267642s

  1064. .:53
  1065. [INFO] plugin/reload: Running configuration MD5 = 6434d0912b39645ed0707a3569fd69dc
  1066. CoreDNS-1.6.7
  1067. linux/amd64, go1.13.6, da7f65b
  1068. [INFO] Reloading
  1069. [INFO] plugin/health: Going into lameduck mode for 5s
  1070. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  1071. [INFO] Reloading complete
  1072. [INFO] 127.0.0.1:32896 - 49064 "HINFO IN 1027842207973621585.7098421666386159336. udp 57 false 512" NXDOMAIN qr,rd,ra 57 0.044098742s
  1073. [INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
  1074. [INFO] Reloading complete
  1075. [INFO] 10.244.1.162:40261 - 21083 "AAAA IN www.baidu.com.kube-system.svc.cluster.local. udp 62 false 512" NXDOMAIN qr,aa,rd 155 0.000217299s
  1076. [INFO] 10.244.1.162:40261 - 20812 "A IN www.baidu.com.kube-system.svc.cluster.local. udp 62 false 512" NXDOMAIN qr,aa,rd 155 0.000264552s
  1077. [INFO] 10.244.1.162:55066 - 53460 "AAAA IN www.baidu.com.svc.cluster.local. udp 50 false 512" NXDOMAIN qr,aa,rd 143 0.000144795s
  1078. [INFO] 10.244.1.162:55066 - 53239 "A IN www.baidu.com.svc.cluster.local. udp 50 false 512" NXDOMAIN qr,aa,rd 143 0.000221163s
  1079. 经过上面两个测试,已经可以得知,如果 Pod DNS 配置中直接修改 DNS 服务器地址为 CoreDNS Pod 的 IP 地址,DNS 解析确实没有问题,能够正常解析。不过,正常的情况下 Pod 中 DNS 配置的服务器地址一般是 CoreDNS 的 Service 地址,不直接绑定 Pod IP(因为 Pod 每次重启 IP 都会发生变化)。 所以问题找到了,正是在 Pod 向 CoreDNS 的 Service “kube-dns” 进行域名解析请求转发时,出现了问题,一般 Service 的问题都跟 Kube-proxy 组件有关,接下来观察该组件是否存在问题。

  1080. 7. 分析 Kube-Proxy 是否存在问题
  1081. 观察 Kube-proxy 的日志,查看是否存在问题:

  1082. 1
  1083. 2
  1084. 3
  1085. 4
  1086. 5
  1087. 6
  1088. 7
  1089. 8
  1090. 9
  1091. 10
  1092. 11
  1093. 12
  1094. 13
  1095. 14
  1096. # 查看 kube-proxy Pod 列表
  1097. $ kubectl get pods -n kube-system | grep kube-proxy

  1098. kube-proxy-6kdj2          1/1     Running   3          9h
  1099. kube-proxy-lw2q6          1/1     Running   3          9h
  1100. kube-proxy-mftlt          1/1     Running   3          9h
  1101. 选择一个 kube-proxy Pod,查看最后 5 条日志内容
  1102. $ kubectl logs kube-proxy-6kdj2 --tail=5  -n kube-system

  1103. E0326 15:20:23.159364  1 proxier.go:1950] Failed to list IPVS destinations, error: parseIP Error ip=[10 96 0 10 0 0 0 0 0 0 0 0 0 0 0 0]
  1104. E0326 15:20:23.159388  1 proxier.go:1192] Failed to sync endpoint for service: 10.8.0.10:53/UPD, err: parseIP Error ip=[10 96 0 16 0 0 0 0 0 0 0 0 0 0 0 0]
  1105. E0326 15:20:23.159479  1 proxier.go:1950] Failed to list IPVS destinations, error: parseIP Error ip=[10 96 0 10 0 0 0 0 0 0 0 0 0 0 0 0]
  1106. E0326 15:20:23.159501  1 proxier.go:1192] Failed to sync endpoint for service: 10.8.0.10:53/TCP, err: parseIP Error ip=[10 96 0 16 0 0 0 0 0 0 0 0 0 0 0 0]
  1107. E0326 15:20:23.159595  1 proxier.go:1950] Failed to list IPVS destinations, error: parseIP Error ip=[10 96 0 10 0 0 0 0 0 0 0 0 0 0 0 0]
  1108. 通过 kube-proxy Pod 的日志可以看到,里面有很多 Error 级别的日志信息,根据关键字 IPVS、parseIP Error 可知,可能是由于 IPVS 模块对 IP 进行格式化导致出现问题。

  1109. 因为这个问题是升级到 kubernetes 1.18 版本才出现的,所以去 Kubernetes Github 查看相关 issues,发现有人在升级 Kubernetes 版本到 1.18 后,也遇见了相同的问题,经过 issue 中 Kubernetes 维护人员讨论,分析出原因可能为新版 Kubernetes 使用的 IPVS 模块是比较新的,需要系统内核版本支持,本人使用的是 CentOS 系统,内核版本为 3.10,里面的 IPVS 模块比较老旧,缺少新版 Kubernetes IPVS 所需的依赖。

  1110. 根据该 issue 讨论结果,解决该问题的办法是,更新内核为新的版本。

  1111. 注:该 issues 地址为 https://github.com/kubernetes/kubernetes/issues/89520

  1112. 解决问题
  1113. 升级系统内核版本
  1114. 升级 Kubernetes 集群各个节点的 CentOS 系统内核版本:

  1115. 1
  1116. 2
  1117. 3
  1118. 4
  1119. 5
  1120. 6
  1121. 7
  1122. 8
  1123. 9
  1124. 10
  1125. 11
  1126. 12
  1127. 13
  1128. 14
  1129. 15
  1130. 16
  1131. 17
  1132. 18
  1133. 19
  1134. 20
  1135. 21
  1136. 22
  1137. 23
  1138. 24
  1139. # 载入公钥
  1140. $ rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org

  1141. # 安装 ELRepo 最新版本
  1142. $ yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm

  1143. # 列出可以使用的 kernel 包版本
  1144. $ yum list available --disablerepo=* --enablerepo=elrepo-kernel

  1145. # 安装指定的 kernel 版本:
  1146. $ yum install -y kernel-lt-4.4.222-1.el7.elrepo --enablerepo=elrepo-kernel

  1147. # 查看系统可用内核
  1148. $ cat /boot/grub2/grub.cfg | grep menuentry

  1149. menuentry 'CentOS Linux (3.10.0-1062.el7.x86_64) 7 (Core)' --class centos (略)
  1150. menuentry 'CentOS Linux (4.4.222-1.el7.elrepo.x86_64) 7 (Core)' --class centos ...(略)

  1151. # 设置开机从新内核启动
  1152. $ grub2-set-default "CentOS Linux (4.4.222-1.el7.elrepo.x86_64) 7 (Core)"

  1153. # 查看内核启动项
  1154. $ grub2-editenv list
  1155. saved_entry=CentOS Linux (4.4.222-1.el7.elrepo.x86_64) 7 (Core)
  1156. 重启系统使内核生效,启动完成查看内核版本是否更新:

  1157. 1
  1158. 2
  1159. $ uname -r
  1160. 4.4.222-1.el7.elrepo.x86_64
  1161. 测试 Pod 中 DNS 是否能够正常解析
  1162. 进入 Pod 内部使用 ping 命令测试 DNS 是否能正常解析:

  1163. 1
  1164. 2
  1165. 3
  1166. 4
  1167. 5
  1168. 6
  1169. 7
  1170. 8
  1171. 9
  1172. 10
  1173. 11
  1174. 12
  1175. 13
  1176. 14
  1177. # 进入 dnsutils Pod 内部 sh 命令行
  1178. $ kubectl exec -it dnsutils /bin/sh -n kube-system

  1179. # Ping 集群外部,例如这里 ping 一下百度
  1180. $ ping www.baidu.com
  1181. 64 bytes from 39.156.66.14 (39.156.66.14): icmp_seq=1 ttl=127 time=7.20 ms
  1182. 64 bytes from 39.156.66.14 (39.156.66.14): icmp_seq=2 ttl=127 time=6.60 ms
  1183. 64 bytes from 39.156.66.14 (39.156.66.14): icmp_seq=3 ttl=127 time=6.38 ms

  1184. # Ping 集群内部 kube-api 的 Service 地址
  1185. $ ping kubernetes.default
  1186. 64 bytes from kubernetes.default.svc.cluster.local (10.96.0.1): icmp_seq=1 ttl=64 time=0.051 ms
  1187. 64 bytes from kubernetes.default.svc.cluster.local (10.96.0.1): icmp_seq=2 ttl=64 time=0.051 ms
  1188. 64 bytes from kubernetes.default.svc.cluster.local (10.96.0.1): icmp_seq=3 ttl=64 time=0.064 ms
  1189. 可以看到 Pod 中的域名解析已经恢复正常。
复制代码


http://team.jiunile.com/blog/2020/05/k8s-1-18-ipvs-problem.html
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表