记录一次docker网络故障-mtu

记录一次docker网络故障-mtu

简述

  1. 从云服务器上通过 wg 隧道将网站的请求转到内网
  2. 配置后,页面打开无响应最后超时

排查步骤

  1. 从云服务器宿主机测试目标站点
curl -i -s -o /dev/null -w "%{http_code}\n" http://192.168.5.30  -H "Host: www.chenwx.top"
200

curl -i http://192.168.5.30  -H "Host: www.chenwx.top"
# 正常打开页面

查看内网服务的nginx日志, 正常响应, 且耗时很低。

  1. 更换容器网络进行验证
docker run --rm -it --network host nginx:1.25.3-alpine \
     curl -I -s -o /dev/null -w "%{http_code}\n" \
     -H "Host: www.chenwx.top" http://192.168.5.30
成功响应 200

docker run --rm -it --network host nginx:1.25.3-alpine \
     curl -H "Host: www.chenwx.top" http://192.168.5.30
成功响应 html

docker run --rm -it --network bridge nginx:1.25.3-alpine \
     curl -I -s -o /dev/null -w "%{http_code}\n" \
     -H "Host: www.chenwx.top" http://192.168.5.30
成功响应 200

docker run --rm -it --network bridge nginx:1.25.3-alpine \
     curl -H "Host: www.chenwx.top" http://192.168.5.30
未响应 html, 阻塞

现象说明

  1. host 网络模式下, 只访问http头和完整页面访问都是正常的;
  2. 桥接网络模式下, 只接收http响应头时是正常的, 如果接收 html body 就会失败;

说明桥接模式下小包是正常的,大数据包会失败, 基本定位 99%是 MTU 的问题。

解决办法: 查看 wg 网卡设置的 mtu 值是 1408, 于是将 docker 桥接网络的 mtu 值也修改为一致;

  1. 检查当前 MTU
[root@ecs2 nginx]# docker network inspect bridge   --format='{{json .Options}}' | jq .
{
  "com.docker.network.bridge.default_bridge": "true",
  "com.docker.network.bridge.enable_icc": "true",
  "com.docker.network.bridge.enable_ip_masquerade": "true",
  "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
  "com.docker.network.bridge.name": "docker0",
  "com.docker.network.driver.mtu": "1500"
}

修改值

/etc/docker/daemon.json
{
  "mtu": 1408
}

# 再看值已经变了
[root@ecs2 nginx]# docker network inspect bridge   --format='{{json .Options}}' | jq .
{
  "com.docker.network.bridge.default_bridge": "true",
  "com.docker.network.bridge.enable_icc": "true",
  "com.docker.network.bridge.enable_ip_masquerade": "true",
  "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
  "com.docker.network.bridge.name": "docker0",
  "com.docker.network.driver.mtu": "1408"
}
  1. 再次测试还是失败

确认因为自己用的一个单独创建的 docker 网络, 所以值是没有变的, 即 daemon.json 内的 mtu 不影响独立创建的网络

docker network inspect traefik  --format='{{json .Options}}' | jq .
{}      # 实际还是个空值
  1. 删除原有网络后, 再新建一个自定义 MTU 的网络

docker compose down

docker network rm traefik

docker network create traefik --opt com.docker.network.driver.mtu=1408

[root@ecs2 nginx]# docker network inspect traefik   --format='{{json .Options}}' | jq .
{
  "com.docker.network.driver.mtu": "1408"
}
  1. 启动服务, 验证通过

至于为什么 wireguard 的 mtu 值会是 1408, 因为wg增加一层封包后原本应该是 1420;

但不知道为什么腾讯云轻量服务器不能使用 1420 这个值, 只能逐个往下减少, 一直试到 1408 wireguard 组网才成功;

最后更新于