当 MTU 不一致导致容器间 SSH 卡顿,如何调优
解读
在国内云主机、专线、混合云场景下,容器网络插件(Flannel、Calico、Weave 等)默认 MTU 往往比宿主机物理网卡或云厂商 VPC 网络小 50 字节,而 SSH 会话又依赖 TCP 大包交互。一旦路径上某段 MTU 小于容器内网卡 MTU,就会出现 IP 分片甚至被丢弃,表现为 SSH 输入延迟、Tab 补全卡顿、文件传输掉速。面试官想考察的是:
- 能否快速定位 MTU 不一致
- 能否在不中断业务的前提下完成端到端调优
- 是否理解 Docker 网络栈与宿主机、Overlay、VXLAN、IPIP 之间的封装开销
知识点
- MTU(Maximum Transmission Unit):链路层单帧最大 payload,以太网默认 1500
- Docker 网络驱动:bridge、host、overlay、macvlan、ipvlan,各自封装开销不同
- VXLAN 额外开销:50 字节(14 ETH + 20 IP + 8 UDP + 8 VXLAN + 14 ETH inner),故 overlay 网络 MTU 需 ≤1450
- TCP MSS(Maximum Segment Size):MTU − IP/TCP 头,通常 40 字节;路径上 MSS 不一致会触发 ICMP Fragmentation Needed,若被云厂商安全组丢弃则导致“黑洞”
- 国内云厂商限制:阿里云 ECS 安全组默认放行 ICMP 3/4,腾讯云 CVM 需手动放通;部分金融云干脆禁止 ICMP,只能降 MTU
- 容器运行时配置:daemon.json 中
"mtu": 1450、docker-compose.yml 中driver_opts.mtu、Swarm service 创建时--opt mtu=1450 - CNI 插件级配置:Flannel 的
--iface-mtu、Calico 的veth_mtu、Weave 的WEAVE_MTU - 在线热调整:ip link set dev eth0 mtu 1450、systemctl reload docker、kubectl patch felixconfiguration 等
- 验证手段:
ping -M do -s 1472 <podIP>测 PMTU、tcpdump 抓 ICMP Type 3 Code 4、ss -i 看 TCP MSS、iftop 看重传率
答案
-
定位:
a. 在宿主机执行ping -M do -s 1472 <对端容器IP>若返回“Frag needed”则确认 MTU 黑洞
b.tcpdump -i any icmp and 'icmp[0]=3 and icmp[1]=4'抓包看是否收到 ICMP 需要分片报文
c.docker exec 容器 ss -i查看 TCP MSS 值是否大于路径最小 MTU -
计算安全值:
若走 VXLAN Overlay,MTU = 1500 − 50 = 1450;若走 IPIP 隧道,MTU = 1500 − 20 = 1480;若宿主机网卡本身被云厂商限制为 1460,则再减 50 取 1410 -
统一调整:
a. Docker daemon 级:/etc/docker/daemon.json新增"mtu": 1450,systemctl reload docker(reload 不重启容器,业务无感知)
b. Compose 项目级:docker-compose.yml 中networks: app: driver: bridge driver_opts: com.docker.network.driver.mtu: "1450"c. Swarm 级:
docker network create -d overlay --opt mtu=1450 --attachable ov1450
d. CNI 级:修改 kube-flannel-cfg ConfigMap 的net-conf.json.Network.MTU=1450,滚动重启 Flannel DaemonSet;Calico 则kubectl patch felixconfiguration default --patch '{"spec":{"vethMTU":1450}}' -
宿主机物理网卡同步:
若宿主机 MTU 被云厂商限制为 1460,需ip link set dev eth0 mtu 1460并写入/etc/sysconfig/network-scripts/ifcfg-eth0的MTU=1460,防止重启回退 -
验证:
再次ping -M do -s 1422 <对端IP>(1422+28=1450)通即 OK;SSH 登录后dd if=/dev/zero bs=1M count=100 | ssh 对端 'cat >/dev/null'观察带宽是否恢复且无重传 -
兜底:
若云环境禁止 ICMP,无法依赖 PMTUD,则强制容器内 TCP MSS Clamp:
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
或在 Calico 的 Felix 配置中开启FELIX_DEFAULTENDPOINTTOHOSTACTION=Accept并启用FELIX_TCPMSSCLAMP=1
拓展思考
- IPv6 场景:VXLAN over IPv6 额外再减 20 字节,MTU 需 ≤1430,国内双栈网络需同步调整
- Service Mesh 层:Istio 开启 mTLS 后,Sidecar 之间再增 24 字节 TLS Header,MTU 需再降 24,建议统一 1426
- 金融云合规:部分银行私有云要求加密机透明代理,MTU 降到 1400 以下,需提前在 CI 流水线里做 iperf3 PMTU 探测 并自动写回 Helm values
- 多集群混合云:跨 Region 专线 MTU 8500,但云主机只有 1500,不可盲目调大,需用 GRE Tunnel 拆包 或 云企业网 提供的 Jumbo Frame 白名单
- 监控闭环:在 Prometheus 中采集
node_network_mtu与container_network_mtu,建立 Grafana 告警:node_network_mtu != container_network_mtu即触发,防止后续扩容再出现“隐形”卡顿