今天一个从来没有用过docker容器的同事问了我一个网络延迟的问题,很简单,但我确没有准确回答出来。经过简单的验证,现在我把过程及结果分享给各位粉丝。
简短对话
容器中的网络延迟相较于宿主机有多高啊?
我不假思索的回答可以忽略不计吧
同事带着疑惑的的说了句,那你说说docker网络桥接的实现
在容器启动时,Docker引擎将veth pair设备的一端放在新创建的容器中,并命名为eth0,另一端放在宿主机中;docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关;这样它们就组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。相当于多了一层网络,就少不了网络解封包开销,看来是有影响的。
影响到底有多大呢?没有做过这方面的测试......
验证环境准备
本次验证工具我使用了Netperf,Netperf是一种网络性能的测量工具,可以测试基于TCP或UDP吞吐、响应速率。Netperf包括Clien和Server端。Server端主要用来实现监听工作,Client端进行测试。根据流量传输方式可分为以下三种:
单方向最大吞吐传输大量数据。
双方向交互传输数据,对于tcp为单连接。
针对tcp,每个连接交互传输数据。
环境信息
总共两台机器,一台机器启动了NetPerf服务端;另外一台机器分别在容器内和宿主机上运行Netperf客户端。
NetPerf服务端
1.下载wget http://repo.iotti.biz/CentOS/7/x86_64/netperf-2.7.0-1.el7.lux.x86_64.rpm
2.安装 rpm -ivh netperf-2.7.0-1.el7.lux.x86_64.rpm
3.启动 netserver
NetPerf客户端
宿主机验证
首先直接在宿主机上安装Netperf,然后进行网络性能测试,如下所示:
TCP_RR 是 netperf 里专门用来测试网络延时的,缺省每次运行10秒钟。运行以后,我们还要计算平均每秒钟 TCP request/response 的次数,这个次数越高,就说明延时越小。如上所示,总共测试三轮,分别得出20146、20248、20221,平均是20221/s
容器中验证
在同一台客户端机器上,启动docker服务,并安装Netperf进行验证,命令如下所示[root@test ~]# docker run -d --name test -v /home/net/:/home/net/ docker.harbor.com/centos:7.8 sleep 36000
我这里相当于是把Netperf挂载到容器内部,然后执行:
docker exec -it test bash
进入容器内部安装Netperf。
同样运行了三轮,分别得出的是19546、19541、19259,平均是19448/s。
从数据上看容器中比宿主机少了773次。773/20221= 4%也就是容器中网络处理速度下降了4%,后来在网上找到了一些paper,有人得出结论是10%上下
。
容器中共享宿主机网络运行
[root@test ~]# docker run -d --name test --network host -v /home/net/:/home/net/ docker.harbor.com/centos:7.8 sleep 36000
可以发现当使用共享宿主机网络模式下,其网络延迟跟宿主机基本没有差异。
原因分析
网络延迟的原因也不难想象,因为每次网络数据传输都要经过veth接口,然后向外发送。这个虚拟的网络设备除了没有硬中断,只有软中断处理过程,其它跟网卡发送数据逻辑基本相似,虽然发送速度很快。但即便如此也带来了一定的网络开销,从而造成了网络延迟。
总结
本文主要通过Netperf工具测试了宿主机和docker容器中的网络延迟,总的来说,在可接受范围之内,但是如果您的服务对延迟比较敏感,那么就可以考虑共享宿主机网络,或者使用后来推出的macvlan/ipvlan(IPVlan 和 macvlan 类似,都是从一个主机接口虚拟出多个虚拟网络接口,发送逻辑更简单。)其性能基本上接近于宿主机。当然最近几年Kubernetes定义了CNI标准,我们可以根据CNI实现自己的网络转发模式。比如Flannel、Calico、Weave和Canal都是基于该接口实现,让Kubernetes生态系统中的网络解决方案有更多样的选择,意味着大多数用户将能够找到适合其当前需求和部署环境的CNI插件和解决方案。如有问题,请关注公众号、加我微信,我拉你进群讨论!
推荐
原创不易,随手关注或者”在看“,诚挚感谢