ovs+dpdk-docker实践
来源:互联网 发布:淘宝联盟是如何运作的 编辑:程序博客网 时间:2024/05/29 10:54
docker 概念
关于docker的基本概念相关,可以参考官网介绍,介绍的挺全面的。另外这篇文章介绍的也很清晰,并附带有可以直接上手的实例。
关于container和vm的对比,需要重点关注下,直接放图如下:
从图中可以看出两者的区别包括:
1. 传统的VM需要依赖hypervisor层来实现,而不同hypervisor实现是和硬件强绑定的;docker对hardware的依赖则很少
2. VM内部除了包含app以及依赖的运行库环境,还包括了Guest OS;相比docker,过于重量级,从而导致对host端资源的占用率比较高
3. docker中多个container App都是使用Host的kernel,不适用与依赖不同kernel实现的App
4. docker提供的swarm模式,可以方便地创建一个docker集群,从而灵活地提供高可用性和故障恢复等特性
研究方案选择
目前dpdk官网提供两种方案来支持container,如下图:
上图(1) 方案中需要NIC支持SR-IOV功能,物理NIC支持的VF个数也依赖于硬件资源;每个container的接口独占VF,多个VF共享下面的一个PF。基于这种方案实现的container,无论对硬件的依赖和绑定,还是container的迁移,支持性都做得不够好。
上图(2) 方案中需要在host中运行vswitch或者vRouter来将上层的containers和底层的物理NIC解耦,只要vswitch(当前比较流行的OVS+DPDK,将OVS放在用户态来实现)的性能足够,一样可以实现高性能的container app了。
技术分析
基于以上比较,本次预研主要选取第二种方案来实现,该方案中container中涉及的组件如下图所示:
方案中使用virtual device(包括virtio-user和vhost-user backend)来实现高性能的container App 或者IPC。Virtio使用共享内存的方式来收发报文,传统的VM可以通过qemu来共享vhost后端的物理地址,但对container而言,作为系统的一个进程,使用这种方式则比较难。目前的思路是只能使用DPDK初始化的hugepages来进行内存共享。所以,要在container中使用dpdk,必须要分配足够的大页内存,且不同container在使用共享内存时要能够分区使用,避免地址重复。
container + dpdk 实践
拓扑图
dpdk 安装
wget http://fast.dpdk.org/rel/dpdk-17.05.tar.xztar -xvf dpdk-17.05.tar.xzcd dpdk-17.05#设置DPDK库目录位置echo export RTE_SDK=$(pwd) >>~/.bashrc#设置DPDK目标环境#注意!这里的x86_64-native-linuxapp-gcc应替换为实际运行环境echo export RTE_TARGET=x86_64-native-linuxapp-gcc >> ~/.bashrcsource ~/.bashrc#配置DPDK,需要使用Vhost-user驱动,需要将CONFIG_RTE_LIBRTE_VHOST=yvim config/common_base#安装dpdkmake config T=$RTE_TARGETmake T=$RTE_TARGET -j8#编译l2fwd[root@nsfocus dpdk-17.05]# cd examples/l2fwd/[root@nsfocus l2fwd]# make
hugepage的配置(配置使用1G大小的hugepagesize,同时最多分配8个):
sudo vim /etc/default/grub2.cfg#找到其中一项为 GRUB_CMDLINE_LINUX_DEFAULT= ,不论后面的引号内包含任何内容,在原本内容之后添加 default_hugepagesz=1GB hugepagesz=1G hugepages=8(这里分配了8个1G的hugepages)reboot#查看分配情况grep Huge /proc/meminfo#分配成功后进行挂载mkdir -p /dev/hugepagesmount -t hugetlbfs none /dev/hugepagesmkdir -p /mnt/hugemount -t hugetlbfs -o pagesize=1G none /mnt/huge
pktgen 安装
pktgen的安装依赖于DPDK,安装前确保RTE_SDK和RTE_TARGET环境变量设置正确。
#安装依赖yum install -y libpcap.x86_64wget http://www.dpdk.org/browse/apps/pktgen-dpdk/snapshot/pktgen-3.4.2.tar.gztar -xvf pktgen-3.4.2.tar.gzcd pktgen-3.4.2make -j8ln -s $(pwd)/app/$RTE_TARGET/pktgen /usr/bin/pktgen
ovs 安装与配置
- 安装ovs:
#下载wget http://openvswitch.org/releases/openvswitch-2.8.1.tar.gz#解压tar xzvf openvswitch-2.8.1.tar.gzcd openvswitch-2.8.1#配置环境并安装./boot.shCFLAGS='-march=native' ./configure --with-dpdk=$RTE_SDK/$RTE_TARGETmakemake install#查看大页内存cat /proc/meminfoAnonHugePages: 32768 kBHugePages_Total: 8HugePages_Free: 4HugePages_Rsvd: 0HugePages_Surp: 0Hugepagesize: 1048576 kB
- 启动ovs:
#start_ovs.sh 1 #init new ovs database 2 ovsdb-tool create /usr/local/etc/openvswitch/conf.db ./vswitchd/vswitch.ovsschema 3 4 #start database server 5 ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \ 6 --remote=db:Open_vSwitch,Open_vSwitch,manager_options \ 7 --pidfile --detach --log-file 8 9 #initialize ovs database 10 ovs-vsctl --no-wait init 11 12 #configure ovs dpdk 13 ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true \ 14 other_config:dpdk-lcore=0x2 other_config:dpdk-socket-mem="1024" 15 16 ##start ovs 17 ovs-vswitchd unix:/usr/local/var/run/openvswitch/db.sock \ 18 --pidfile --detach
- 创建ovs ports:
# creat_ports.sh 1 #ovs use core 2 for the PMD 2 ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0x4 3 4 #create br0 and vhost ports which use DPDK 5 ovs-vsctl add-br ovs-br0 -- set bridge ovs-br0 datapath_type=netdev 6 ovs-vsctl add-port ovs-br0 vhost-user0 -- set Interface vhost-user0 type=dpdkvhostuser 7 ovs-vsctl add-port ovs-br0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser 8 ovs-vsctl add-port ovs-br0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser 9 ovs-vsctl add-port ovs-br0 vhost-user3 -- set Interface vhost-user3 type=dpdkvhostuser 10 11 #show ovs-br0 info 12 ovs-vsctl show
- 添加流表
# add_flow.sh 1 #clear current flows 2 ovs-ofctl del-flows ovs-br0 3 4 #add bi-directional flow between vhost-user1 and vhost-user2(port 2 and 3) 5 ovs-ofctl add-flow ovs-br0 \ 6 in_port=2,dl_type=0x800,idle_timeout=0,action=output:3 7 ovs-ofctl add-flow ovs-br0 \ 8 in_port=3,dl_type=0x800,idle_timeout=0,action=output:2 9 #add bi-directional flow between vhost-user0 and vhost-user4(port 1 and 4) 10 ovs-ofctl add-flow ovs-br0 \ 11 in_port=1,dl_type=0x800,idle_timeout=0,action=output:4 12 ovs-ofctl add-flow ovs-br0 \ 13 in_port=4,dl_type=0x800,idle_timeout=0,action=output:1 14 15 #show current flows 16 ovs-ofctl dump-flows ovs-br0
可以检查系统配置如下:
[root@nsfocus openvswitch-2.8.1]# ovs-vsctl show a852baf4-b7ab-44cf-8c73-c9d7031af99d Bridge "ovs-br0" Port "vhost-user3" Interface "vhost-user3" type: dpdkvhostuser Port "vhost-user1" Interface "vhost-user1" type: dpdkvhostuser Port "ovs-br0" Interface "ovs-br0" type: internal Port "vhost-user0" Interface "vhost-user0" type: dpdkvhostuser Port "vhost-user2" Interface "vhost-user2" type: dpdkvhostuser[root@nsfocus openvswitch-2.8.1]# ovs-ofctl show ovs-br0 1(vhost-user0): addr:00:00:00:00:00:00 config: 0 state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max 2(vhost-user1): addr:00:00:00:00:00:00 config: 0 state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max 3(vhost-user2): addr:00:00:00:00:00:00 config: 0 state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max 4(vhost-user3): addr:00:00:00:00:00:00 config: 0 state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max LOCAL(ovs-br0): addr:62:07:93:f5:72:48 config: PORT_DOWN state: LINK_DOWN current: 10MB-FD COPPER speed: 10 Mbps now, 0 Mbps max[root@nsfocus openvswitch-2.8.1]# ovs-ofctl dump-flows ovs-br0 cookie=0x0, duration=89113.410s, table=0, n_packets=655640, n_bytes=21468324000, ip,in_port="vhost-user1" actions=output:"vhost-user2" cookie=0x0, duration=89113.404s, table=0, n_packets=27460, n_bytes=21133440, ip,in_port="vhost-user2" actions=output:"vhost-user1" cookie=0x0, duration=89113.398s, table=0, n_packets=1200940, n_bytes=39358530000, ip,in_port="vhost-user0" actions=output:"vhost-user3" cookie=0x0, duration=89113.392s, table=0, n_packets=15560, n_bytes=11562240, ip,in_port="vhost-user3" actions=output:"vhost-user0"[root@nsfocus openvswitch-2.8.1]# ovs-ofctl dump-ports ovs-br0OFPST_PORT reply (xid=0x2): 5 ports port "vhost-user3": rx pkts=15560, bytes=11562240, drop=0, errs=0, frame=?, over=?, crc=? tx pkts=27460, bytes=21133440, drop=1173480, errs=?, coll=? port "vhost-user1": rx pkts=1748120, bytes=57248848800, drop=0, errs=0, frame=?, over=?, crc=? tx pkts=27460, bytes=21133440, drop=0, errs=?, coll=? port "vhost-user0": rx pkts=1747020, bytes=57248782800, drop=0, errs=0, frame=?, over=?, crc=? tx pkts=15560, bytes=11562240, drop=0, errs=?, coll=? port "vhost-user2": rx pkts=27460, bytes=21133440, drop=0, errs=0, frame=?, over=?, crc=? tx pkts=15560, bytes=11562240, drop=640080, errs=?, coll=? port LOCAL: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=0, bytes=0, drop=0, errs=0, coll=0
至此ovs就启动并配置好了,vhost-user backend口已经创建好,相应的流表路由表项也已经添加好,接下来就该部署container了。
创建testpmd container 和 l2fwd container
前提:系统已经安装了docker,这个过程文档就不再记录
l2fwd和testpmd都属于dpdk提供的app,使用同一个container即可。创建container时把之前build的dpdk目录copy到docker中。
# cd $RTE_SDK/../# cat Dockerfile 1 FROM ubuntu:latest 2 RUN apt update -y 3 RUN apt-get install -y numactl 4 WORKDIR /root/dpdk 5 COPY dpdk-17.05 /root/dpdk/. 6 ENV PATH "$PATH:/root/dpdk/x86_64-native-linuxapp-gcc/app/"# docker build -t dpdk-docker:17.05 .# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEdpdk-docker 17.05 15a8a7206e7c 3 days ago 366.5 MB
创建pktgen docker
同理,把之前编译好的pktgen映射到container中即可。此外需要注意的是,pktgen依赖libpcap,所以需要在container中安装一份。使用时还发现运行container提示无法找到共享库libpcap.so.1, 而安装libpcap后只有libpcap.so,解决办法就是做个软链就可以了。
具体的配置步骤如下:
# cd pktgen-3.4.2/..# cat Dockerfile 1 FROM ubuntu:latest 2 RUN apt update -y 3 RUN apt-get install -y numactl libpcap-dev 4 WORKDIR /root/dpdk 5 COPY dpdk-17.05 /root/dpdk/. 6 COPY pktgen-3.4.2 /root/pktgen/. 7 RUN ln -s /root/pktgen/app/x86_64-native-linuxapp-gcc/pktgen /usr/bin/pktgen 8 RUN ln -s /usr/lib/x86_64-linux-gnu/libpcap.so /usr/lib/x86_64-linux-gnu/libpcap.so.1 9 ENV PATH "$PATH:/root/dpdk/x86_64-native-linuxapp-gcc/app/"# docker build -t pktgen-docker .# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEpktgen-docker latest 371924729d87 23 hours ago 431.7 MBdpdk-docker 17.05 15a8a7206e7c 3 days ago 366.5 M
实验一
- overview
- 启动pktgen
#首先启动docker container[root@nsfocus]# docker run -ti --privileged --name=pktgen-docker \-v /mnt/huge:/mnt/huge -v /usr/local/var/run/openvswitch:/var/run/openvswitch \ pktgen-docker:latestroot@a2603b54d66d:~/pktgen# pktgen -c 0x19 --master-lcore 3 -n 1 --socket-mem 1024,1024 --file-prefix pktgen --no-pci \--vdev 'net_virtio_user0,mac=00:00:00:00:00:05,path=/var/run/openvswitch/vhost-user0' \ --vdev 'net_virtio_user1,mac=00:00:00:00:00:01,path=/var/run/openvswitch/vhost-user1' \-- -T -P -m "0.0,4.1"
- 启动testpmd
[root@nsfocus ~]# docker run -it --privileged --name=dpdk-docker \ -v /mnt/huge:/mnt/huge -v /usr/local/var/run/openvswitch:/var/run/openvswitch \dpdk-docker:17.05root@bdbe9fabe89a:~/dpdk/examples/l2fwd/build# cd ~/dpdk/x86_64-native-linuxapp-gcc/app/root@bdbe9fabe89a:~/dpdk/x86_64-native-linuxapp-gcc/app# testpmd -c 0xE0 -n 1 --socket-mem 1024,1024 --file-prefix testpmd --no-pci \--vdev 'net_virtio_user2,mac=00:00:00:00:00:02,path=/var/run/openvswitch/vhost-user2' \--vdev 'net_virtio_user3,mac=00:00:00:00:00:03,path=/var/run/openvswitch/vhost-user3' \-- -i --burst=64 --disable-hw-vlan --txd=2048 --rxd=2048 -a --coremask=0xc0
- 发包验证
在pktgen端执行:
# 在pktgen中设置速率为10%,更具体的速率设置可以通过tx_cycles设置# 端口0共发送100个包,端口1发送200个Pktgen:/>set all rate 10Pktgen:/>set 0 count 100Pktgen:/>set 1 count 200Pktgen:/>str
pktgen端:
testpmd端:
ovs端:
实验二
- overview
2. 启动pktgen
#首先启动docker container[root@nsfocus]# docker run -ti --privileged --name=pktgen-docker \-v /mnt/huge:/mnt/huge -v /usr/local/var/run/openvswitch:/var/run/openvswitch \pktgen-docker:latestroot@a2603b54d66d:~/pktgen# pktgen -c 0x19 --master-lcore 3 -n 1 --socket-mem 1024,1024 --file-prefix pktgen --no-pci \--vdev 'net_virtio_user0,mac=00:00:00:00:00:05,path=/var/run/openvswitch/vhost-user0' \--vdev 'net_virtio_user1,mac=00:00:00:00:00:01,path=/var/run/openvswitch/vhost-user1' \-- -T -P -m "0.0,4.1"
- 启动l2fwd
[root@nsfocus ~]# docker run -it --privileged --name=dpdk-docker \-v /mnt/huge:/mnt/huge -v /usr/local/var/run/openvswitch:/var/run/openvswitch \dpdk-docker:17.05root@bdbe9fabe89a:~/dpdk/examples/l2fwd/build#./l2fwd -c 0xE0 -n 1 --socket-mem 1024,1024 --file-prefix testpmd --no-pci \ --vdev 'net_virtio_user2,mac=00:00:00:00:00:02,path=/var/run/openvswitch/vhost-user2' \ --vdev 'net_virtio_user3,mac=00:00:00:00:00:03,path=/var/run/openvswitch/vhost-user3' \ -- -p 0x3
- 发包验证
在pktgen端执行:
# 在pktgen中设置速率为10%,更具体的速率设置可以通过tx_cycles设置# 端口0共发送100个包,端口1发送200个Pktgen:/>set all rate 10Pktgen:/>set 0 count 100Pktgen:/>set 1 count 200Pktgen:/>str
pktgen端:
l2fwd端:
说明l2fwd已按照我们的预想进行了报文的转发。
总结
本次实践主要还是集中在OVS上面的container App的互通以及container内部对dpdk的支持,分别验证了在container内部运行testpmd和l2fwd来进行报文转发。其中,dpdk app的运行模式可以为后续cneos平台server docker化提供一定的技术指导作用。
如果从更系统化的层面来考虑docker结合ovs以及dpdk的使用,更通用的使用场景应该是这样的:在ovs的南向通过dpdk pmd和硬件平台上物理nic的PF或VF绑定,高速收发报文;在ovs的北向,通过virtual device和docker container来共享收发报文,进行上层业务的处理。 南北向之间的流量需要配置flow table来指导转发。流量示意如下图所示:
1. 流量从物理port流入,到达OVS查找流表送入到串联检测类container1(如NF,IPS)中,container1处理完后再送回流表,再次查找流表找到物理口发送出去
2. 流量从物理port流入,到达OVS查找流表送入到检测类container2中(如WAF)
3. 考虑到有多个安全container app,流量串行通过containerN,container2; 实际上,container之间的数据交互还有别的实现方式,如docker天然支持容器互联技术,这块还有待进一步确定实际方案
参考资料
- http://dpdk.org/doc/guides/howto/virtio_user_for_container_networking.html?highlight=container
- http://docs.openvswitch.org/en/latest/intro/install/dpdk/
- http://www.sdnlab.com/20112.html
- https://www.slideshare.net/MichelleHolley1/dpdk-in-containers-handson-lab
- ovs+dpdk-docker实践
- Ovs+Dpdk简单实践
- OVS+DPDK
- ovs-dpdk 在美团云环境中的应用与实践
- ovs + dpdk版本说明
- ovs + dpdk版本说明
- ovs+dpdk测试总结
- ovs+dpdk测试总结
- 还用ovs+dpdk?
- 使用OVS DPDK
- 2017 DPDK summit 主讲美团云&OVS-DPDK
- 使用OVS DPDK (by quqi99)
- centos6.5使用ovs-dpdk
- ovs+dpdk bond功能总结
- DPDK+OVS+qemu环境测试
- ovs-dpdk和ovs-kernel的checksum处理
- ovs原生和ovs+dpdk iperf3测试结果对比
- 在Ubuntu下安装ovs-dpdk
- jsp页面接收到ajax发回来的data是个原页面的html解决
- Android Studio中各种jdk和sdk的类找不到,提示setup jdk
- CSS基本知识
- 深入理解Java并发机制(4)--AQS、ReentrantLock、ReentrantReadWriteLock源码分析
- ReactNative网络获取数据在Android平台5.0以下https访问失败的问题
- ovs+dpdk-docker实践
- python中显示图片和文字
- Linux进程间通信——使用共享内存
- GPRS的接入
- 钛媒体发布全新品牌「72问」,All in知识付费
- 卖完电视卖电脑,百年东芝是怎么没落的?
- 腾讯市值首破5000亿美元;阿里224亿港币入股高鑫零售;特斯拉新超跑在华接受预定丨价值早报
- 创投日报:11月20日收录投融资项目17起
- c# 一次性插入多条数据