云资源PAAS平台如何高效管理硬件设备?

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_38625669/article/details/89713378

善用 udev 管理硬件设备

在这里插入图片描述
笔者:陈大
有任何疑问欢迎关注微信公众号:网易游戏运维平台。(长按识别上图二维码)
微信公众号原文链接:云资源PAAS平台如何高效管理硬件设备?

前言

随着业务的发展,现如今的小小云所使用的硬件也是越来越高级。从一开始普通的双盘位 DELL 1950,到现在多达 26 盘位的混合多种磁盘类型的存储服务器 DELL R730xd;从普通的刀片千兆网,到现在多达 4 张万兆网的网络节点 DELL R630。这种多盘位及多网卡设备的出现,给硬件设备的管理带来了不小的挑战,本文将分享 udev 相关知识及应用心得,希望能起抛砖引玉的效果。

udev 的前世今生

在 Linux 2.6 之前,Linux 使用的是一套 devfs 的设备管理虚拟文件系统,挂载在 /dev 目录下,每个设备对应一个文件(Linux哲学:一切皆文件),通过这些特殊文件实现设备的交互及管理。但它有些无法避免的缺点,比如设备名的不确定性,一个设备所对应的设备文件可能发生变化(比如一台机器新插一个硬盘到原来的空盘位,根据识别的顺序不同,原来的盘符都可能发生变化);比如命名规则不灵活,无法任意指定等等。因此在 Linux 2.6 之后,Linux 重新设计了一套 sysfs,使用设备树的方式向用户空间提供直观的设备及驱动信息,而 udev 则是基于 sysfs 提供的设备入口和 uevent 通道开发出的全新的 Linux 设备管理器。

关键要点

  • udev 基于 sysfs,是一套用户空间程序,对应的进程是 udevd。
  • udev 能通过定义一个 udev 规则来产生你所需要设备文件(这也是 udev 灵活的根源)。
  • udevadm 是命令行工具,用于向 udevd 发送指令。

udev 能做什么

  • 重命名设备为我们所需要的名字
  • 创建软链接到设备节点来提供一个可选的固定的设备节点名字
  • 基于程序或脚本的输出来命名设备节点
  • 更改设备节点的权限及所有权
  • 在设备节点被创建或删除时触发脚本操作

udev 规则说明

1. udev 主配置文件

在 /etc/udev/udev.conf 配置文件中,可以配置比如日志级别等设置,需要注意的是 udev 在 initramfs 阶段就开始执行,如果 udev.conf 有更新,需要执行 update-initramfs -u 来更新 initramfs。

2. udev 规则文件

位于 /etc/udev/rules.d/,该目录为 udev 管理设备时所使用的规则文件所在目录,注意所有的规则文件必须以 “.rules” 为后缀名。

在 udev 规则文件中,所有的非空行都被视为一条规则,每条规则一行,由多个 key-value 键值对组成,并由逗号隔开,键值对可以分为**条件匹配键值对赋值键值对**,每条规则中可以有多个匹配键值对和多个赋值键值对。同时 value 还支持 shell 通配符,利用不同键值对就可以完成我们对各种复杂的设备管理的需求。

以我们最熟悉的 /etc/udev/rules.d/70-persistent-net.rules 为例

# PCI device 0x14e4:/sys/devices/pci0000:00/0000:00:07.0/0000:10:00.0 (bnx2)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:21:5e:91:c9:bc", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

# PCI device 0x14e4:/sys/devices/pci0000:00/0000:00:07.0/0000:10:00.1 (bnx2)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:21:5e:91:c9:be", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

其中 == 为匹配键值对,= 为赋值键值对,这两条规则指定了在添加网卡设备时,根据多个属性匹配(主要是 MAC 地址不同),设置对应的 eth 名称。这两条规则是系统默认生成的,规则生成后,原有规则不再变动,这也就导致我们在更换服务器主板后,需要清理这个文件才能网络恢复(因为旧的规则占用旧的 eth 名称,换了主板后,顺带网卡 MAC 地址变化,系统会识别为新设备,添加新规则,eth 名字往下顺移,导致原有网络配置与 eth 名称对应不上。)

3 操作符

操作符 说明
== 比较键、值,若等于,则该条件满足
!= 比较键、值,若不等于,则该条件满足
= 对一个键赋值
+= 对一个 key 赋值并保留多个条目(列表值)
-= 删除列表键值中的对应值
:= 对一个 key 最终赋值并结束规则防止后续规则的修改

4 可用于匹配常见 KEY 类型

key 名称 详细说明
ACTION 事件 (uevent) 的行为,例如:添加设备 add、设备删除 remove。
KERNEL 为设备匹配的内核名字,如 eth0,sda。
SUBSYSTEM 设备的子系统名称,比如 sda 的子系统为 block,eth0 的子系统为 net。(如何查看设备所属的SUBSYSTEM见下文)
SYMLINK 设备的软链接名,如果之前的规则设置了 SYMLINK 这个 key,则可以使用该 key 来匹配,可以有多个 SYMLINK,一条匹配规则中只有一个 SYMLINK 能被匹配命中。注意:对网卡设备无效
NAME 网卡设备的命名,如果之前的规则设置了 NAME 这个 key,则可以使用该 key 来匹配。注意:只针对网卡有效
DRIVER 设备的驱动名称,在外插多网卡机器上,通过这个 key 可以筛选出我们所需要的网卡。
ATTR{filename} 匹配设备的 sysfs 属性值。(如何查看设备所有可用的属性值见下文)
TEST{octal mode mask} 用于判断文件是否存在,可以指定八进制的文件权限掩码。
PROGRAM 执行一个程序,如果程序成功返回,key 为 true。该程序的标准输出可以从 RESULT 这个 key 中读取。
RESULT PROGRAM操作执行一个程序的标准输出内容。

5.可用于赋值常见 KEY 类型

key 名称 详细说明
NAME 用于对网卡设备进行重新命名。注意:只针对网卡有效
SYMLINK 创建设备的软链接,位于 /dev/ 目录下,一个设备允许有多个软链接。注意:对网卡设备无效
OWNER,GROUP,MODE 用于设置设备的权限属性。
ATTR{key} 用于设置设备的 sysfs 属性。
SYSCTL{kernel parameter} 用于设置设备的内核参数。
RUN{type} 用于触发外部命令或脚本。注意:udevd 在系统启动中非常靠前,它运行时 rootfs 还处于只读阶段,一些修改文件内容的操作会失败;另外命令及脚本需要使用绝对路径。

6.可用于 value 的常见内部变量

内部变量 详细说明
$kernel, %k 该设备的内核名字
$number, %n 该设备的内核名字的编号,比如 “sda3” 对应编号为 ”3“。
$devpath, %p 该设备的 devpath,比如 /sys/devices/pci0000:00/0000:00:03.0/net/eth0,对应的 devpath 值为 /devices/pci0000:00/0000:00:03.0/net/eth0
$parent, %P 该设备的父节点名称
$result, %c PROGRAM调用外部命令执行返回的输出。
$name 该设备当前的名称
$attr{file} 设备对应的 sysfs 属性。
$devnode, %N 该设备在 /dev/ 下的名称,比如 /dev/sda
%% %符号
$$ $符号
篇幅所限,这里只列举一些常用的 KEY 和变量,详细内容见本文后面的参考资料

7.通配符规则

匹配符 说明
* 匹配任意长度的字符,包括空字符串。
? 匹配任意单个字符。
[] 匹配指定字符区间的单个字符,[0-9] 匹配 0-9 任意一个数字,[!0-9] 匹配非 0-9 数字的单个字符。
| 匹配两项之间的一个选择。比如**“abc|x*”** 匹配 “abc” 或者 "x"*。

udev 应用样例

  • 案例 1: 我们在线上环境发现 Broadcom 的万兆网卡(采用 bnx2x 驱动)在 VXLAN 大流量的场景下,有驱动 crash 的情况出现,我们为了规避这种情况,需要关闭对应网卡的 VXLAN Offload 特性。一般来说可以考虑在启动脚本中增加对应操作或是在 /etc/network/ 中增加对应的钩子脚本,但总是需要自己写一堆匹配逻辑,改用 udev 规则文件可以十分方便的完成这种需求。

    root@host:/home/igi# cat /etc/udev/rules.d/90-vxlan-offload-off.rules
    SUBSYSTEM=="net", ACTION=="add", DRIVERS=="bnx2x", RUN="/sbin/ethtool -K %k tx-udp_tnl-segmentation off"
    
  • 案例 2: 我们的存储节点为了达到高负载下更好的IO时延,需要把 IO 调度策略切换到 deadline 模式,这种操作,除了启动脚本外,或是修改 grub 参数,或是采用 sysfsutils 的配置文件来实现,但无论哪一种,都没有 udev 规划来得方便。

    igi@host:~$ cat /etc/udev/rules.d/60-disk-scheduler.rules
    ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/scheduler}="deadline"
    
    • sysfsutils 的配置文件 /etc/sysfs.conf 也可以完成修改 IO scheduler 的功能,但它只支持精确匹配,这就要求必须精确知道所有盘的名字,否则会报错误,但由于我们的存储有不同的硬盘数量,这时 sysfsutils 就不太方便批量管理了。
    • 修改 grub 参数总是需要 update-grub,这个操作重了点,显然也没有部署一个配置文件方便。
    • 增加一个启动脚本也十分不规范。
  • 案例 3: 我们的网络节点需要打开 SR-IOV 功能,并把 VF 数量设置到最大(不同网卡支持的最大 VF 数量不同),传统的启动脚本或是钩子脚本,依旧需要写一堆处理逻辑,我们看看 udev 是如何实现把支持SR-IOV功能的设备开启最大 VF 的。

igi@host:~$ cat /etc/udev/rules.d/80-net-sriov.rules
SUBSYSTEM==“pci”, ATTR{sriov_totalvfs}!=“0”, ATTR{sriov_numvfs}="$attr{sriov_totalvfs}"
```
* SR-IOV SUBSYSTEM是 pci,而非 net,可通过 udevadm info -p /sys/class/net/eth0 -a 查询对应设备每个节点的信息

udevadm 使用范例

  • 查询一个设备的各种属性

    #通过以下命令可以查询一个设备的子系统名称
    udevadm info /dev/sda  | grep SUBSYSTEM
    
    #通过以下命令可以递归查看一个设备及它相关的设备所有的信息及可使用的属性
    udevadm info /sys/class/net/eth0 -a
    
  • 测试 udev 规则, 需要注意 RUN 这类 key 在 test 操作中不会被执行。

    udevadm test /sys/class/net/eth0
    
  • 触发 udev 指定事件信号,可以用来重新加载指定规则, 下面代码演示了通过 trigger 执行 udev 规则的例子。

    root@host:/# ifconfig eth0 mtu 1500
    root@host:/# ifconfig eth0 | grep MTU
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
    root@host:/# cat /etc/udev/rules.d/test.rules
    SUBSYSTEM=="net", ACTION=="add", KERNEL=="eth0", NAME="eth0", RUN="/sbin/ifconfig %k mtu 1400"
    root@host:/# udevadm trigger -c add -s net
    root@host:/# ifconfig eth0 | grep MTU
              UP BROADCAST RUNNING MULTICAST  MTU:1400  Metric:1
    

参考资料

展开阅读全文

没有更多推荐了,返回首页