因MTU导致的容器网络问题
将CI/CD服务前移到k8s后,当drone的插件drone-docker构建镜像时,总卡在更新软件包的步骤。是网络连接的问题,为了解决这个问题,耗费了我整个周末。
# apk update
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
Drone-Runner in K8S
在k8s环境中,drone-runner通过调用k8s的api,创建相应的pod来运行pipeline。此时,一个pipeline对应一个pod。Pod中的各个容器对应pipeline中的各个step。
Drone-Docker
在docker环境中,drone-docker一般以docker outside of docker(dood)的方式运行。但在k8s环境中,drone-docker以docker in docker(dind)的方式运行,可以理解成“套娃”。
由于我的集群的cri是containerd,更准确的说,这里是以docker in containerd的方式运行的:
- 执行drone-pipeline的pod运行在k8s的containerd上
- 构建镜像的docker容器通过pod内容器的docker服务运行
k8s (containerd)
└── pod (pipeline)
├── container (step clone)
└── container (step drone-docker)
└── docker (dind)
└── container (docker build)
这种复杂的结构,导致了奇怪的网络现象,结合以上树形图进行说明:
- 容器(step drone-docker)的网络正常
- 容器(docker build)可以下载基于http协议的小体积文件
- 容器(docker build)不能下载基于http协议的大文件以及所有基于https的文件
Maximum Transmission Unit(MTU)
起初,我以为区别在于http和https协议,可能是tls握手出现了问题。打算通过http协议,下载安装一些包,进行网络测试,却发现大体积的文件也无法下载。即使能够下载,下载的速度也特别慢。
看来并不是协议的问题,是响应体大小的问题,更准确的说是传输速度的问题。其实,我有过容器内下载速度慢的经验:在京东云运行docker容器时因为网速慢调整过mtu。于是便在mtu上下功夫了。
容器(step drone-docker),主机网卡eth0@if112
mtu是1450
,docker网桥docker0
mtu是1500
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: eth0@if112: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP
link/ether 76:93:e3:c6:53:fb brd ff:ff:ff:ff:ff:ff
inet 10.42.0.108/24 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::7493:e3ff:fec6:53fb/64 scope link tentative dadfailed
valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:2a:76:ce:8a brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:2aff:fe76:ce8a/64 scope link
valid_lft forever preferred_lft forever
容器(docker build),主机网卡eth0@if8
mtu是1500
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
7: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
果然,子容器内的mtu跟容器宿主机的mtu是不一致的,且子容器的mtu比容器宿主机的mtu大。这就导致了数据传输时需要分片,进而导致网络速度下降。将子容器的mtu设置成与容器宿主机一样的值就行了。
在这里,我在drone pipeline内设置相应的mtu值即可。注意:这里的mtu键是plugins/docker
插件的一个参数。对于正常的容器而言,应设置与之对应的参数。
kind: pipeline
type: kubernetes
name: default
steps:
- name: php-fpm
image: plugins/docker
settings:
mtu: 1450
关于MTU的理解
将子容器往容器宿主机数据传输过程比作用货车运箱子:子容器mtu值是箱子的大小,容器宿主机的mtu值是货车车厢的容量大小。
当箱子比车厢大时,需要将箱子切割并分给其他货车运输(数据包的分片),因此箱子的运输效率会降低。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南