pmtu协商失败
Docker 容器中出现 PMTU 协商失败(Path MTU Discovery Failed) 的问题,通常会导致容器中的网络连接异常,比如:
-
大数据包传输失败
-
VPN / API 调用失败
-
curl、wget卡住 -
页面加载不完全
📌 一、问题本质:PMTU 协商失败
-
PMTU(Path MTU Discovery)是操作系统尝试找出从源主机到目标主机之间路径中 最小的 MTU 值。
-
Docker 默认使用 桥接网络(bridge),再加上可能存在 NAT、防火墙、VPN、云平台(如阿里云/腾讯云)限制,PMTU 的探测包(带
Don't Fragment的 ICMP)被丢弃,导致协商失败。
✅ 二、快速解决方法
方法 1:容器内禁用 PMTU 探测
在容器内部执行:
echo 1 > /proc/sys/net/ipv4/ip_no_pmtu_disc
或者使用 sysctl:
sysctl -w net.ipv4.ip_no_pmtu_disc=1
要永久生效,修改容器内的 /etc/sysctl.conf:
net.ipv4.ip_no_pmtu_disc = 1
方法 2:宿主机强制禁用 Docker 网络的 PMTU 探测
在宿主机上设置,对所有容器生效:
sysctl -w net.ipv4.conf.all.accept_redirects=0
sysctl -w net.ipv4.conf.all.send_redirects=0
sysctl -w net.ipv4.ip_no_pmtu_disc=1
或者修改 /etc/sysctl.conf 添加以下内容后执行 sysctl -p:
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.ip_no_pmtu_disc = 1
方法 3:限制 Docker 网络接口 MTU 值
Docker 默认使用宿主机网卡的 MTU,如果宿主 MTU 是 9000(例如云服务器或虚拟机使用 jumbo frame),但路径中某一跳不支持,会导致丢包。
强制限制 Docker 网络的 MTU,比如改成 1400:
dockerd --mtu=1400
或者编辑 Docker 的配置文件(推荐):
sudo mkdir -p /etc/docker
sudo vi /etc/docker/daemon.json
添加:
{
"mtu": 1400
}
然后重启 Docker:
sudo systemctl restart docker
注意: MTU 不能设置得太小,可能影响效率;也不能太大,否则依然协商失败。
方法 4:Docker Compose 添加 MTU 限制(每个容器网络)
networks:
default:
driver: bridge
driver_opts:
com.docker.network.driver.mtu: 1400
🔍 三、排查辅助命令
查看当前 MTU:
ip link
测试 MTU 传输:
ping -M do -s 1472 8.8.8.8
如果失败,就减小 -s 的值直到成功,说明路径 MTU 较小。
⚠️ 四、特别注意(云服务器 / 容器云)
-
在云环境(如阿里云、腾讯云)中,很多运营商会屏蔽 ICMP 报文,导致 PMTU 协商失败。
-
建议默认设置 MTU 为
1400或1450,防止 GRE、VPN、Overlay 网络(如 Calico, Flannel)出问题。
需要我帮你写个一键脚本来自动设置这些参数吗?或者你现在的环境是哪个云平台/系统版本?我可以针对性给出配置建议。
浙公网安备 33010602011771号