更新时间:2024-08-14 GMT+08:00

如何设置镜像的网卡多队列属性?

操作场景

随着网络IO的带宽不断提升,单核CPU处理网络中断存在瓶颈,不能完全满足网卡的需求,通过开启网卡多队列功能,您可以将弹性云服务器中的网卡中断分散给不同的CPU处理,以满足网卡的需求,从而提升网络PPS和带宽性能。

网卡多队列支持列表

网卡多队列的支持情况和实例规格、虚拟化类型、镜像的操作系统有关,只有同时满足这些要求,云服务器才能开启网卡多队列功能。

  • 支持网卡多队列的实例规格请参见《弹性云服务器用户指南》的“实例”章节。

    网卡多队列数为大于1的值,表示支持网卡多队列。

  • 虚拟化类型必须为KVM,XEN类型不支持网卡多队列。
  • 表1所列的Linux公共镜像,支持网卡多队列。
    • Windows操作系统公共镜像暂未支持网卡多队列,如果对Windows操作系统镜像开启网卡多队列功能,可能会引起操作系统启动速度变慢等问题。
    • Linux操作系统云服务器建议将操作系统内核版本升级至2.6.35及以上,否则不支持网卡多队列。

      建议您使用命令uname -r查询内核版本,如果低于2.6.35请联系技术支持升级内核。

表1 KVM弹性云服务器网卡多队列支持列表

类别

镜像

支持度

Windows

Windows Server 2008 WEB R2 64bit

可通过私有镜像支持

Windows Server 2008 R2 Standard/Datacenter/Enterprise 64bit

可通过私有镜像支持

Windows Server 2012 R2 Standard/Datacenter 64bit

可通过私有镜像支持

Windows Server 2016 Standard/Datacenter 64bit

可通过私有镜像支持

Linux

Ubuntu 14.04/16.04 Server 64bit

支持

openSUSE 42.2 64bit

支持

SUSE Enterprise 12 SP1/SP2 64bit

支持

CentOS 6.8/6.9/7.0/7.1/7.2/7.3/7.4/7.5/7.6 64bit

支持

Debian 8.0.0/8.8.0/8.9.0/9.0.0 64bit

支持

Fedora 24/25 64bit

支持

EulerOS 2.2 64bit

支持

操作说明

假设以下场景所述的云服务器满足规格和虚拟化类型要求:

将外部镜像文件导入镜像服务控制台

将外部镜像文件导入镜像服务控制台,详细操作请参见注册镜像(Linux)

为镜像添加网卡多队列标签

Windows操作系统暂未商用支持网卡多队列,如果对Windows操作系统镜像添加网卡多队列标签,开启网卡多队列功能,可能会引起操作系统启动速度变慢等问题。

用户可以选择以下任意一种方式设置镜像的网卡多队列属性。

方式1
  1. 登录IMS控制台。
    1. 登录管理控制台。
    2. 选择“计算 > 镜像服务”。

      进入镜像服务页面。

  2. 单击“私有镜像”页签,在对应镜像所在行的“操作”列下,单击“修改”。
  3. 设置镜像的网卡多队列属性。
方式2
  1. 登录IMS控制台。
    1. 登录管理控制台。
    2. 选择“计算 > 镜像服务”。

      进入镜像服务页面。

  2. 单击“私有镜像”页签,在镜像列表中,单击镜像名称,进入镜像详情页面。
  3. 单击右上角的“修改”,在弹出的“修改镜像”对话框中,设置镜像的网卡多队列属性。

方法3:通过API为镜像添加网卡多队列标签hw_vif_multiqueue_enabled

  1. 获取Token的方法请参考《镜像服务API参考》中的“如何调用API > 认证鉴权”。
  2. “更新镜像信息”的API使用方法请参考《镜像服务API参考》中的“更新镜像信息(OpenStack原生)”章节。
  3. 在请求消息头中增加“X-Auth-Token”。

    “X-Auth-Token”的取值为步骤1中获取的Token。

  4. 在请求消息头中增加“Content-Type”。

    “Content-Type”取值为application/openstack-images-v2.1-json-patch

    请求的URI格式为:

    PATCH /v2/images/{image_id}

    请求的body体如下所示。
    [       
             { 
              "op":"add",
              "path":"/hw_vif_multiqueue_enabled", 
              "value": true
             } 
     ]

使用私有镜像创建云服务器

使用注册好的私有镜像创建云服务器,详细操作请参见《弹性云服务器用户指南》。在配置参数时,需要注意以下两点:
  • 区域:必须选择私有镜像所在的区域。
  • 镜像:选择“私有镜像”,并在下拉列表中选择需要的镜像。

开启网卡多队列

使用Windows操作系统的KVM弹性云服务器,可通过私有镜像支持网卡多队列功能。

使用Linux操作系统的弹性云服务器,本节以CentOS 7.4为例,介绍开启网卡多队列的具体操作:

  1. 开启网卡多队列功能

    1. 登录弹性云服务器
    2. 执行以下命令,查看网卡支持和已开启的队列数。

      ethtool -l 网卡

    3. 执行以下命令,设置网卡当前使用的队列数。

      ethtool -L 网卡 combined 队列数

    示例:

    [root@localhost ~]# ethtool -l eth0  #查询网卡eth0的队列数
    Channel parameters for eth0:
    Pre-set maximums:
    RX:               0
    TX:               0
    Other:                  0
    Combined: 4  #表示此网卡最多支持设置开启4个队列
    Current hardware settings:
    RX:               0
    TX:               0
    Other:                  0
    Combined: 1 #表示当前开启的是1个队列
    
    [root@localhost ~]# ethtool -L eth0 combined 4 #设置eth0网卡开启4个队列

  2. (可选)建议开启irqbalance服务,让系统自动调整网卡中断在多个CPU核上的分配。

    1. 执行以下命令,开启irqbalance服务。

      service irqbalance start

    2. 执行以下命令,查询irqbalance服务状态。

      service irqbalance status

      如果回显中“Active”字段的值包含“active (running)”,表示irqbalance服务已正常开启,如图1所示。

      图1 irqbalance服务正常开启

  3. (可选)开启中断绑定。

    开启irqbalance服务让中断自由调度,网络性能提升。如果提升后的网络性能仍不满足您的预期,可以手动设置弹性云服务器操作系统的中断亲和性。

    具体操作如下:

    执行以下脚本,使得弹性云服务器中每个CPU服务一个多队列的中断请求,一对一的对应设置。即一个队列对应一个中断号,一个中断号绑定一个CPU,一一对应。

    #!/bin/bash
    service irqbalance stop
    
    eth_dirs=$(ls -d /sys/class/net/eth*)
    if [ $? -ne 0 ];then
        echo "Failed to find eth*  , sleep 30" >> $ecs_network_log
        sleep 30
        eth_dirs=$(ls -d /sys/class/net/eth*)
    fi
    
    for eth in $eth_dirs
    do
        cur_eth=$(basename $eth)
        cpu_count=`cat /proc/cpuinfo| grep "processor"| wc -l`
        virtio_name=$(ls -l /sys/class/net/"$cur_eth"/device/driver/ | grep pci |awk {'print $9'})
    
        affinity_cpu=0
        virtio_input="$virtio_name""-input"
        irqs_in=$(grep "$virtio_input" /proc/interrupts | awk -F ":" '{print $1}')
        for irq in ${irqs_in[*]}
        do
            echo $((affinity_cpu%cpu_count)) > /proc/irq/"$irq"/smp_affinity_list
            affinity_cpu=$[affinity_cpu+2]
        done
    
        affinity_cpu=1
        virtio_output="$virtio_name""-output"
        irqs_out=$(grep "$virtio_output" /proc/interrupts | awk -F ":" '{print $1}')
        for irq in ${irqs_out[*]}
        do
            echo $((affinity_cpu%cpu_count)) > /proc/irq/"$irq"/smp_affinity_list
            affinity_cpu=$[affinity_cpu+2]
        done
    done

  4. (可选)开启XPS、RPS特性。

    XPS主要是针对多队列的网卡发送时的优化,当发送一个数据包的时候,它会根据CPU来选择对应的队列。

    #!/bin/bash
    # enable XPS feature
    cpu_count=$(grep -c processor /proc/cpuinfo)
    dec2hex(){
      echo $(printf "%x" $1)
    }
    eth_dirs=$(ls -d /sys/class/net/eth*)
    if [ $? -ne 0 ];then
        echo "Failed to find eth* , sleep 30" >> $ecs_network_log
        sleep 30
        eth_dirs=$(ls -d /sys/class/net/eth*)
    fi
    for eth in $eth_dirs
    do
        cpu_id=1
        cur_eth=$(basename $eth)
        cur_q_num=$(ethtool -l $cur_eth | grep -iA5 current | grep -i combined | awk {'print $2'})
        for((i=0;i<cur_q_num;i++))
        do
            if [ $i -eq $ cpu_count ];then
                cpu_id=1
            fi
            xps_file="/sys/class/net/${cur_eth}/queues/tx-$i/xps_cpus"
            rps_file="/sys/class/net/${cur_eth}/queues/rx-$i/rps_cpus"
            cpuset=$(dec2hex "$cpu_id")
            echo $cpuset > $xps_file
            echo $cpuset > $rps_file
            let cpu_id=cpu_id*2
        done
    done