问题描述
部分域名在宿主机可以正常访问,容器内部无法访问(周期性,偶尔可以访问, 周期大概为30s)
问题原因
宿主机dns解析列表有两个是公司的,一个可能是云添加的.宿主机使用的dns解析策略为顺序解析,公司的dns在前,因此可以正常解析.k8s的coreDns解析策略默认为随机,当解析服务器随机到云添加的解析地址时,其也可以解析,但解析出来的是外网地址(因为xxx.com不属于本公司)
问题排查
- 启动辅助容器排查网络问题
kubectl run tmp-shell --rm -i --tty --image harbor.lcdp.com:8443/library/netshoot:latest -- /bin/bash
- 容器内执行命令获取解析规律
export test_result=0
export success_count=0
export failed_count=0
while [ "" = "" ]; do
sleep 1
nslookup gitlab.xxx.com && test_result="success" || test_result="failed"
if [ "$test_result" = "success" ]; then
success_count=$(( $success_count + 1 ))
else
failed_count=$(( $failed_count + 1 ))
fi
echo -e "测试结果$test_result"
echo -e "成功:$success_count"
echo -e "失败:$failed_count"
done
- 查看容器解析列表
bash-5.1# cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 169.254.20.10
options ndots:5
- 使用nslookup查看解析服务器
bash-5.1# nslookup gitlab.xxx.com
Server: 169.254.20.10
Address: 169.254.20.10#53
Name: gitlab.xxx.com
Address: 10.33.123.37
这一步可以看到,无论解析失败还是解析成功,都是使用的169.254.20.10作为解析服务器
- 排查是否是dns服务器的问题, 使用dig命令查询
export test_result=0
export success_count=0
export failed_count=0
while [ "" = "" ]; do
sleep 1
dig @169.254.20.10 gitlab.xxx.com && test_result="success" || test_result="failed"
if [ "$test_result" = "success" ]; then
success_count=$(( $success_count + 1 ))
else
failed_count=$(( $failed_count + 1 ))
fi
echo -e "测试结果$test_result"
echo -e "成功:$success_count"
echo -e "失败:$failed_count"
done
这一步执行完可以知道,错误仍然出现,因此可以确定是dns服务器169.254.20.10的问题
-
确定169.254.20.10是从哪里来的
由于在集群内没有该ip的记录,所有服务的service基本都是172.xxx的, 上谷歌搜索, 可以看到关键字local-dns -
进入dns服务器排查问题
[root@172-16-48-9 ~]# kubectl get pod -A | grep local-dns
kube-system node-local-dns-4tlpv 1/1 Running 0 16m
kube-system node-local-dns-8kd2c 1/1 Running 0 16m
kube-system node-local-dns-zhqz6 1/1 Running 0 16m
# 进入容器(省略, 通过图形化页面辅助进入的,具体命令没试)
# cat /etc/resolv.conf
nameserver 10.1.3.50
nameserver 10.33.120.13
# Your system has been configured with 'manage-resolv-conf' set to true.
# As a result, cloud-init has written this file with configuration data
# that it has been provided. Cloud-init, by default, will write this file
# a single time (PER_ONCE).
#
nameserver 183.60.83.19
nameserver 183.60.82.98
这里可以看到解析的服务器跟宿主机是完全一致的,可以猜测该dns服务器是直接复制宿主机的dns作为备用解析的,另外应该对内部服务名做了一些特殊处理.
但这个解析列表如果是按照常的顺序解析的话,应该是没问题的,使用10.1.3.50就可以解析到gitlab.xxx.com的地址. 所以应该是dns服务器做了某些特殊策略.
遂查资料, 在文章中看到: 当宿主机上namserver有多个时,coredns内部默认采用的时random的方式随机转发,失败后就返回错误。
可以知道, dns服务器果然使用了不同于顺序解析的策略
- 验证策略
dig @10.1.3.50 gitlab.xxx.com
dig @10.33.120.13 gitlab.xxx.com
dig @183.60.83.19 gitlab.xxx.com
可以看到前两个是可以正常解析ip的,最后一个183.60.83.19不能正常解析(并不是不能解析,解析到外网了,因此可能没有触发错误策略使用另外的nameserver),因此基本可以确定就是该nameserver导致的解析错误
解决方案
将集群内所有节点的宿主机/etc/resolv.conf文件删减至两个
nameserver 10.1.3.50
nameserver 10.33.120.13
重启coredns, 并强制删除三个local-dns-cache pod.(页面操作,命令待补充)