线上业务报错,日志提示不能解析dns,so 开始排查,进入容器执行dig,发现一切正常,然后执行ping,提示:bad address.
开始排查:
1.ping 其他外网地址和内网地址一切正常
2.查看/etc/resolv.conf中配置的nameserver,并用dig @nameserver 手动指定dns服务器去解析方式发现一切正常
3.用其他容器去ping 相同地址发现一切正常,初步怀疑是容器本身问题,查看容器版本: /etc/issue ,发现容器是Alpine(已经开始慌了,因为Alpine之前在线上也遇到过其它奇奇怪怪的问题,alpine用的是musllibc)
4.抓包验证:
通过上面的信息可以看到客户端向dns服务器解析指定域名,服务端也响应了客户端的请求,但是并没有相应具体记录,在Flags中 Truncated: Message is truncated 为1,证明我们的请求被截断了,具体flags代表什么意义可以查看:https://www.ietf.org/rfc/rfc2181.txt ,查看相应资料发现只要udp请求大于512 字节就会回复截断标志。
5.为了验证我们的猜想,于是我们手动解析了一个测试域名,同时给这个域名解析了32个A记录,然后用alpine镜像去尝试ping
我们得到了相同的报错,于是我们将这个域名的A记录由原来的32个减少到2个,然后再次尝试ping
减少A记录条目后问题解决
查阅相关资料,总结以下解决方案:
1.返回的A记录应该小于512字节,如果真的要返回大量A记录,客户端应该自己实现dns(支持tcp dns的库),而不是依赖操作系统
2.减少dns返回条目
3.更换操作系统
4.解析大于512字节的记录时应使用TCP来解析dns,而不是udp(Alpine不支持tcp解析dns)
5.Alpine社区态度:应该是客户端和dns服务商来解决这个问题,而不应该是操作系统,Alpine不认为这是一个bug,而是一个特性,设置了截断标志,但是响应是空的。本质上是在强迫客户端从UDP升级到TCP,以避免易受攻击或启用DNS放大攻击
总结:线上最好还是不要用Alpine镜像,一大堆问题