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,如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m130RYst-1658817337021)(http://dpdk.org/doc/guides/_images/use_models_for_running_dpdk_in_containers.svg)]
上图(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中涉及的组件如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mo51hKpO-1658817337022)(http://dpdk.org/doc/guides/_images/virtio_user_for_container_networking.svg)]

方案中使用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.xz
tar -xvf dpdk-17.05.tar.xz
cd 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  >> ~/.bashrc
source ~/.bashrc#配置DPDK,需要使用Vhost-user驱动,需要将CONFIG_RTE_LIBRTE_VHOST=y
vim config/common_base#安装dpdk
make config T=$RTE_TARGET
make 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/hugepages
mount -t hugetlbfs none /dev/hugepages
mkdir -p /mnt/huge
mount -t hugetlbfs -o pagesize=1G none /mnt/huge

pktgen 安装

pktgen的安装依赖于DPDK,安装前确保RTE_SDK和RTE_TARGET环境变量设置正确。

#安装依赖
yum install -y libpcap.x86_64
wget http://www.dpdk.org/browse/apps/pktgen-dpdk/snapshot/pktgen-3.4.2.tar.gz
tar -xvf pktgen-3.4.2.tar.gz
cd pktgen-3.4.2
make -j8
ln -s $(pwd)/app/$RTE_TARGET/pktgen /usr/bin/pktgen

ovs 安装与配置

  1. 安装ovs:
#下载
wget http://openvswitch.org/releases/openvswitch-2.8.1.tar.gz
#解压
tar xzvf openvswitch-2.8.1.tar.gz
cd openvswitch-2.8.1
#配置环境并安装
./boot.sh
CFLAGS='-march=native' ./configure --with-dpdk=$RTE_SDK/$RTE_TARGET
make
make install#查看大页内存
cat /proc/meminfo
AnonHugePages:     32768 kB
HugePages_Total:       8
HugePages_Free:        4
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:    1048576 kB
  1. 启动ovs:
#start_ovs.sh1 #init new ovs database2 ovsdb-tool create /usr/local/etc/openvswitch/conf.db ./vswitchd/vswitch.ovsschema3 4 #start database server5 ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \6     --remote=db:Open_vSwitch,Open_vSwitch,manager_options \7     --pidfile --detach --log-file8 9 #initialize ovs database10 ovs-vsctl --no-wait init11 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 ovs17 ovs-vswitchd unix:/usr/local/var/run/openvswitch/db.sock \18     --pidfile --detach
  1. 创建ovs ports:
# creat_ports.sh1 #ovs use core 2 for the PMD2 ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0x43 4 #create br0 and vhost ports which use DPDK5 ovs-vsctl add-br ovs-br0 -- set bridge ovs-br0 datapath_type=netdev6 ovs-vsctl add-port ovs-br0 vhost-user0 -- set Interface vhost-user0 type=dpdkvhostuser7 ovs-vsctl add-port ovs-br0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser8 ovs-vsctl add-port ovs-br0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser9 ovs-vsctl add-port ovs-br0 vhost-user3 -- set Interface vhost-user3 type=dpdkvhostuser10 11 #show ovs-br0 info12 ovs-vsctl show
  1. 添加流表
# add_flow.sh1 #clear current flows2 ovs-ofctl del-flows ovs-br03 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:37 ovs-ofctl add-flow ovs-br0 \8     in_port=3,dl_type=0x800,idle_timeout=0,action=output:29 #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:412 ovs-ofctl add-flow ovs-br0 \13     in_port=4,dl_type=0x800,idle_timeout=0,action=output:114 15 #show current flows16 ovs-ofctl dump-flows ovs-br0

可以检查系统配置如下:

[root@nsfocus openvswitch-2.8.1]# ovs-vsctl show
a852baf4-b7ab-44cf-8c73-c9d7031af99dBridge "ovs-br0"Port "vhost-user3"Interface "vhost-user3"type: dpdkvhostuserPort "vhost-user1"Interface "vhost-user1"type: dpdkvhostuserPort "ovs-br0"Interface "ovs-br0"type: internalPort "vhost-user0"Interface "vhost-user0"type: dpdkvhostuserPort "vhost-user2"Interface "vhost-user2"type: dpdkvhostuser[root@nsfocus openvswitch-2.8.1]# ovs-ofctl show ovs-br01(vhost-user0): addr:00:00:00:00:00:00config:     0state:      LINK_DOWNspeed: 0 Mbps now, 0 Mbps max2(vhost-user1): addr:00:00:00:00:00:00config:     0state:      LINK_DOWNspeed: 0 Mbps now, 0 Mbps max3(vhost-user2): addr:00:00:00:00:00:00config:     0state:      LINK_DOWNspeed: 0 Mbps now, 0 Mbps max4(vhost-user3): addr:00:00:00:00:00:00config:     0state:      LINK_DOWNspeed: 0 Mbps now, 0 Mbps maxLOCAL(ovs-br0): addr:62:07:93:f5:72:48config:     PORT_DOWNstate:      LINK_DOWNcurrent:    10MB-FD COPPERspeed: 10 Mbps now, 0 Mbps max[root@nsfocus openvswitch-2.8.1]# ovs-ofctl dump-flows ovs-br0cookie=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-br0
OFPST_PORT reply (xid=0x2): 5 portsport  "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=0tx 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 Dockerfile1 FROM ubuntu:latest2 RUN apt update -y3 RUN apt-get install -y  numactl4 WORKDIR /root/dpdk5 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 images
REPOSITORY                                  TAG                 IMAGE ID            CREATED             SIZE
dpdk-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 Dockerfile1 FROM ubuntu:latest2 RUN apt update -y3 RUN apt-get install -y  numactl libpcap-dev4 WORKDIR /root/dpdk5 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/pktgen8 RUN ln -s /usr/lib/x86_64-linux-gnu/libpcap.so /usr/lib/x86_64-linux-gnu/libpcap.so.19 ENV PATH "$PATH:/root/dpdk/x86_64-native-linuxapp-gcc/app/"
# docker build -t pktgen-docker .
# docker images
REPOSITORY                                  TAG                 IMAGE ID            CREATED             SIZE
pktgen-docker                               latest              371924729d87        23 hours ago        431.7 MB
dpdk-docker                                 17.05               15a8a7206e7c        3 days ago          366.5 M

实验一

  1. overview
App parameter thread Core Mask
Open vSwitch dpdk-lcore-mask=0x2 daemon 0000 0010
- pmd-cpu-mask=0x4 DPDK PMD 0000 0100
pktgen -c 0x19 GUI& Messages 0001 1001
- –master-lcore 3 DPDK master lcore 0000 1000
- -m “0.0,4.1” DPDK PMD core 0:port 0, core 4:port 1
testpmd -c 0xE0 testpmd DPDK PMD 1110 0000
  1. 启动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:latest
root@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"
  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.05
root@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
  1. 发包验证
    在pktgen端执行:
# 在pktgen中设置速率为10%,更具体的速率设置可以通过tx_cycles设置
# 端口0共发送100个包,端口1发送200个
Pktgen:/>set all rate 10
Pktgen:/>set 0 count 100
Pktgen:/>set 1 count 200
Pktgen:/>str

pktgen端:

testpmd端:

ovs端:

实验二

  1. overview
App parameter thread Core Mask
Open vSwitch dpdk-lcore-mask=0x2 daemon 0000 0010
- pmd-cpu-mask=0x4 DPDK PMD 0000 0100
pktgen -c 0x19 GUI& Messages 0001 1001
- –master-lcore 3 DPDK master lcore 0000 1000
- -m “0.0,4.1” DPDK PMD core 0:port 0, core 4:port 1
l2fwd -c 0xE0 l2fwd DPDK PMD 1110 0000
  1. 启动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:latest
root@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"
  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.05
root@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
  1. 发包验证
    在pktgen端执行:
# 在pktgen中设置速率为10%,更具体的速率设置可以通过tx_cycles设置
# 端口0共发送100个包,端口1发送200个
Pktgen:/>set all rate 10
Pktgen:/>set 0 count 100
Pktgen:/>set 1 count 200
Pktgen:/>str

pktgen端:

l2fwd端:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eoDSNQMT-1658817337025)(http://ww1.sinaimg.cn/large/411271bbly1fll3rlte76j20f408n74j.jpg)]

说明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天然支持容器互联技术,这块还有待进一步确定实际方案

参考资料

  1. http://dpdk.org/doc/guides/howto/virtio_user_for_container_networking.html?highlight=container
  2. http://docs.openvswitch.org/en/latest/intro/install/dpdk/
  3. http://www.sdnlab.com/20112.html
  4. https://www.slideshare.net/MichelleHolley1/dpdk-in-containers-handson-lab

ovs+dpdk-docker实践相关推荐

  1. OVS+DPDK Datapath 包分类技术

    本文主体内容译于[DPDK社区文档],但并没有逐字翻译,在原文的基础上进行了一些调整,增加了对TSS分类器的详细阐述. 1. 概览 本文描述了OVS+DPDK中的包分类器(datapath class ...

  2. 携程Docker实践

    原文地址:http://www.iteye.com/news/31468         请点击原文阅读 ---------------------以下是原文--------------------- ...

  3. OVS DPDK vs OVS Deep Dive(十六)

    背景 OvS(Open vSwitch)是云计算平台的重要连接组件,为虚拟机提供网络连,被各大云平台,基础设施供应商广泛使用,比如OpenStack, OpenNebula.vSwitch–Virtu ...

  4. OVS DPDK vhost-user详解(十三)

    vhost user协议的控制和数据通道 所有的控制信息通过UNIX套接口(控制通道)交互.包括为进行直接内存访问而交换的内存映射信息,以及当数据填入virtio队列后需要出发的kick事件和中断信息 ...

  5. Docker实践,来自沪江、滴滴、蘑菇街架构师的交流分享

    架构师小组交流会:每期选一个时下最热门的技术话题进行实践经验分享. 第一期主题:容器实践.Docker 作为当前最具颠覆性的开源技术之一,其轻量虚拟化.可移植性是CI/CD,DevOps,微服务的重要 ...

  6. Docker实践:Cannot connect to the Docker daemon.

    Docker实践:Cannot connect to the Docker daemon. 查看docker daemon是否在运行 [root@localhost openec]#  ps aux ...

  7. Docker实践(七)部署SpringBoot微服务

    目录 打包 编写DockerFile 构建镜像 创建容器并启动容器 测试 打包 使用maven或者其他构建工具,打包可运行jar或者war,这里使用可运行jar进行部署. 编写DockerFile 创 ...

  8. docker实践(2)常用命令和DockerFile详解

    <docker实践(1) 入门和springBoot实践部署> <docker实践(2)常用命令和DockerFile详解> <docker实践(3) 仓库registr ...

  9. Windows 10中的Docker实践

    题记 微软在人们的心目中就是商业化的代名词,操作系统.Office.数据库.Azure等可能是我们耳熟能详的,当然微软也在布局更多的技术王国.开源界对微软一直嗤之以鼻,指责其闭源行为影响技术的发展,不 ...

  10. Docker实践7:容器与主机拷贝数据

    在Docker实践2中使用-v参数将主机与容器中相关目录联系在一起(挂载),所以我们可以用这个通道将想要互相拷贝的数据放入其中,这样就可以用cp命令来复制文件了. 除了这个办法,我们还可以分别用不同的 ...

最新文章

  1. oracle修改时区无效,Oracle 时区问题
  2. opencv-contrib配置过程
  3. 解决IndexClosedException: closed
  4. 创新创业计划书_创践——大学生创新创业实务 ——如何撰写一份优秀的商业计划书...
  5. CG-CTF-Web-伪装者
  6. leetcode979. 在二叉树中分配硬币(dfs)
  7. redis设置密码(redis-cli)
  8. js中prototype用法
  9. Windows系统cmd命令检测dll文件
  10. Elasticsearch一些常用操作和一些基础概念
  11. 65. 布置行内脚本
  12. 【java】蔡勒公式计算星期(switch语句方法和数组方法)
  13. 12 个追地铁的人:照亮生活的一次追逐
  14. 空格变成问号的怪问题
  15. UWB-DW1000 在8位单片机上移植使用
  16. 单目标跟踪 (一)相关滤波器 方法综述
  17. 基于阿里云生态构建网聚宝业务监控系统
  18. illustrator插件-画板功能开发-插入页码-js脚本开发-ai插件
  19. 学计算机键盘用什么轴,机械键盘别再盲目的选择,看看四种常用轴到底适合什么用途...
  20. 一剂拯救“国足”的终极药方:全面 AI 化

热门文章

  1. AirPods 2/Pro 使用方法
  2. 初创期企业运营必备手册-工具包-股权激励方案及合同工具包
  3. 每天早晨的问候能够彻底的改善你的人脉关系
  4. Adobe PhotoShop 2020 特别版
  5. 骁龙660鸿蒙系统,高通骁龙670和660区别大吗?骁龙670有哪些升级?
  6. hive map格式转换为字符串_Hive学习之Hive数据类型 | 学步园
  7. Linux磁盘占满,如何清理磁盘空间
  8. Rstudio中读取Excel中数据的详细步骤。
  9. underscore-1.8.3.js 源码解读全文注释版
  10. 百度上线“濒危物种AI守护官”:用科技为文明护航