Intel HDSLB 高性能四层负载均衡器 — 基本原理和摆设配置 ...

打印 上一主题 下一主题

主题 840|帖子 840|积分 2520

前言

在上一篇《Intel HDSLB 高性能四层负载均衡器 — 快速入门和应用场景》中,我们着重介绍了 HDSLB(High Density Scalable Load Balancer,高密度可扩展的负载均衡器)作为新一代高性能四层负载均衡器的需求定位、分析了 HDSLB 在云盘算和边缘盘算应用场景中的特性优势,以及解读了 HDSLB 的性能测试数据。
再进一步的,在本篇中我们主要关注 HDSLB 的基本运行原理和摆设配置方式,更侧重于实际的操作。为了让更广泛的开辟者们都能够快捷方便的对 HDSLB 展开研究,所以在本篇中会采用 HDSLB-DPVS 开源版本来进行介绍。
HDSLB-DPVS 的基本原理

顾名思义,HDSLB-DPVS 是基于 DPVS 进行二次开辟的项目。而 DPVS,又称为 DPDK-LVS,是一个参考了 LVS 内核态四层负载均衡器设计原理并基于 DPDK 用户态数据面加速框架进行开辟的四层负载均衡器。可见,HDSLB-DPVS 的技术堆栈主要由以下 4 个部分组成:

  • LVS
  • DPDK
  • DPVS
  • HDSLB-DPVS
要清晰的明白 HDSLB-DPVS 的基本实现原理,我们需要重新开始讲起。
LVS

LVS(Linux Virtual Server,Linux 虚拟服务器)是一个诞生于 1998 年的四层负载均衡器开源项目,其目标是使用 Local Balancer 技术和 Server Cluster 技术来实现一个具有精良可伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability)的 Virtual Server。

现在来看,虽然 LVS 基于 Kernel 实现的数据面性能已经不合时宜,但在逻辑架构的设计层面,LVS 的核心术语依旧沿用至今,包罗:

  • VS(Virtual Server,虚拟服务器):VS 是由 DS 和 RS 组合构成的一个逻辑概念,VS 最终通过一个 VIP 对外部 Clients 提供服务。
  • DS(Director Server,流量调度服务器):是充当 LB 流量入口的服务器,负责负载均衡策略的执行和流量分发。所以也称为 FE(前端服务器)。
  • RS(Real Server,真实服务器):RS 是真正用于处理请求流量的服务器,也称为 BE(后端服务器)。
  • VIP(Virtual IP,虚拟 IP 地点):VS 向外部 Client 提供服务的 IP 地点。
  • DIP(Director IP,直连 IP 地点):Director Server 向内部与 RS 进行通讯的 IP 地点。
  • RIP(Real IP,真实 IP 地点):RS 与 DS 互通的 IP 地点。
  • CIP(Client IP,客户端的 IP 地点)
  • NAT 反向署理转发模式
  • IP Tunneling 透明转发模式
  • DR 三角流量转发模式
  • 等等

关于 LVS 更详细的内容,推荐阅读:《LVS & Keepalived 实现 L4 高可用负载均衡器
DPDK

随着 2010 年,IEEE 802.3 尺度委员会发布了 40GbE 和 100GbE 802.3ba 以太网尺度后,数据中心正式进入了 100G 时代。从那时起,Linux 内核协议栈的网络处理性能就不停备受挑战。先看几个数据:

  • CPU 访问 Main Memory 所需要的时长为 65 纳秒。
  • 跨 NUMA node 的 Main Memory 数据 Copy 所需要的时长为 40 纳秒。
  • CPU 处理一次硬件中断所需要的时间为 100 微秒。
但实际上,100G 网卡线速为 2 亿 PPS,即每个包处理的时间不能超过 50 纳秒。
可见,基于 Kernel 的数据面已经走到了拐点,DPDK 为此而生,并通过下列加速技术实现了 100G 线性转发。

  • 使用用户态协议栈取代内核协议栈:Kernel by-pass (user space implementation).
  • 使用轮训取代中断:Polling instead of interrupt.
  • 使用多核编程取代多线程:Share-nothing, per-CPU for key data (lockless).
  • 跨 CPU 无锁通讯:Lockless message for high performance IPC.
  • RX Steering and CPU affinity (avoid context switch).
  • Zero Copy (avoid packet copy and syscalls).
  • Batching TX/RX.
  • etc...


关于 DPDK 更详细的内容,推荐阅读:《DPDK — 数据加速方案的核心思想
DPVS

综上,由于 LVS 的数据面是一个 Linux Kernel Module(ipvs),其性能无法满足当代化需求,所以国内公司 iqiyi 基于 DPDK 开辟了 DPVS。值得一提的是,由于 DPVS 项目由国内公司开源和维护,所以其开源社区对中文开辟者也会更加友好。

除了性能方面的优化之外,在功能层面,DPVS 也提供了更丰富的能力,包罗:

  • L4 Load Balancer, including FNAT, DR, Tunnel, DNAT modes, etc.
  • SNAT mode for Internet access from internal network.
  • NAT64 forwarding in FNAT mode for quick IPv6 adaptation without application changes.
  • Different schedule algorithms like RR, WLC, WRR, MH(Maglev Hashing), Conhash(Consistent Hashing) etc.
  • User-space Lite IP stack (IPv4/IPv6, Routing, ARP, Neighbor, ICMP ...).
  • Support KNI, VLAN, Bonding, Tunneling for different IDC environment.
  • Security aspect, support TCP syn-proxy, Conn-Limit, black-list, white-list.
  • QoS: Traffic Control.
在软件架构方面,DPVS 沿用了数据分离架构和基于 Keepalived 的 Master-Backup 高可用架构。

  • ipvsadm:用于 VS、RS 等逻辑资源对象的管理。
  • dpip:用于 IP、Route 等基础网络资源的管理。
  • keepalived:用于提供基于 VRRP 协议的主备高可用。

HDSLB-DPVS

HDSLB-DPVS 和 DPVS 本身都作为高性能负载均衡器,那么两者的本质区别是什么呢?答案就是更强大的性能!

通常的,我们可以使用 RBP(Ratio of Bandwidth and Performance growth rate,带宽性能增速比)来界说网络带宽的增速比上 CPU 性能的增速,即:RBP=BW GR/Perf. GR。
如下图所示。2010 年前,网络的带宽年化增长大约是 30%,到 2015 年增长到 35%,然后在近年到达 45%。相对应的,CPU 的性能增长从 10 年前的 23%,下降到 12%,并在近年直接低落到 3.5%。在这 3 个时间段内,RBP 指标从 RBP~1 附近(I/O 压力尚未显现出来),上升到 RBP~3,并在近年超过了 RBP~10。
可见,CPU 几乎已经无法直策应对网络带宽的增速。而围绕 CPU 进行纯软件加速的 DPDK 框架正在面对挑战。

回到 DPVS 和 HDSLB-DPVS 的本质区别这个问题。在理论设计层面,DPVS 的目标是基于 DPDK 框架实现了软件层面的加速,而 HDSLB-DPVS 则更进一步的将这种加速融入到 CPU 和 NIC 互相结合的硬件平台之上,并实现了 “高密度” 和 “可扩展” 这 2 大目标:

  • 高密度:指的是单个 HDSLB 节点的 TCP 并发毗连数目和吞吐量特别高。
  • 可拓展:指的是其性能可以随着 CPU Core 的数目或者资源总量的增长而线性拓展。
实践方面,在最新型的 Intel Xeon CPU(e.g. 3rd & 4th generation)和 E810 100G NIC 硬件平台上,实现了:

  • Concurrent Session: 100M level / Node
  • Throughput: > 8Mpps / Core @FNAT
  • TCP Session Est. Rate > 800K / Core
  • Linear growth
对此,我们在《Intel HDSLB 高性能四层负载均衡器 — 快速入门和应用场景》文中已经对 HDSLB-DPVS 超越前代的性能数据进行了分析,这里不在赘述。
HDSLB 的摆设配置

硬件要求

下面进入到实践环节,主要关注 HDSLB-DPVS 的编译、摆设和配置。为了低落开辟者门槛,所以本文主要使用了开辟机低门槛配置来进行摆设和调试。
物理测试机性能推荐虚拟开辟机低门槛推荐CPU 架构Intel Xeon CPU 四代支持 AVX512 系列指令集的 Intel CPU 型号,比方:Skylake 等CPU 资源2NUMA,关闭超线程1NUMA,4CMemory 资源128G16GNIC 型号Intel E810 100GVirtI/O 驱动,支持多队列本文 CPU 信息:
  1. $ lscpu
  2. Architecture:                    x86_64
  3. CPU op-mode(s):                  32-bit, 64-bit
  4. Byte Order:                      Little Endian
  5. Address sizes:                   46 bits physical, 57 bits virtual
  6. CPU(s):                          4
  7. On-line CPU(s) list:             0-3
  8. Thread(s) per core:              2root@l4lb:~# lscpu
  9. Architecture:                    x86_64
  10. CPU op-mode(s):                  32-bit, 64-bit
  11. Byte Order:                      Little Endian
  12. Address sizes:                   46 bits physical, 57 bits virtual
  13. CPU(s):                          4
  14. On-line CPU(s) list:             0-3
  15. Thread(s) per core:              2
  16. Core(s) per socket:              2
  17. Socket(s):                       1
  18. NUMA node(s):                    1
  19. Vendor ID:                       GenuineIntel
  20. CPU family:                      6
  21. Model:                           106
  22. Model name:                      Intel(R) Xeon(R) Platinum 8350C CPU @ 2.60GHz
  23. Stepping:                        6
  24. CPU MHz:                         2599.994
  25. BogoMIPS:                        5199.98
  26. Hypervisor vendor:               KVM
  27. Virtualization type:             full
  28. L1d cache:                       96 KiB
  29. L1i cache:                       64 KiB
  30. L2 cache:                        2.5 MiB
  31. L3 cache:                        48 MiB
  32. NUMA node0 CPU(s):               0-3
  33. Vulnerability Itlb multihit:     Not affected
  34. Vulnerability L1tf:              Not affected
  35. Vulnerability Mds:               Not affected
  36. Vulnerability Meltdown:          Not affected
  37. Vulnerability Mmio stale data:   Vulnerable: Clear CPU buffers attempted, no microcode; SMT Host state unknown
  38. Vulnerability Retbleed:          Not affected
  39. Vulnerability Spec store bypass: Vulnerable
  40. Vulnerability Spectre v1:        Mitigation; usercopy/swapgs barriers and __user pointer sanitization
  41. Vulnerability Spectre v2:        Vulnerable, IBPB: disabled, STIBP: disabled, PBRSB-eIBRS: Vulnerable
  42. Vulnerability Srbds:             Not affected
  43. Vulnerability Tsx async abort:   Not affected
  44. Flags:                           fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_ts
  45.                                  c arch_perfmon rep_good nopl xtopology cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_tim
  46.                                  er aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single ssbd ibrs ibpb ibrs_enhanced fsgsbase tsc_adjust bm
  47.                                  i1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xge
  48.                                  tbv1 xsaves arat avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid arch_capabilities
复制代码
软件要求


  • OS:Ubuntu 20.04.3
  • Kernel:5.4.0-110-generic
  • GCC:9.4.0
  • DPDK:20.08
值的注意的是,Ubuntu /boot 分区要大于 2G,避免出现内核升级故障问题。参考引用:https://askubuntu.com/questions/1207958/error-24-write-error-cannot-write-compressed-block
本文 OS 信息:
  1. # 更新系统
  2. $ sudo apt-get update -y && sudo apt-get upgrade -y
  3. # Dev
  4. $ sudo apt-get install git vim wget patch unzip -y
  5. # popt
  6. $ sudo apt-get install libpopt-dev -y
  7. # NUMA
  8. $ sudo apt-get install libnuma-dev -y
  9. $ sudo apt-get install numactl -y
  10. # Pcap
  11. $ sudo apt-get install libpcap-dev -y
  12. # SSL
  13. $ sudo apt-get install libssl-dev -y
  14. # Kernel 5.4.0-136
  15. $ uname -r
  16. 5.4.0-136-generic
  17. $ ll /boot/vmlinuz*
  18. lrwxrwxrwx 1 root root       25 Dec 27  2022 /boot/vmlinuz -> vmlinuz-5.4.0-136-generic
  19. -rw------- 1 root root 13660416 Aug 10  2022 /boot/vmlinuz-5.4.0-125-generic
  20. -rw------- 1 root root 13668608 Nov 24  2022 /boot/vmlinuz-5.4.0-136-generic
  21. -rw------- 1 root root 11657976 Apr 21  2020 /boot/vmlinuz-5.4.0-26-generic
  22. lrwxrwxrwx 1 root root       25 Dec 27  2022 /boot/vmlinuz.old -> vmlinuz-5.4.0-125-generic
  23. $ dpkg -l | egrep "linux-(signed|modules|image|headers)" | grep $(uname -r)
  24. ii  linux-headers-5.4.0-136-generic       5.4.0-136.153                     amd64        Linux kernel headers for version 5.4.0 on 64 bit x86 SMP
  25. ii  linux-image-5.4.0-136-generic         5.4.0-136.153                     amd64        Signed kernel image generic
  26. ii  linux-modules-5.4.0-136-generic       5.4.0-136.153                     amd64        Linux kernel extra modules for version 5.4.0 on 64 bit x86 SMP
  27. ii  linux-modules-extra-5.4.0-136-generic 5.4.0-136.153                     amd64        Linux kernel extra modules for version 5.4.0 on 64 bit x86 SMP
  28. # GCC 9.4.0
  29. $ gcc --version
  30. gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
  31. Copyright (C) 2019 Free Software Foundation, Inc.
  32. This is free software; see the source for copying conditions.  There is NO
  33. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  34. # 文件描述符
  35. $ ulimit -n 655350
  36. $ echo "ulimit -n 655350" >> /etc/rc.local
  37. $ chmod a+x /etc/rc.local
复制代码
编译安装 DPDK

DPDK 安装摆设的详细内容,推荐阅读:《DPDK — 安装摆设》。
  1. $ cd /root/
  2. $ git clone https://github.com/intel/high-density-scalable-load-balancer hdslb
  3. $ wget http://fast.dpdk.org/rel/dpdk-20.08.tar.xz
  4. $ tar vxf dpdk-20.08.tar.xz
  5. # 打补丁
  6. $ cp hdslb/patch/dpdk-20.08/*.patch dpdk-20.08/
  7. $ cd dpdk-20.08/
  8. $ patch -p 1 < 0002-support-large_memory.patch
  9. $ patch -p 1 < 0003-net-i40e-ice-support-rx-markid-ofb.patch
  10. # 编译
  11. $ make config T=x86_64-native-linuxapp-gcc MAKE_PAUSE=n
  12. $ make MAKE_PAUSE=n -j 4
复制代码
编译安装 HDSLB-DPVS

HDSLB-DPVS 的编译安装过程中需要依赖许多 CPU 硬件加速指令,比方:AVX2、AVX512 等等。要编译乐成,有 2 方面的要求:

  • 要求 CPU 硬件支持:推荐使用 Intel Xeon 数据中心系列,比方:Intel Xeon Gold。
  • 要求 GCC 版本支持:推荐采用版本较高的 GCC,比方本文中的 9.4.0。
  1. $ cd dpdk-20.08/
  2. $ export RTE_SDK=$PWD
  3. $ cd hdslb/
  4. $ chmod +x tools/keepalived/configure
  5. # 编译安装
  6. $ make -j 4
  7. $ make install
复制代码
配置大页内存

在物理机测试环境中,大页内存应该尽可能的给,HDSLB 的 LB connect pool 需要分配大量的内存,这与实际的性能规格有直接关系。
  1. $ mkdir /mnt/huge_1GB
  2. $ mount -t hugetlbfs nodev /mnt/huge_1GB
  3. $ vim /etc/fstab
  4. nodev /mnt/huge_1GB hugetlbfs pagesize=1GB 0 0
  5. $ # for NUMA machine
  6. $ echo 15 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages
  7. $ vim /etc/default/grub
  8. GRUB_CMDLINE_LINUX_DEFAULT="${GRUB_CMDLINE_LINUX_DEFAULT} default_hugepagesz=1G hugepagesz=1G hugepages=15"
  9. $ sudo update-grub
  10. $ init 6
  11. $ cat /proc/meminfo | grep Huge
  12. AnonHugePages:         0 kB
  13. ShmemHugePages:        0 kB
  14. FileHugePages:         0 kB
  15. HugePages_Total:      13
  16. HugePages_Free:       13
  17. HugePages_Rsvd:        0
  18. HugePages_Surp:        0
  19. Hugepagesize:    1048576 kB
  20. Hugetlb:        13631488 kB
  21. $ free -h
  22.               total        used        free      shared  buff/cache   available
  23. Mem:           15Gi        13Gi       2.0Gi       2.0Mi       408Mi       2.2Gi
  24. Swap:            0B          0B          0B
复制代码
配置网卡
  1. $ modprobe vfio-pci
  2. $ modprobe vfio enable_unsafe_noiommu_mode=1 # https://stackoverflow.com/questions/75840973/dpdk20-11-3-cannot-bind-device-to-vfio-pci
  3. $ echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode
  4. $ cd dpdk-20.08/
  5. $ export RTE_SDK=$PWD
  6. $ insmod ${RTE_SDK}/build/kmod/rte_kni.ko
  7. $ ${RTE_SDK}/usertools/dpdk-devbind.py --status-dev net
  8. Network devices using kernel driver
  9. ===================================
  10. 0000:01:00.0 'Virtio network device 1000' if=eth0 drv=virtio-pci unused=vfio-pci *Active*
  11. 0000:03:00.0 'Virtio network device 1000' if=eth1 drv=virtio-pci unused=vfio-pci
  12. 0000:04:00.0 'Virtio network device 1000' if=eth2 drv=virtio-pci unused=vfio-pci
  13. $ ifconfig eth1 down # 0000:03:00.0
  14. $ ifconfig eth2 down # 0000:04:00.0
  15. $ ${RTE_SDK}/usertools/dpdk-devbind.py -b vfio-pci 0000:03:00.0 0000:04:00.0
  16. $ ${RTE_SDK}/usertools/dpdk-devbind.py --status-dev net
  17. Network devices using DPDK-compatible driver
  18. ============================================
  19. 0000:03:00.0 'Virtio network device 1000' drv=vfio-pci unused=
  20. 0000:04:00.0 'Virtio network device 1000' drv=vfio-pci unused=
  21. Network devices using kernel driver
  22. ===================================
  23. 0000:01:00.0 'Virtio network device 1000' if=eth0 drv=virtio-pci unused=vfio-pci *Active*
复制代码
配置 HDSLB-DPVS
  1. $ cp conf/hdslb.conf.sample /etc/hdslb.conf
  2. # 配置解析
  3. $ cat /etc/hdslb.conf
  4. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  5. ! This is hdslb default configuration file.
  6. !
  7. ! The attribute "<init>" denotes the configuration item at initialization stage. Item of
  8. ! this type is configured oneshoot and not reloadable. If invalid value configured in the
  9. ! file, hdslb would use its default value.
  10. !
  11. ! Note that hdslb configuration file supports the following comment type:
  12. !   * line comment: using '#" or '!'
  13. !   * inline range comment: using '<' and '>', put comment in between
  14. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  15. ! global config
  16. global_defs {
  17.     log_level   DEBUG # 方便调试
  18.     ! log_file    /var/log/hdslb.log
  19.     ! log_async_mode    on
  20. }
  21. ! netif config
  22. netif_defs {
  23.     <init> pktpool_size     1048575
  24.     <init> pktpool_cache    256
  25.     # LAN Interface 配置
  26.     <init> device dpdk0 {
  27.         rx {
  28.             queue_number        3
  29.             descriptor_number   1024
  30.             ! rss                 all
  31.         }
  32.         tx {
  33.             queue_number        3
  34.             descriptor_number   1024
  35.         }
  36.         fdir {
  37.             mode                perfect
  38.             pballoc             64k
  39.             status              matched
  40.         }
  41.         ! promisc_mode
  42.         kni_name                dpdk0.kni
  43.     }
  44.     # WAN Interface 配置
  45.     <init> device dpdk1 {
  46.         rx {
  47.             queue_number        3
  48.             descriptor_number   1024
  49.             ! rss                 all
  50.         }
  51.         tx {
  52.             queue_number        3
  53.             descriptor_number   1024
  54.         }
  55.         fdir {
  56.             mode                perfect
  57.             pballoc             64k
  58.             status              matched
  59.         }
  60.         ! promisc_mode
  61.         kni_name                dpdk1.kni
  62.     }
  63.     ! <init> bonding bond0 {
  64.     !    mode        0
  65.     !    slave       dpdk0
  66.     !    slave       dpdk1
  67.     !    primary     dpdk0
  68.     !    kni_name    bond0.kni
  69.     !}
  70. }
  71. ! worker config (lcores)
  72. worker_defs {
  73.     # control plane CPU
  74.     <init> worker cpu0 {
  75.         type    master
  76.         cpu_id  0
  77.     }
  78.     # data plane CPU
  79.     # dpdk0、1 这 2 个 Port 的同一个收发队列共用同一个 CPU
  80.     <init> worker cpu1 {
  81.         type    slave
  82.         cpu_id  1
  83.         port    dpdk0 {
  84.             rx_queue_ids     0
  85.             tx_queue_ids     0
  86.             ! isol_rx_cpu_ids  9
  87.             ! isol_rxq_ring_sz 1048576
  88.         }
  89.         port    dpdk1 {
  90.             rx_queue_ids     0
  91.             tx_queue_ids     0
  92.             ! isol_rx_cpu_ids  9
  93.             ! isol_rxq_ring_sz 1048576
  94.         }
  95.     }
  96.     <init> worker cpu2 {
  97.         type    slave
  98.         cpu_id  2
  99.         port    dpdk0 {
  100.             rx_queue_ids     1
  101.             tx_queue_ids     1
  102.             ! isol_rx_cpu_ids  10
  103.             ! isol_rxq_ring_sz 1048576
  104.         }
  105.         port    dpdk1 {
  106.             rx_queue_ids     1
  107.             tx_queue_ids     1
  108.             ! isol_rx_cpu_ids  10
  109.             ! isol_rxq_ring_sz 1048576
  110.         }
  111.     }
  112.     <init> worker cpu3 {
  113.         type    slave
  114.         cpu_id  3
  115.         port    dpdk0 {
  116.             rx_queue_ids     2
  117.             tx_queue_ids     2
  118.             ! isol_rx_cpu_ids  11
  119.             ! isol_rxq_ring_sz 1048576
  120.         }
  121.         port    dpdk1 {
  122.             rx_queue_ids     2
  123.             tx_queue_ids     2
  124.             ! isol_rx_cpu_ids  11
  125.             ! isol_rxq_ring_sz 1048576
  126.         }
  127.     }
  128. }
  129. ! timer config
  130. timer_defs {
  131.     # cpu job loops to schedule dpdk timer management
  132.     schedule_interval    500
  133. }
  134. ! hdslb neighbor config
  135. neigh_defs {
  136.     <init> unres_queue_length  128
  137.     <init> timeout             60
  138. }
  139. ! hdslb ipv4 config
  140. ipv4_defs {
  141.     forwarding                 off
  142.     <init> default_ttl         64
  143.     fragment {
  144.         <init> bucket_number   4096
  145.         <init> bucket_entries  16
  146.         <init> max_entries     4096
  147.         <init> ttl             1
  148.     }
  149. }
  150. ! hdslb ipv6 config
  151. ipv6_defs {
  152.     disable                     off
  153.     forwarding                  off
  154.     route6 {
  155.         <init> method           hlist
  156.         recycle_time            10
  157.     }
  158. }
  159. ! control plane config
  160. ctrl_defs {
  161.     lcore_msg {
  162.         <init> ring_size                4096
  163.         sync_msg_timeout_us             30000000
  164.         priority_level                  low
  165.     }
  166.     ipc_msg {
  167.         <init> unix_domain /var/run/hdslb_ctrl
  168.     }
  169. }
  170. ! ipvs config
  171. ipvs_defs {
  172.     conn {
  173.         <init> conn_pool_size       2097152
  174.         <init> conn_pool_cache      256
  175.         conn_init_timeout           30
  176.         ! expire_quiescent_template
  177.         ! fast_xmit_close
  178.         ! <init> redirect           off
  179.     }
  180.     udp {
  181.         ! defence_udp_drop
  182.         uoa_mode        opp
  183.         uoa_max_trail   3
  184.         timeout {
  185.             normal      300
  186.             last        3
  187.         }
  188.     }
  189.     tcp {
  190.         ! defence_tcp_drop
  191.         timeout {
  192.             none        2
  193.             established 90
  194.             syn_sent    3
  195.             syn_recv    30
  196.             fin_wait    7
  197.             time_wait   7
  198.             close       3
  199.             close_wait  7
  200.             last_ack    7
  201.             listen      120
  202.             synack      30
  203.             last        2
  204.         }
  205.         synproxy {
  206.             synack_options {
  207.                 mss             1452
  208.                 ttl             63
  209.                 sack
  210.                 ! wscale
  211.                 ! timestamp
  212.             }
  213.             ! defer_rs_syn
  214.             rs_syn_max_retry    3
  215.             ack_storm_thresh    10
  216.             max_ack_saved       3
  217.             conn_reuse_state {
  218.                 close
  219.                 time_wait
  220.                 ! fin_wait
  221.                 ! close_wait
  222.                 ! last_ack
  223.            }
  224.         }
  225.     }
  226. }
  227. ! sa_pool config
  228. sa_pool {
  229.     pool_hash_size   16
  230. }
复制代码
启动 HDSLB-DPVS
  1. $ cd hdslb/
  2. $ ./bin/hdslb
  3. current thread affinity is set to F
  4. EAL: Detected 4 lcore(s)
  5. EAL: Detected 1 NUMA nodes
  6. EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
  7. EAL: Selected IOVA mode 'PA'
  8. EAL: Probing VFIO support...
  9. EAL: VFIO support initialized
  10. EAL:   Invalid NUMA socket, default to 0
  11. EAL: Probe PCI driver: net_virtio (1af4:1000) device: 0000:01:00.0 (socket 0)
  12. EAL:   Invalid NUMA socket, default to 0
  13. EAL: Probe PCI driver: net_virtio (1af4:1000) device: 0000:03:00.0 (socket 0)
  14. EAL:   using IOMMU type 8 (No-IOMMU)
  15. EAL: Ignore mapping IO port bar(0)
  16. EAL:   Invalid NUMA socket, default to 0
  17. EAL: Probe PCI driver: net_virtio (1af4:1000) device: 0000:04:00.0 (socket 0)
  18. EAL: Ignore mapping IO port bar(0)
  19. EAL: No legacy callbacks, legacy socket not created
  20. DPVS: HDSLB version: , build on 2024.05.24.14:37:02
  21. CFG_FILE: Opening configuration file '/etc/hdslb.conf'.
  22. CFG_FILE: log_level = WARNING
  23. NETIF: dpdk0:rx_queue_number = 3
  24. NETIF: dpdk1:rx_queue_number = 3
  25. NETIF: worker cpu1:dpdk0 rx_queue_id += 0
  26. NETIF: worker cpu1:dpdk0 tx_queue_id += 0
  27. NETIF: worker cpu1:dpdk1 rx_queue_id += 0
  28. NETIF: worker cpu1:dpdk1 tx_queue_id += 0
  29. NETIF: worker cpu2:dpdk0 rx_queue_id += 1
  30. NETIF: worker cpu2:dpdk0 tx_queue_id += 1
  31. NETIF: worker cpu2:dpdk1 rx_queue_id += 1
  32. NETIF: worker cpu2:dpdk1 tx_queue_id += 1
  33. NETIF: worker cpu3:dpdk0 rx_queue_id += 2
  34. NETIF: worker cpu3:dpdk0 tx_queue_id += 2
  35. NETIF: worker cpu3:dpdk1 rx_queue_id += 2
  36. NETIF: worker cpu3:dpdk1 tx_queue_id += 2
  37. Kni: kni_add_dev: fail to set mac FA:27:00:00:0A:02 for dpdk0.kni: Timer expired
  38. Kni: kni_add_dev: fail to set mac FA:27:00:00:0B:F6 for dpdk1.kni: Timer expired
复制代码

HDSLB-DPVS 进程起来后,可以看见 2 个 DPDK Port 和对应的 2 个 KNI Interface。其中 DPDK Port 用于 LB 数据面转发,而 KNI 则用于 Keepalived HA 摆设模式。
  1. $ cd hdslb/bin/
  2. $ ./dpip link show
  3. 1: dpdk0: socket 0 mtu 1500 rx-queue 3 tx-queue 3
  4.     UP 10000 Mbps half-duplex auto-nego
  5.     addr FA:27:00:00:0A:02 OF_TX_IP_CSUM
  6. 2: dpdk1: socket 0 mtu 1500 rx-queue 3 tx-queue 3
  7.     UP 10000 Mbps half-duplex auto-nego
  8.     addr FA:27:00:00:0B:F6 OF_TX_IP_CSUM
  9. $ ip a
  10. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
  11.     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  12.     inet 127.0.0.1/8 scope host lo
  13.        valid_lft forever preferred_lft forever
  14.     inet6 ::1/128 scope host
  15.        valid_lft forever preferred_lft forever
  16. 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
  17.     link/ether fa:27:00:00:00:c0 brd ff:ff:ff:ff:ff:ff
  18.     inet 192.168.0.4/25 brd 192.168.0.127 scope global eth0
  19.        valid_lft forever preferred_lft forever
  20.     inet6 fe80::f827:ff:fe00:c0/64 scope link
  21.        valid_lft forever preferred_lft forever
  22. 71: dpdk0.kni: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
  23.     link/ether fa:27:00:00:0a:02 brd ff:ff:ff:ff:ff:ff
  24. 72: dpdk1.kni: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
  25.     link/ether fa:27:00:00:0b:f6 brd ff:ff:ff:ff:ff:ff
复制代码
测试 HDSLB-DPVS Two-arm Full-NAT 模式



  • HDSLB-DPVS
  1. $ cd hdslb/bin
  2. # add VIP to WAN interface
  3. $ ./dpip addr add 10.0.0.100/32 dev dpdk1
  4. # route for WAN/LAN access
  5. $ ./dpip route add 10.0.0.0/16 dev dpdk1
  6. $ ./dpip route add 192.168.100.0/24 dev dpdk0
  7. # add routes for other network or default route if needed.
  8. $ ./dpip route show
  9. inet 10.0.0.100/32 via 0.0.0.0 src 0.0.0.0 dev dpdk1 mtu 1500 tos 0 scope host metric 0 proto auto
  10. inet 192.168.100.0/24 via 0.0.0.0 src 0.0.0.0 dev dpdk0 mtu 1500 tos 0 scope link metric 0 proto auto
  11. inet 10.0.0.0/16 via 0.0.0.0 src 0.0.0.0 dev dpdk1 mtu 1500 tos 0 scope link metric 0 proto auto
  12. # add service <VIP:vport> to forwarding, scheduling mode is RR.
  13. $ ./ipvsadm -A -t 10.0.0.100:80 -s rr
  14. # add two RS for service, forwarding mode is FNAT (-b)
  15. $ ./ipvsadm -a -t 10.0.0.100:80 -r 192.168.100.2 -b
  16. $ ./ipvsadm -a -t 10.0.0.100:80 -r 192.168.100.3 -b
  17. # add at least one Local-IP (LIP) for FNAT on LAN interface
  18. $ ./ipvsadm --add-laddr -z 192.168.100.200 -t 10.0.0.100:80 -F dpdk0
  19. # Check
  20. $  ./ipvsadm -Ln
  21. IP Virtual Server version 0.0.0 (size=0)
  22. Prot LocalAddress:Port Scheduler Flags
  23.   -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
  24. TCP  10.0.0.100:80 rr
  25.   -> 192.168.100.2:80             FullNat 1      0          0
  26.   -> 192.168.100.3:80             FullNat 1      0          0
复制代码

  • Server
  1. $ python -m SimpleHTTPServer 80
复制代码

  • Client
  1. $ curl 10.0.0.100
复制代码
问题分析

问题 1:hdslb/tools/keepalived/configure 没有执行权限。
  1. make[1]: Leaving directory '/root/hdslb/src'
  2. make[1]: Entering directory '/root/hdslb/tools'
  3. if [ ! -f keepalived/Makefile ]; then \
  4.         cd keepalived && \
  5.         ./configure && \
  6.         cd -; \
  7. fi
  8. /bin/sh: 3: ./configure: Permission denied
  9. make[1]: *** [Makefile:29: keepalived_conf] Error 126
  10. make[1]: Leaving directory '/root/hdslb/tools'
  11. make: *** [Makefile:33: all] Error 1
  12. # 解决
  13. $ chmod +x /root/hdslb/tools/keepalived/configure
复制代码
问题 2:缺少配置文件
  1. Cause: ports in DPDK RTE (2) != ports in dpvs.conf(0)
  2. # 解决
  3. $ cp conf/hdslb.conf.sample /etc/hdslb.conf
复制代码
问题 3:开辟机 2MB hugepage size 太小
  1. Cause: Cannot init mbuf pool on socket 0
  2. # 解决:把 hugepagesize 配置为 1G
  3. # ref:https://stackoverflow.com/questions/51630926/cannot-create-mbuf-pool-with-dpdk
复制代码
问题 4:缺少 rte_kni 模块
  1. Cause: add KNI port fail, exiting...
  2. # 解决
  3. $ insmod ${RTE_SDK}/build/kmod/rte_kni.ko
复制代码
问题 5:开辟机大页内存不够
  1. Kni: kni_add_dev: fail to set mac FA:27:00:00:07:AA for dpdk0.kni: Timer expired
  2. Kni: kni_add_dev: fail to set mac FA:27:00:00:00:E1 for dpdk1.kni: Timer expired
  3. IPSET: ipset_init: lcore 3: nothing to do.
  4. IPVS: dp_vs_conn_init: lcore 3: nothing to do.
  5. IPVS: fail to init synproxy: no memory
  6. Segmentation fault (core dumped)
  7. # 解决:扩容到 15G。
复制代码
问题 6:开辟机网卡不支持 HDSLB-DPVS 需要的 hardware offloads 功能。
  1. Kni: kni_add_dev: fail to set mac FA:27:00:00:0A:02 for dpdk0.kni: Timer expired
  2. Kni: kni_add_dev: fail to set mac FA:27:00:00:0B:F6 for dpdk1.kni: Timer expired
  3. Ethdev port_id=0 requested Rx offloads 0x62f doesn't match Rx offloads capabilities 0xa1d in rte_eth_dev_configure()
  4. NETIF: netif_port_start: fail to config dpdk0
  5. EAL: Error - exiting with code: 1
  6.   Cause: Start dpdk0 failed, skipping ...
  7. # 解决:修改 netif 模块,不启动不支持的 offloads 功能。
  8. static struct rte_eth_conf default_port_conf = {
  9.     .rxmode = {
  10. ......
  11.         .offloads = 0,
  12.         //.offloads = DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_VLAN,
  13.     },
  14. ......
  15.     .txmode = {
  16. ......
  17.         .offloads = 0,
  18.         //.offloads = DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_MBUF_FAST_FREE,
  19.     },
复制代码
NOTE:根据 DPDK 的文档,offloads mask 的每个 bit 都代表了特定的卸载功能。以下 0-15bit 对应的 Features:

  • DEV_RX_OFFLOAD_VLAN_STRIP
  • DEV_RX_OFFLOAD_IPV4_CKSUM
  • DEV_RX_OFFLOAD_UDP_CKSUM
  • DEV_RX_OFFLOAD_TCP_CKSUM
  • DEV_RX_OFFLOAD_TCP_LRO
  • DEV_RX_OFFLOAD_QINQ_STRIP
  • DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM
  • DEV_RX_OFFLOAD_MACSEC_STRIP
  • DEV_RX_OFFLOAD_VLAN_FILTER
  • DEV_RX_OFFLOAD_VLAN_EXTEND
  • DEV_RX_OFFLOAD_SCATTER
  • DEV_RX_OFFLOAD_TIMESTAMP
  • DEV_RX_OFFLOAD_SECURITY
  • DEV_RX_OFFLOAD_KEEP_CRC
  • DEV_RX_OFFLOAD_SCTP_CKSUM
  • DEV_RX_OFFLOAD_OUTER_UDP_CKSUM
问题 7:开辟机网络不支持 RSS 多队列。valid value: 0x0 表现当前网卡不支持任何 RSS 哈希函数。
  1. Kni: kni_add_dev: fail to set mac FA:27:00:00:0A:02 for dpdk0.kni: Timer expired
  2. Kni: kni_add_dev: fail to set mac FA:27:00:00:0B:F6 for dpdk1.kni: Timer expired
  3. Ethdev port_id=0 invalid rss_hf: 0x3afbc, valid value: 0x0
  4. NETIF: netif_port_start: fail to config dpdk0
  5. EAL: Error - exiting with code: 1
  6.   Cause: Start dpdk0 failed, skipping ...
  7. # 解决方式 1:使用支持 multi-queues 和 RSS hash 的网卡。
  8. # 解决方式 2:修改 netif 模块,不启动 multi-queues 和 RSS hash 功能。
  9. static struct rte_eth_conf default_port_conf = {
  10.     .rxmode = {
  11.         //.mq_mode        = ETH_MQ_RX_RSS,
  12.         .mq_mode        = ETH_MQ_RX_NONE,
  13. ......
  14.     },
  15.     .rx_adv_conf = {
  16.         .rss_conf = {
  17.             .rss_key = NULL,
  18.             //.rss_hf  = /*ETH_RSS_IP*/ ETH_RSS_TCP,
  19.             .rss_hf  = 0
  20.         },
  21.     },
  22. ......
  23. port->dev_conf.rx_adv_conf.rss_conf.rss_hf = 0;   
复制代码
问题 8:不支持多播地点配置
  1. Kni: kni_add_dev: fail to set mac FA:27:00:00:0A:02 for dpdk0.kni: Timer expired
  2. Kni: kni_add_dev: fail to set mac FA:27:00:00:0B:F6 for dpdk1.kni: Timer expired
  3. NETIF: multicast address add failed for device dpdk0
  4. EAL: Error - exiting with code: 1
  5.   Cause: Start dpdk0 failed, skipping ...
  6. # 解决:关闭多播功能
  7.     //ret = idev_add_mcast_init(port);
  8.     //if (ret != EDPVS_OK) {
  9.     //    RTE_LOG(WARNING, NETIF, "multicast address add failed for device %s\n", port->name);
  10.     //    return ret;
  11.     //}
复制代码
问题 9:LB connect pool 内存太小,程序崩溃退出。
  1. $ ./ipvsadm -A -t 10.0.0.100:80 -s rr
  2. [sockopt_msg_recv] socket msg header recv error -- 0/88 recieved  
  3. IPVS: lb_conn_hash_table_init: lcore 0: create conn_hash_tbl failed. Requested size: 1073741824 bytes. LB_CONN_CACHE_LINES_DEF: 1, LB_CONN_TBL_SIZE: 16777216
  4. # 解决方式 1:继续加大页内存到实际需要的大小。
  5. # 解决方式 2:
  6. #        1):释放一个 lcore 的大页内存
  7. #        2):调小 DPVS_CONN_POOL_SIZE_DEF 从 2097152 减少到 1048576
  8. //#define DPVS_CONN_POOL_SIZE_DEF     2097152
  9. #define DPVS_CONN_POOL_SIZE_DEF     1048576
复制代码
问题 10:编译器版本低缺少编译指令。
  1. error: inlining failed in call to always_inline   "'_mm256_cmpeq_epi64_mask':"  : target specific option mismatch
  2. # 解决:
  3. # 1)升级 GCC 版本到 9.4.0
  4. # 2)确定 CPU 支持指令集。ref:https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#expand=3828,301,2553&text=_mm256_cmpeq_epi64_mask&ig_expand=872
复制代码

最后

值得注意的是上述问题记录是笔者在低配开辟机中调试程序时所遇见的问题,实际上在一个资源富足的物理测试机上通常不会出现由于资源不足导致的大部分问题。
最后,本篇主要介绍了 Intel HDSLB 的基本运行原理和摆设配置的方式,盼望能够资助读者们顺遂的把 HDSLB-DPVS 项目 “玩” 起来。后面,我们将再次开辟机环境的基础之上,通过《Intel HDSLB 高性能四层负载均衡器 — 高级特性和代码剖析》,继续深入挖掘 HDSLB-DPVS 的高级特性、软件架构分析和代码解读。敬请继续等待。:)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

数据人与超自然意识

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表