Docker容器运行约40小时后DNS查询失败 求故障原因及排查方案
可能的原因
- Docker 19.03.5版本存在已知的嵌入式DNS连接泄漏缺陷:该版本内置的127.0.0.11 DNS转发服务在处理频繁DNS查询请求时,会出现UDP连接无法释放的问题,长期运行后临时端口耗尽,就会抛出日志中
resource temporarily unavailable的报错,该缺陷在20.10及以上的Docker稳定版中已被修复。 - 故障容器独立网络命名空间异常:由于同Docker网络下的其他容器解析正常,可排除宿主机、Docker全局网络层面的配置问题,大概率是故障容器的网络命名空间出现了路由规则异常、端口资源耗尽、内部iptables规则错误等单点问题。
- 容器维度conntrack条目耗尽:如果容器开启了连接跟踪,高并发请求下conntrack表被占满,新的DNS查询UDP报文会被直接丢弃,导致查询超时。
- Docker daemon分配的单容器DNS转发队列阻塞:故障容器的高频DNS请求占满了dockerd为其单独分配的转发队列,后续请求无法被处理,只有重启容器重置队列才能恢复。
可行的排查方法
- 监控dockerd的UDP连接变化:故障重现周期内定时执行
ss -u -a -p | grep dockerd统计dockerd持有的UDP连接数,如果数值持续上涨且无释放趋势,即可判定为DNS连接泄漏问题。 - 排查故障容器的网络命名空间状态:故障出现后执行
docker inspect <故障容器ID> | grep SandboxKey获取容器网络命名空间路径,再通过以下命令检查网络配置:- 查看容器内UDP连接:
nsenter --net=<替换为SandboxKey路径> ss -u -a - 检查容器内iptables规则:
nsenter --net=<替换为SandboxKey路径> iptables -L -n - 检查容器路由表:
nsenter --net=<替换为SandboxKey路径> ip route
- 查看容器内UDP连接:
- 检查连接跟踪资源占用:宿主机执行
sysctl net.netfilter.nf_conntrack_count和sysctl net.netfilter.nf_conntrack_max,对比当前计数是否接近上限;也可进入容器网络命名空间后查看对应维度的conntrack计数。 - 版本验证:在测试环境将Docker升级到20.10.x稳定版,观察是否还会出现运行40小时后DNS超时的问题,若故障消失即可确认是旧版本Docker的缺陷。
- 绕过Docker DNS验证:在docker-compose配置中为容器显式指定
dns配置项,值为私有网络DNS服务器的IP,跳过127.0.0.11转发环节,若故障不再出现即可确认是Docker嵌入式DNS服务的问题。
内容的提问来源于stack exchange,提问作者Robrecht Vanhuysse
相关产品推荐
相关产品推荐

