如何将两个Docker容器连接至OVS+DPDK实现互通与吞吐测试
OVS-DPDK对接Docker容器吞吐测试配置指南
环境基础说明
当前测试环境为VMware下Ubuntu18.04,DPDK版本20.11.0、OVS版本2.15.90,采用networkstatic/iperf3官方镜像,无外部流量交互需求,核心目标为对比OVS-DPDK与Linux内核网络栈的容器间吞吐性能差异。
已完成的基础配置(无需调整)包括:
- 安装openvswitch-switch-dpdk组件,将OVS-vswitchd默认服务切换为DPDK版本
- 完成大页内存配置、GRUB参数更新与挂载
- 将ens33网卡绑定至vfio-pci驱动(满足OVS-DPDK服务初始化的PMD设备要求,避免服务启动失败)
- 创建datapath类型为netdev的br0网桥
核心配置偏差修正
此前流程中创建的server、client端口为绑定物理PCI地址的DPDK物理口类型,这类端口仅用于对接外部物理网卡,无法对接Docker容器,是当前无法建立连通性的核心原因。需要将原有端口替换为专门用于对接容器/虚拟机端点的vhost-user类型端口,操作步骤如下:
- 删除原有错误配置的端口:
- 执行
ovs-vsctl del-port br0 server - 执行
ovs-vsctl del-port br0 client
- 执行
- 加载vhost-net内核模块,保障用户态OVS与容器网络的通信通道:
modprobe vhost_net - 创建vhost-user类型的OVS端口,端口通过主机本地unix socket通信,无需绑定物理设备:
- 创建server侧端口(OVS作为vhost服务端,监听本地socket连接):
ovs-vsctl add-port br0 server -- set Interface server type=dpdkvhostuser options:path=/tmp/ovs/server.sock - 创建client侧端口:
ovs-vsctl add-port br0 client -- set Interface client type=dpdkvhostuser options:path=/tmp/ovs/client.sock
- 创建server侧端口(OVS作为vhost服务端,监听本地socket连接):
- 调整socket文件的访问权限,允许容器内进程建立连接:
- 先创建socket存放目录:
mkdir -p /tmp/ovs && chmod 777 /tmp/ovs - 端口创建完成后,再次调整权限:
chmod 777 /tmp/ovs/*.sock
- 先创建socket存放目录:
- 更新流表转发规则:
- 执行
ovs-ofctl show br0,记录server、client对应的OpenFlow端口号(即输出中的ofport值) - 清空原有流表,配置双向流量转发规则:
ovs-ofctl del-flows br0- 配置server端口收到的流量转发到client端口:
ovs-ofctl add-flow br0 in_port=<server的ofport值>,action=output:<client的ofport值> - 配置client端口收到的流量转发到server端口:
ovs-ofctl add-flow br0 in_port=<client的ofport值>,action=output:<server的ofport值>
- 配置server端口收到的流量转发到client端口:
- 执行
Docker容器侧配置
由于采用networkstatic/iperf3镜像(基于内核网络栈的测试工具),需将容器的网络端点与OVS的vhost-user socket建立关联,操作步骤如下:
- 启动两个特权测试容器,禁用Docker默认网络栈,避免原有桥接规则干扰测试:
- 启动iperf3服务端容器:
docker run -itd --name iperf-server --network=none --privileged networkstatic/iperf3 tail -f /dev/null - 启动iperf3客户端容器:
docker run -itd --name iperf-client --network=none --privileged networkstatic/iperf3 tail -f /dev/null
- 启动iperf3服务端容器:
- 将容器的网络namespace绑定到系统的ip netns管理体系,方便后续配置网卡:
- 获取server容器进程PID:
SERVER_PID=$(docker inspect -f '{{.State.Pid}}' iperf-server) - 获取client容器进程PID:
CLIENT_PID=$(docker inspect -f '{{.State.Pid}}' iperf-client) - 创建netns关联目录:
mkdir -p /var/run/netns - 建立namespace关联:
ln -sf /proc/$SERVER_PID/ns/net /var/run/netns/iperf-serverln -sf /proc/$CLIENT_PID/ns/net /var/run/netns/iperf-client
- 获取server容器进程PID:
- 通过vhost-net内核模块建立OVS用户态端口与容器内核协议栈的共享内存通道:
- 针对server侧socket(/tmp/ovs/server.sock)创建对应的virtio-net内核设备,将设备移至server容器的网络namespace,配置同网段IP地址(如192.168.1.10/24)
- 针对client侧socket(/tmp/ovs/client.sock)创建对应的virtio-net内核设备,将设备移至client容器的网络namespace,配置同网段IP地址(如192.168.1.20/24)
注意:VMware环境下需为虚拟机开启网卡混杂模式,关闭TSO、GRO等网卡卸载特性,避免PMD轮询效率下降导致测试结果失真。不可将内核态veth、tap设备直接加入br0网桥,否则OVS会自动切换到内核datapath,无法体现DPDK的性能优势。
性能测试执行
- 连通性校验:
- 进入server容器执行ping指令,测试与client容器的网络连通性
- 吞吐测试:
- 启动iperf3服务端:
docker exec -it iperf-server iperf3 -s - 启动iperf3客户端打流:
docker exec -it iperf-client iperf3 -c 192.168.1.10 -t 60 -i 1 - 基准性能对比:相同硬件资源配置下,测试两个容器走Docker默认bridge网络(Linux内核栈)的iperf3吞吐结果,与OVS-DPDK场景的测试值对比,得到性能差异。
- 启动iperf3服务端:
内容的提问来源于stack exchange,提问作者Mohammad Siavashi
相关产品推荐
相关产品推荐

