记一次 docker 路由冲突

有两位研发告诉我,他们无法访开发服务器了,过了一会儿我被拉到一个群聊中,群里都是在吐槽无法访问开发服务器的问题,我被有要求来排查这个问题。群里也有 OPS 的同学,他们发现 iptables 中有很多 docker 注入的策略。docker 的网络策略和宿主机的防火墙测试是不兼容的,如果修改了服务器的防火墙配置,会导致无法重启 docker 容器。这里的问题是大家无法访问服务器的 ssh 端口。这个问题最诡异的地方是,我登录服务器没有问题,但是其他的同学通过本地登录服务器都不行,但是其他人可以通过别的服务器跳转一次登录到服务器上。我开始怀疑是防火墙的策略的问题,没有技术的我看不懂防火墙输出的策略日志。于是关闭防火墙试试,还是不行,还是无法访问。我想到了是不是因为 ip 段的问题,我的 ip 和其他的同事的不一样,因为我在武汉,其他人在北京。我们不是一个网段的。我想到路由信息会收到网段的影响,我问了2个同事的 ip 地址

1
2
10.43.77.42
10.43.75.35

然后看了一样服务器上的路由配置

1
2
3
4
5
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0 10.249.104.1 0.0.0.0 UG 0 0 0 eth0
10.32.0.0 0.0.0.0 255.240.0.0 U 0 0 0 weave
10.249.104.0 0.0.0.0 255.255.252.0 U 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0

写段小代码可以发现,这个 10.43.77.42 地址能被路由到 weave 这个 docker 网卡中,所有导致数据丢失

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"net"
)

func main() {
ip := net.IPv4(byte(10), byte(32), byte(0), byte(0))
mask := net.IPv4Mask(byte(255), byte(240), byte(0), byte(0))
ipNet := &net.IPNet{
IP: ip,
Mask: mask,
}
println(ipNet.Contains(net.IPv4(byte(10), byte(43), byte(77), byte(42))))
}

于是我加了一条路由配置

1
route add -net 10.43.0.0 netmask 255.255.0.0 gw 10.249.104.1

10.43 网络的包强制走 eth0 网卡,而不是走 weave 虚拟网卡。