Docker Swarm绑定全接口后无法接收eth1网卡UDP数据包的问题求助
Docker Swarm绑定全接口后无法接收eth1网卡UDP数据包的问题求助
遇到这种多网卡环境下UDP端口绑定失效的问题确实挺闹心的,我结合你的环境信息梳理了几个可能的排查方向和解决思路,你可以一步步试试:
先明确下你的环境和现象
主机网卡信息:
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:b5:1e:5a:50 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 docker_gwbridge: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255 inet6 fe80::42:36ff:feae:7b45 prefixlen 64 scopeid 0x20<link> ether 02:42:36:ae:7b:45 txqueuelen 0 (Ethernet) RX packets 226939106 bytes 46241924181 (43.0 GiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 166 bytes 8300 (8.1 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 1.1.1.1 netmask 255.255.255.0 broadcast 1.1.1.255 inet6 fe80::21a:ff:fe00:43f prefixlen 64 scopeid 0x20<link> ether 00:1a:00:00:04:3f txqueuelen 1000 (Ethernet) RX packets 3852423 bytes 1206323488 (1.1 GiB) RX errors 0 dropped 11 overruns 0 frame 0 TX packets 380930 bytes 85160453 (81.2 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 2.2.2.2 netmask 255.255.255.0 broadcast 2.2.2.255 inet6 fe80::21a:ff:fe00:b1a prefixlen 64 scopeid 0x20<link> ether 00:1a:00:00:0b:1a txqueuelen 1000 (Ethernet) RX packets 226939106 bytes 46241924181 (43.0 GiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 166 bytes 8300 (8.1 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Swarm Compose端口配置:
ports: - target: 162 published: 162 protocol: udp mode: host networks: - default
现象:
- 发送UDP包到
eth0(1.1.1.1:162),容器内tcpdump能抓到包 - 发送UDP包到
eth1(2.2.2.2:162),容器内完全抓不到
可能的原因和排查步骤
1. 反向路径过滤(rp_filter)导致数据包被内核丢弃
这是多网卡UDP问题最常见的原因:当数据包从eth1进入主机,容器响应时可能走默认路由(比如eth0),内核的反向路径检查会认为这个数据包的来源路径不合理,直接丢弃。
排查&解决:
# 查看当前eth1和全局的rp_filter设置 sysctl net.ipv4.conf.eth1.rp_filter sysctl net.ipv4.conf.all.rp_filter # 临时修改(重启后失效),把值改成0(关闭检查)或者2(宽松检查) sysctl -w net.ipv4.conf.eth1.rp_filter=0 sysctl -w net.ipv4.conf.all.rp_filter=0 # 永久生效的话,编辑/etc/sysctl.conf,添加或修改以下内容: # net.ipv4.conf.all.rp_filter=0 # net.ipv4.conf.eth1.rp_filter=0 # 执行sysctl -p生效
修改后再测试发送UDP包到eth1,看容器是否能抓到。
2. iptables规则未覆盖eth1
Docker Swarm在host模式下绑定端口时,会自动生成iptables规则,但有可能规则只针对eth0生效,没有包含eth1。
排查:
# 过滤出UDP 162端口的iptables规则 iptables-save | grep -i udp | grep 162
如果输出里只有针对eth0或者特定IP的规则,没有0.0.0.0/0的全局规则,那需要重启Docker服务让Swarm重新生成规则,或者手动添加一条:
iptables -A INPUT -i eth1 -p udp --dport 162 -j ACCEPT
3. 端口监听未绑定到全接口
虽然compose里配置了mode: host,但有可能服务实际监听的只是eth0的IP,而非全接口。
排查:
# 查看UDP 162端口的监听状态 ss -ulpn | grep 162
确认输出里的监听地址是0.0.0.0:162或者:::162(表示监听所有接口)。如果是1.1.1.1:162(只监听eth0),那说明绑定没生效,需要重新部署Swarm服务:
docker stack deploy -c docker-compose.yml <你的服务名> --prune
4. 先确认主机是否能收到eth1的包
如果以上步骤都没问题,先排查数据包是否真的到达了主机:
# 在主机上抓eth1的UDP 162端口数据包 tcpdump -i eth1 udp port 162
如果主机都抓不到包,那问题不在Docker层面,可能是交换机端口配置、路由策略或者上游网络的问题;如果主机能抓到,但容器抓不到,再回到前面的rp_filter和iptables排查。
备注:内容来源于stack exchange,提问作者Unknown.Vagrant
相关产品推荐
相关产品推荐

