宿主机能ping通docker容器但是访问不了网页_一个奇怪的docker网络问题解决

很久没有写东西了,实在是太忙。
这次遇到了这个奇怪的问题,最终还是得以解决了,在此分享给大家。
希望通过本文记录,给大家解决问题的时候,能提供一些思路和些许的参考。

1.问题描述

就在今天,我用docker容器跑的FBE突然无法访问了(https访问)。
host机工作正常,且host机上的其它容器也都工作正常。只有FBE无法正常工作。
具体的表现为:
FBE并不是完全无法打开, 而是有时候能打开,有时候要等很久才能打开。
通过firefox的dev工具观察network请求,发现即使我们成功进入了FBE web界面,
在里面点击打开任意一个目录(本质上是向FBE发送一个https请求),有很大概率不能打开。
有时候能打开,但是,观察到的结果是,一个普通的列目录的https请求,居然花费了18秒!

2. 尝试过的无效的解决方案

尝试1:重建搜索索引
首先,我想到的是,是不是CPU太忙了,没空处理我们的请求?
所以我尝试删除了FBE的文件索引,毕竟我这里有接近100多万个文件被FBE索引了.
我检查了下FBE的索引文件,大概有 11GB大小,好像是有点大啊。
于是我删除了索引数据库的目录 .root.bleve , 然后重启FBE容器,重启后FBE成功重新生成了索引.
新的索引大概有10GB的样子。所以,索引里虽然由于长期使用,存在一些垃圾。但是,不是索引引起的。

尝试2: 重建容器
会不会这个容器跑太久了,docker自己出现了奇怪的问题?进入portainer re-create 这个容器,
然后再测试,结果也是一样,没有变。所以,不是这个原因

尝试3: 直接进入host机,访问FBE容器开放的端口
结果跟我们之前的测试一样,在TCP层就已经卡住了.

老衲实在黔驴技穷了,怎么办?放弃吧?
不能放弃啊,FBE作为日常使用的应用,不解决怎么行?
上个厕所,洗把脸,抽根烟,站在阳台眺望一下远方。继续回到电脑前面研究吧。

3.解决方案探索

这里假设host机的局域网IP为 192.168.8.123, FBE https监听端口为 8084
我们在局域网上任意一台电脑上使用curl命令测试下https是否连接正常:

curl -k -vvv https://192.168.8.123:8084/
* Trying 192.168.8.123:8084...
* TCP_NODELAY set

结果是卡住了,卡在 TCP_NODELAY set, 应用层(https)压根就没有进行通信。
从这里我们可以看出什么?

  1. 8084端口是正常打开的,且端口开放正常,没有被firewall挡住
    这个很好测试,假设端口没打开或者被firewall挡住了,结果应该 是Connection refused, 比如我们随便访问一个251的端口:

❯ curl -vvv -k https://192.168.8.123:251/
* Trying 192.168.8.123:251...
* TCP_NODELAY set
* connect to 192.168.8.123 port 251 failed: Connection refused
* Failed to connect to 192.168.8.123 port 251: Connection refused
* Closing connection 0
curl: (7) Failed to connect to 192.168.8.123 port 251: Connection refused
  1. 还没有达到应用层,说明在tcp层就已经卡住了.

我们直接ssh 到host机看看吧。

nas9320# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a05c6ff61ec3 80x86/qbittorrent:latest "/entrypoint.sh /app…" 40 hours ago Up 40 hours 192.168.8.123:8011->8011/tcp, 8999/tcp, 8999/udp qbittorrent
c03432a4d628 80x86/filebrowser:latest "/entrypoint.sh /app…" 3 weeks ago Up 56 minutes 8082-8083/tcp, 192.168.8.123:8084->8084/tcp filebrowser
018b1a87e742 80x86/ddns-updater:latest "/app/ddns-updater" 5 weeks ago Up 4 weeks (healthy) 192.168.8.123:8082->8082/tcp    

注意, 这里,我们已经测试过了,同一个host机下的其它容器都工作正常. 所以,这里我们用docker ps 主要是看看, FBE 的端口8084 是否正常映射了。
从结果看,端口完全映射正常.

我这里所有的容器都是使用的bridge 类型的网络, 由于docker对于bridge类型的端口开放,其实在Linux上的底层实现是走的dst port nat.
我们用iptables 检查下,这些个nat规则是否生效了。

nas9320# iptables -v -n -t nat -L DOCKER
Chain DOCKER (2 references)
 pkts bytes target prot opt in out source destination         
   13 618 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0           
  515 26164 DNAT tcp -- !docker0 * 0.0.0.0/0 192.168.8.123 tcp dpt:8082 to:172.17.0.2:8082
  899 50736 DNAT tcp -- !docker0 * 0.0.0.0/0 192.168.8.123 tcp dpt:8011 to:172.17.0.4:8011
   36 2160 DNAT tcp -- !docker0 * 0.0.0.0/0 192.168.8.123 tcp dpt:8084 to:172.17.0.3:8084

从结果看,端口映射也是OK的。并且,从这个结果,我们还看到了FBE容器的内部IP为 172.17.0.3 , 这个IP能否Ping通呢?
我们测试一下看:

nas9320# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
From 172.17.0.4 icmp_seq=1 Redirect Host(New nexthop: 3.0.17.172)
From 172.17.0.4 icmp_seq=2 Redirect Host(New nexthop: 3.0.17.172)
From 172.17.0.4 icmp_seq=3 Redirect Host(New nexthop: 3.0.17.172)
From 172.17.0.4 icmp_seq=4 Redirect Host(New nexthop: 3.0.17.172)
^C
--- 172.17.0.3 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3048ms
nas9320# 

oh no, 这结果不对啊,最直观的结果:丢包率100%
然后,还有一些奇怪的东西.
奇怪1: 我们ping的是  172.17.0.3, 为什么ICMP ping返回的结果是从172.17.0.4 这个IP返回的?
奇怪2: ping的返回结果不是该主机无法到达,而是奇怪的 Redirect Host(New nexthop: 3.0.17.172)
也就是说,我们ping 172.17.0.3, 返回的结果却是172.17.0.4 发过来的,并且还告诉我们,下一跳是 172.17.0.3

Google了下,也没有发现其它人有类似的情况。
于是只能继续探索。
我们再确认一下,其它容器的IP是否能正常ping通:
测试 172.17.0.2 ,结果完全正常,通的:

nas9320# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.071 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.062 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.060 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.057 ms
^C
--- 172.17.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3031ms
rtt min/avg/max/mdev = 0.057/0.062/0.071/0.005 ms

继续测试 172.17.0.4:

nas9320# ping 172.17.0.4
PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data.
64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from 172.17.0.4: icmp_seq=2 ttl=64 time=0.058 ms
64 bytes from 172.17.0.4: icmp_seq=3 ttl=64 time=0.059 ms
64 bytes from 172.17.0.4: icmp_seq=4 ttl=64 time=0.054 ms
^C
--- 172.17.0.4 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3030ms
rtt min/avg/max/mdev = 0.054/0.057/0.059/0.002 ms

结果也是OK。
那么,问题来了,为什么只有ping 172.17.0.3的时候不正常?

直觉和经验告诉我,是docker的network这一块出问题了。
因此,我尝试进入portainer, 让FBE容器 leave the network (bridge), 然后再加入bridge network,
结果呢?docker还是给FBE分配了同样的IP 172.17.0.3
还是失败啊。
这个问题,可能有点难搞啊。

然后,我想是不是mac地址分配有问题?
于是,继续进portainer, 查看一下整个bridge network的情况:

e76784b780ce2b37cc5bd6578563fbf6.png

发现问题了吧,172.17.0.4 和 172.17.0.3 的mac地址是雷同的!
这就是问题的根本原因。

由于172.17.0.4 的端口是工作正常的,因此, 这里我们只针对FBE容器进行network的修复。
在portainer里点击编辑 FBE的容器,底部切换到Network选项卡,删除Mac Address的值,
然后点击 Deploy the container 重新创建并替换当前容器.

b089972f6d6327143831e1ca8e9d82fb.png

重建之后的结果:

6d91521dde85037e6efa1a5ebfbbf7d7.png

没错,现在 172.17.0.3 的 mac地址OK了.
然后,我们测试下 FBE 的web ui是否能正常访问了.
测试结果:完全正常。

OK, 问题解决了.
本文用到了一些常用的命令,并且涉及一些基本的计算机网络故障排查知识,由于时间关系,这里只关注于解决问题的思路和方法,这些基本知识就没有多说。
关于docker bridge network的更多资料,大家可以查看 docker 官方文档.
关于iptables命令的使用,大家可以查看linux man.

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页