pmtu协商失败

Docker 容器中出现 PMTU 协商失败(Path MTU Discovery Failed) 的问题,通常会导致容器中的网络连接异常,比如:

  • 大数据包传输失败

  • VPN / API 调用失败

  • curlwget 卡住

  • 页面加载不完全


📌 一、问题本质: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 为 14001450,防止 GRE、VPN、Overlay 网络(如 Calico, Flannel)出问题。


需要我帮你写个一键脚本来自动设置这些参数吗?或者你现在的环境是哪个云平台/系统版本?我可以针对性给出配置建议。

posted on 2025-04-17 21:35  吃草的青蛙  阅读(89)  评论(0)    收藏  举报

导航