Running Containers With OVS-DPDK


 

DPDK(Data Plane Development Kit),即數據平面開發工具包,是一組用於快速數據包處理的數據平面庫和網絡接口控制器驅動程序,DPDK 為 x86,ARM 和 PowerPC 處理器提供編程框架,可以更快地開發高速數據包網絡應用程序。該平台采用 BSD 許可證發布,目前作為 Linux Foundation 下的開源項目進行管理。

在 X86 架構中,處理數據包的傳統方式是 CPU 中斷方式,即網卡驅動接收到數據包后通過中斷通知 CPU 處理,然后由 CPU 拷貝數據並交給協議棧。在數據量大時,這種方式會產生大量 CPU 中斷,導致 CPU 無法運行其他程序。而 DPDK 則采用輪詢方式實現數據包處理過程:DPDK 重載了網卡驅動,在收到數據包后不中斷通知 CPU,而是將數據包通過零拷貝技術存入內存,這時應用層程序就可以通過 DPDK 提供的接口,直接從內存讀取數據包。這種處理方式節省了 CPU 中斷時間、內存拷貝時間,並向應用層提供了簡單易行且高效的數據包處理方式,使得網絡應用的開發更加方便。但同時,由於需要重載網卡驅動,因此該開發包目前只能用在部分網絡處理芯片的網卡中。

OVS-DPDK 是什么

OVS-DPDK 的數據平面通過 DPDK 快速通道進行處理,DPDK 的 PMD 模型使得數據收發繞過內核協議棧,達到數據包的快速收發。OVS-DPDK 有三層緩存表:Exact Match Cache(EMC)完全匹配緩存,無法通過通配符匹配;tuple space search (TSS) 元組空間搜索,使用 hash 表實現,可以通過通配符匹配; ofproto classifier table,被兼容 openflow 的控制器進行管理。

OVS-DPDK 與物理網卡的連接方式:利用 DPDK 提供的工具,使物理 NIC 直接綁定到 UIO 驅動上面,將物理網卡作為一個 port 綁定到 OVS-DPDK 上。這種情況下物理網卡將對系統不可見,也無法使用系統工具對網卡進行配置。

OVS with DPDK

OVS-DPDK 為容器提供網絡支持

基於 DPDK 的應用

DPDK 官網容推薦器內運行 DPDK 應用有的兩種模型,分片和匯聚,如下圖所示。

use_models_for_running_dpdk_in_containers

圖 2 方案可以使用 vswitch 將上層的容器和底層的物理 NIC 解耦,可以通過 OVS-DPDK 實現高性能的容器應用。OVS-DPDK 可以創建 dpdkvhostuser 模式的 DPDK port,將這個 port mount 進容器的 network namespace 可以作為容器的虛擬網絡接口,容器里面的 DPDK PMD 程序可以使用經過改進的 virtio-user 連接這個 port,通過 hugepage 內存區域(shared 模式)建立起到 OVS-DPDK 和物理 NIC 的高速數據通道。經過 OVS 流表配置,可以做到東西向和南北向的數據通道加速,整個過程 by-pass 宿主機的內核。

Intel 實現了 vhost-user-net-plugin cni 插件,實現在 OVS-DPDK 上建立 dpdkvhostuser 模式的 DPDK port,這個 port mount 進容器作為容器的虛擬網絡接口,供 DPDK 應用使用。其結構如下所示:

vhost user net plugin

DPDK 繞過了 Linux 內核協議棧,加速了數據的處理,用戶可以在用戶空間定制協議棧,滿足自己的應用需求。用戶業務可以借助 mTCP、f-stack 等用戶態協議棧對業務應用進行改造,優化網絡性能,實現高性能的網絡應用。

基於內核協議棧的應用

基於內核協議棧的應用容器內部沒有 virtio PMD 程序運行,所以只能連接傳統的 OVS 端口,主要有兩種可以參考的方案:

  • 使用 veth 對連接容器和 ovs,在這種模式下 ovs 將回落到 system datapath(如圖1所示);
  • 使用 tap 將數據轉發到 ovs-dpdk 的 virtio-user 接口,然后使用 dpdk 進行加速,在 tap 轉發到 virtio-user 接口時會造成一次內存拷貝,會造成性能損失(如圖2所示)。

兩種模式都可以再通過設置 OVS 流表,將這些數據傳輸到基於 DPDK PMD 的 type=dpdk 的端口,這樣可以在數據傳輸出網卡的后半程使用 DPDK 加速。這種情況下,數據在進入 OVS 端口並進行轉發到 OVS DPDK PMD 綁定的 NIC 端口之后,就進入了 DPDK 高速通道。

OVS-DPDK 容器網絡方案驗證

搭建 DPDK 環境

1)、編譯 dpdk

 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 
# install build dependencies yum makecache sudo yum install -y autoconf automake libtool wget vim gcc \  gcc-c++ kernel-devel kernel-headers kernel net-tools \  numactl-devel numactl-libs libpcap libpcap-devel pciutils \  python-six python-twisted-core python-zope-interface \  openssl-devel openssl-libs # download dpdk 17.11.3 wget http://fast.dpdk.org/rel/dpdk-17.11.3.tar.xz tar -xvf dpdk-17.11.3.tar.xz # build dpdk export DPDK_DIR=/root/ovs-dpdk/dpdk-stable-17.11.3 export DPDK_TARGET=x86_64-native-linuxapp-gcc export DPDK_BUILD=$DPDK_DIR/$DPDK_TARGET export RTE_SDK=$DPDK_DIR export RTE_TARGET=x86_64-native-linuxapp-gcc make install T=$DPDK_TARGET DESTDIR=install RTE_SDK=`pwd` 

2)、配置 dpdk 環境

 1  2  3  4  5  6  7  8  9 10 11 
# 加載 igb_uio 模塊 modprobe uio_pci_generic modprobe uio modprobe vfio-pci insmod build/kmod/igb_uio.ko # 在 grub.cfg 中添加參數分配1G大頁 default_hugepagesz=1GB hugepagesz=1G hugepages=4 # 在 grub.cfg 中添加參數啟用 iommu iommu=pt intel_iommu=on 

查看系統的大頁支持情況:

 

3)、綁定網卡,並測試 dpdk 環境是否 ok

查看當前的網卡驅動綁定狀態:

1 
 ./usertools/dpdk-devbind.py --status

綁定網卡到 igb_uio 驅動:

1 2 3 4 
ip link set ens4 down ip link set ens9 down ./usertools/dpdk-devbind.py --bind=igb_uio ens4 ./usertools/dpdk-devbind.py --bind=igb_uio ens9 

運行 testpmd 程序進行測試,可以看到數據包在兩個接口間的轉發情況,表示 dpdk 環境安裝ok:

1 
./x86_64-native-linuxapp-gcc/app/testpmd -- -i

編譯運行 OVS-DPDK

1)、編譯 OVS-DPDK (注意 ovs 和 dpdk 的版本是否匹配,參考官網 FAQ)

1 2 3 4 5 6 7 8 9 
# 下載 openvswitch 2.9.2 源碼 wget http://openvswitch.org/releases/openvswitch-2.9.2.tar.gz # build and install LANGUAGE=en_US.UTF-8 LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 ./boot.sh ./configure --with-dpdk=$DPDK_BUILD \  --prefix=/usr --sysconfdir=/etc \  --localstatedir=/var make && make install 

2)、配置 ovs-dpdk

 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 
# 啟動 ovs-dpdk /usr/share/openvswitch/scripts/ovs-ctl start # 配置 ovs-dpdk ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem="1024,0" ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask=0x2 # 創建一個支持 dpdk 的網橋 ovs-vsctl add-br ovs-br0 -- set bridge ovs-br0 datapath_type=netdev # 創建 dpdk 接口並綁定到物理網卡 ovs-vsctl add-port ovs-br0 dpdkprot01 -- set Interface dpdkprot01 type=dpdk options:dpdk-devargs=0000:00:08.0 # 創建 dpdk vhost-user 接口 ovs-vsctl add-port ovs-br0 vhost-user0 -- set Interface vhost-user0 type=dpdkvhostuser ovs-vsctl add-port ovs-br0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser # 創建流表 ovs-ofctl add-flow ovs-br0 in_port=1,idle_timeout=0,action=output:2 ovs-ofctl add-flow ovs-br0 in_port=2,idle_timeout=0,action=output:1 

DPDK 應用的容器

實驗環境:

  • 支持 dpdk 的網橋 ovs-br0
  • 4個 dpdk vhost-user 接口
  • pktgen 容器(用於生成數據包)和 testpmd 容器(流量轉發)
  • 配置流表 2<–>3 1<–>4

連接情況如下:

 

1)、構建 pktgen 和 testpmd 鏡像

pkktgen Dockerfile 如下:

1 2 3 4 
FROM centos:latest RUN yum update -y && yum install -y iproute numactl-libs numactl libpcap pciutils COPY ./pktgen-3.5.0/ /root/pktgen-3.5.0 WORKDIR /root/pktgen-3.5.0

testpmd Dockerfile 如下:

1 2 3 4 
FROM centos:latest RUN yum update -y && yum install -y iproute numactl-libs numactl libpcap pciutils COPY ./dpdk-stable-17.11.3/ /root/dpdk-stable-17.11.3/ WORKDIR /root/dpdk-stable-17.11.3

2)、運行並設置 ovs-dpdk

 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 
# 啟動 ovs-dpdk /usr/share/openvswitch/scripts/ovs-ctl start # 配置 ovs-dpdk ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem="1024,0" # 創建一個支持 dpdk 的網橋 ovs-vsctl add-br ovs-br0 -- set bridge ovs-br0 datapath_type=netdev # 創建 dpdk 接口並綁定到物理網卡 ovs-vsctl add-port ovs-br0 dpdkprot01 -- set Interface dpdkprot01 type=dpdk options:dpdk-devargs=0000:00:08.0 # 創建 dpdk vhost-user 接口 ovs-vsctl add-port ovs-br0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser ovs-vsctl add-port ovs-br0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser ovs-vsctl add-port ovs-br0 vhost-user3 -- set Interface vhost-user3 type=dpdkvhostuser ovs-vsctl add-port ovs-br0 vhost-user4 -- set Interface vhost-user4 type=dpdkvhostuser # 創建流表 ovs-ofctl del-flows ovs-br0 # 刪除當前流表 ovs-ofctl add-flow ovs-br0 in_port=1,idle_timeout=0,action=output:4 ovs-ofctl add-flow ovs-br0 in_port=4,idle_timeout=0,action=output:1 ovs-ofctl add-flow ovs-br0 in_port=2,idle_timeout=0,action=output:3 ovs-ofctl add-flow ovs-br0 in_port=3,idle_timeout=0,action=output:2 

系統狀態如下:

 

3)、創建 pktgen 容器和 testpmd 容器,運行測試

 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 
# 運行 pktgen 容器 docker run -i -t --rm --privileged \  -v /dev/hugepages:/dev/hugepages \  -v /var/run/openvswitch:/var/run/openvswitch pktgen-docker # 在容器內運行 pktgen 程序,連接 vhost-user1 vhost-user2 ./app/x86_64-native-linuxapp-gcc/pktgen \  --socket-mem 1024 --file-prefix pktgen --no-pci \  --vdev 'net_virtio_user1,mac=00:00:00:00:00:05,path=/var/run/openvswitch/vhost-user1' \  --vdev 'net_virtio_user2,mac=00:00:00:00:00:01,path=/var/run/openvswitch/vhost-user2' \  -- -T -P -m "2.0,2.1" # 運行 dpdk 容器 docker run -i -t --rm --privileged \  -v /dev/hugepages:/dev/hugepages \  -v /var/run/openvswitch:/var/run/openvswitch dpdk-docker # 在容器中運行 testpmd 程序,連接 vhost-user3 vhost-user4 ./x86_64-native-linuxapp-gcc/app/testpmd \  --socket-mem 1024 --file-prefix testpmd-docker --no-pci \  --vdev 'virtio_user3,mac=00:00:00:00:00:02,path=/var/run/openvswitch/vhost-user3' \ --vdev 'virtio_user4,mac=00:00:00:00:00:03,path=/var/run/openvswitch/vhost-user4' \  -- -i --burst=64 --disable-hw-vlan --rxq=1 --txq=1 --rxd=256 --txd=256 -a 

在 pktgen 應用中設置發送到數據包數量,發送頻率:

1 2 3 4 
set all rate 10 set 0 count 200 # 端口0發送200個包 set 1 count 100 # 端口1發送100個包 str # 啟動發包 

我們可以在 testpmd 中看到數據包的狀態,使用命令 show port stats all 可以看到接口轉發的包情況。結果如下圖所示:

在 pktgen 中可以看到數據包發送接收情況,結果如下圖:

也可以從 ovs 的接口中讀到數據包的轉發情況:

基於內核協議棧的應用(使用 veth pair 連接 ovs-dpdk)

實驗環境:

  • 支持 dpdk 的網橋 ovs-br0
  • 使用 ovs-docker 為容器添加網絡
  • 兩個 centos 容器(互相 ping 測試)
  • 配置流表

1)、創建兩個 centos 容器

1 
docker run -i -t --rm --network=none centos 

2)、使用 ovs-docker 配置容器網絡

1 2 
ovs-docker add-port ovs-br0 eth1 c13983ca7a73 --ipaddress=192.168.99.100/24 --gateway=192.168.99.1 --macaddress="a2:c3:0d:49:7f:f8" --mtu=1450 ovs-docker add-port ovs-br0 eth1 31ad2f628b48 --ipaddress=192.168.99.101/24 --gateway=192.168.99.1 --macaddress="a2:c3:0d:49:7f:f9" --mtu=1450 

從 ovs-br0 上可以看到多了兩個接口:

為這兩個接口添加流表:

1 2 
ovs-ofctl add-flow ovs-br0 in_port=6,idle_timeout=0,action=output:5 ovs-ofctl add-flow ovs-br0 in_port=5,idle_timeout=0,action=output:6 

3)、測試容器網絡

根據設置的 ip,讓兩個容器互相 ping ,觀察結果如下,兩個容器可以互相 ping 通:

4)、分析 ovs-docker 命令

ovs-docker 命令是 ovs 官方提供的為容器添加網絡支持的 python 腳本,其中添加端口的流程如下:

  • 創建 nate namespace
  • 創建 veth 對
  • 將 veth 對的一端添加到 ovs 上
  • 將 veth 對的另一端加入到 net namespace 中,設置網卡名,ip,網關等信息

基於內核協議棧的應用(使用 tap 連接 ovs-dpdk 的 virtio-user 接口)

實驗環境:

  • 支持 dpdk 的網橋 ovs-br0
  • 使用 ovs-docker 為容器網絡
  • 兩個 centos 容器(互相 ping 測試)
  • 配置流表

1 2 3 4 5 6 7 8 9 
# 加載 vhost 模塊 modprobe vhost modprobe vhost_net # container----tap----vhost-net----ovs ovs-vsctl add-port ovs-br0 virtiouser0 -- set Interface virtiouser0 type=dpdk options:dpdk-devargs=virtio_user0,path=/dev/vhost-net,iface=virtiouser0 # container----tap----tap pmd----ovs ovs-vsctl add-port ovs-br0 tap01 -- set Interface tap01 type=dpdk options:dpdk-devargs=net_tap01,path=/dev/vhost-net,iface=tap01 

廠商方案

美團點評容器平台網絡架構

數據平面: 采用萬兆網卡,結合 OVS-DPDK 方案,並進一步優化單流的轉發性能,將幾個 CPU 核綁定給 OVS-DPDK 轉發使用,只需要少量的計算資源即可提供萬兆的數據轉發能力。OVS-DPDK 和容器所使用的 CPU 完全隔離,因此也不影響用戶的計算資源。

控制平面: 我們使用 OVS 方案。該方案是在每個宿主機上部署一個自研的軟件 Controller,動態接收網絡服務下發的網絡規則,並將規則進一步下發至OVS流表,決定是否對某網絡流放行。

2017年總結優化:

  • SRIOV 方式優化 local 性能。KNI 和 TAP 是常用的 DPDK 網絡設備和內核數據交互的方案,為了提升 Local port 的性能,滿足一些宿主機特殊場景。美團雲將 SRIOV 和 BOND 結合,優化 OVS-DPDK bridge 的 local port 性能,現在 Local 可以跑滿萬兆。
  • OVS-DPDK 進程重啟時間長,一直是存在的一個重要問題。美團雲在今年上半年,重點解決了這個問題。這里采用的方案主要是雙進程模式,以及 dpdk vhost 后端雙進程模式,同時也對 restore flow 時間做了優化。60+VM,10G,2000 條流表的情況下,原生 OVS-DPDK 需要 2min+ 時間,經過改造后,可以達到 1s 以內。達到了 OVS-DPDK 進程平滑熱升級,以及故障快速自恢復的功能。
  • 跨 OVS-kernel 和 OVS-DPDK 熱遷移。這里主要需要解決 OVS-DPDK 對 TSO、UFO 等 feature 支持, 因為原 OVS-kernel 的 VM 是默認打開這些 feature 的。而且需要解決 VM->VM, VM-NIC, VM-LOCAL, LOCAL->NIC 等多個路徑的 offload 操作。

網易

網易的 ovs-dpdk 使用方案未知,網易的容器主要運行在虛擬機中,ovs-dpdk 的使用方案可能會是 ovs 端創建 dpdkvhostuser 接口,虛擬機啟動會通過 virtio 驅動加載出 dpdk 的網卡,以此提供網絡加速。 網易使用 OVS+VXLAN 方案。 網絡層面:基於 DPDK/SR-IOV 實現高速網絡包轉發,網絡包處理能力接近150W; DDoS 攻擊防護:基於 Intel DPDK 技術實現高性能實時抗攻擊

Intel

Intel Developer Zone 上一篇文章使用 ovs-dpdk 為 Docker 提供網絡,其使用的方案為 veth 對直接連接容器和 ovs,文章地址為: Using Docker* Containers with Open vSwitch* and DPDK on Ubuntu* 17.10 | Intel® Software

intel 在 2017 年 dpdk summit 上對 dpdk 提供容器網絡加速,對於 tcp/ip 協議棧的應用提出了下面三種模型

1、 使用 tap 將數據轉發到 ovs-dpdk 中處理數據。

2、VF 作為容器網卡,然后在通過 dpdk 連接的 VF 接口轉發到 ovs 處理,整個過程會 by-pass 內核,但其會受到物理網卡的限制。

3、容器跑在虛擬機中

 

參考文章


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM