上一篇文章中,分享了关于低成本全闪存 NAS 的个人方案选择。

本篇文章,来聊聊硬件相关部分,以及软件的基础配置部分,也聊聊雷电组网的踩坑之旅。

写在前面

我使用的设备是 NUC9i5QNX,这台设备的硬件基础规格,可以在 Intel ARK 网站中找到。在上一篇文章《廉价的全闪存雷电 NAS 折腾笔记:组网方案的选择》中,我介绍了这台设备的优势,感兴趣可以自行翻阅。

本文的主角:NUC9

简单来说,NUC 9 支持一大票有用的接口,并且可以通过 PCIe 继续扩展 NVMe 盘位或网卡。

NUC 9 丰富的端口支持

如果你的 NUC9 选择了带有显卡的版本,并且希望用这个显卡跑一些 AI 程序,也可以参考之前写过的两篇文章,来进行折腾:《基于 Docker 的深度学习环境:入门篇》、《基于 Docker 的深度学习环境:Windows 篇》,这两篇文章聊过了在 Linux 和 Windows 环境下,如何简单、正确的配置 GPU Docker 环境。

测试使用的老硬盘

本文中,我在 NUC9 上使用的固态硬盘是很早之前汰换下来的硬盘,所以在写入速度上,并不会特别的亮眼,但好处是发热量小,以及不用额外破费银子。

在开始折腾之前,因为这款设备的发布时间较早(20~21年),所以推荐先升级 BIOS 。

必要的 BIOS 升级

如果你的设备硬件型号也是 NUC9i5QN、NUC9i7QN、NUC9i9QN 之一,可以在 Intel 下载中心,找到 NUC9 的 BIOS 升级程序,下载到今年 5 月 9 日发布的新版本 BIOS 固件如果你选择了其他设备,请自行寻找合适的 BIOS 程序进行升级。

一般情况下,BIOS 属于我们购买机器后,一般不会关注到的细节。但从个人使用硬件的经验来看,设备发行后的 BIOS 至少要等一年半载才能够填坑完毕,包括并不局限于底层漏洞、硬件设备支持列表完善、BIOS 程序本身的 BUG 等等。我们从 Intel NUC9 BIOS 发行日志中,也可以看到更新 BIOS 的必要性。

我到手的设备默认的 BIOS 版本是 OXCFL579.0045.2020.0617.1710,不用翻看官网,单从命名也看得出来是三年前出厂时的版本。说起来这个版本的构建完成时间点,是在朝九晚五的 Intel 工程师们接近下班后构建的。(一定是 CI,不是人肉整的,哈哈 :-D )

升级 BIOS 的方式有许多种,我的升级方式是:

  1. 翻箱倒柜找到一块 U 盘,在操作系统中对其进行格式化(FAT 格式)。
  2. 将下载好的 QX0072.cap 文件放置到 U 盘根目录,将 U 盘插在设备背板插槽,重启设备。
  3. 在启动设备的时候按着 F7,进入 BIOS 升级工具中。
  4. 选择 U 盘里的升级文件,确保电源稳定的情况下,等待设备升级完毕。

完成 BIOS 升级之后,NUC9 默认是会关机的,所以耐心等待固件升级完毕后,我们开机按着 F2 进入 BIOS 就能够看到更新后的 BIOS 版本啦。

在 BIOS 里,我们可以禁用一些设备,以及开启更节能的休眠,对于长时间运行的设备来说,还是很必要的。

这些我们可以稍晚些再设置,在安装完毕操作系统前,我们先调用全部的性能,把系统安装好先。

如果你只想和快速上手,那么可以跳过踩坑,直接阅读“雷电 NAS 操作系统选择”小节。

我相信我的读者有各种 NAS 操作系统的粉丝,所以这里我们就挨着聊聊常见系统的踩坑之路。

测试硬盘能力

测试 Linux 的磁盘读写能力,我们可以使用 FIO 来进行,首先进行软件的安装:

apt-get install fio 

先来测试顺序读写 10G 的文件,测试结果是大文件读写,磁盘写入能力大概只有 500MB/s 左右:

# fio -filename=test -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=16k -size=10G -numjobs=1 -runtime=600 -group_reporting -name=write

write: (g=0): rw=write, bs=(R) 16.0KiB-16.0KiB, (W) 16.0KiB-16.0KiB, (T) 16.0KiB-16.0KiB, ioengine=psync, iodepth=1
fio-3.33
Starting 1 thread
write: Laying out IO file (1 file / 10240MiB)
Jobs: 1 (f=1): [W(1)][100.0%][w=479MiB/s][w=30.7k IOPS][eta 00m:00s]
write: (groupid=0, jobs=1): err= 0: pid=6608: Mon Sep 11 23:57:20 2023
  write: IOPS=30.7k, BW=479MiB/s (503MB/s)(10.0GiB/21360msec); 0 zone resets
    clat (usec): min=23, max=1107, avg=31.85, stdev= 3.71
     lat (usec): min=24, max=1107, avg=32.10, stdev= 3.71
    clat percentiles (nsec):
     |  1.00th=[29824],  5.00th=[30848], 10.00th=[31104], 20.00th=[31360],
     | 30.00th=[31360], 40.00th=[31616], 50.00th=[31616], 60.00th=[31872],
     | 70.00th=[31872], 80.00th=[32128], 90.00th=[32640], 95.00th=[33024],
     | 99.00th=[34048], 99.50th=[35072], 99.90th=[55552], 99.95th=[63744],
     | 99.99th=[85504]
   bw (  KiB/s): min=488192, max=494656, per=100.00%, avg=491089.52, stdev=1067.40, samples=42
   iops        : min=30512, max=30916, avg=30693.10, stdev=66.71, samples=42
  lat (usec)   : 50=99.84%, 100=0.16%, 250=0.01%, 500=0.01%, 1000=0.01%
  lat (msec)   : 2=0.01%
  cpu          : usr=5.29%, sys=31.13%, ctx=655383, majf=0, minf=0
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,655360,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
  WRITE: bw=479MiB/s (503MB/s), 479MiB/s-479MiB/s (503MB/s-503MB/s), io=10.0GiB (10.7GB), run=21360-21360msec

Disk stats (read/write):
  nvme1n1: ios=0/648710, merge=0/220, ticks=0/13924, in_queue=13934, util=99.67%

测试文件顺序读取,性能相对好一些,900MB/s 的水平:

# fio -filename=test -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=16k -size=10G -numjobs=1 -runtime=600 -group_reporting -name=read

read: (g=0): rw=read, bs=(R) 16.0KiB-16.0KiB, (W) 16.0KiB-16.0KiB, (T) 16.0KiB-16.0KiB, ioengine=psync, iodepth=1
fio-3.33
Starting 1 thread
Jobs: 1 (f=1): [R(1)][100.0%][r=900MiB/s][r=57.6k IOPS][eta 00m:00s]
read: (groupid=0, jobs=1): err= 0: pid=6642: Mon Sep 11 23:58:29 2023
  read: IOPS=57.5k, BW=898MiB/s (941MB/s)(10.0GiB/11407msec)
    clat (usec): min=15, max=7055, avg=17.13, stdev=10.42
     lat (usec): min=15, max=7056, avg=17.16, stdev=10.42
    clat percentiles (usec):
     |  1.00th=[   17],  5.00th=[   17], 10.00th=[   17], 20.00th=[   17],
     | 30.00th=[   17], 40.00th=[   17], 50.00th=[   17], 60.00th=[   17],
     | 70.00th=[   17], 80.00th=[   18], 90.00th=[   18], 95.00th=[   19],
     | 99.00th=[   21], 99.50th=[   22], 99.90th=[   91], 99.95th=[  149],
     | 99.99th=[  281]
   bw (  KiB/s): min=906208, max=925824, per=100.00%, avg=919847.27, stdev=4588.69, samples=22
   iops        : min=56638, max=57864, avg=57490.45, stdev=286.79, samples=22
  lat (usec)   : 20=96.86%, 50=2.96%, 100=0.08%, 250=0.07%, 500=0.02%
  lat (usec)   : 1000=0.01%
  lat (msec)   : 10=0.01%
  cpu          : usr=4.91%, sys=24.21%, ctx=655367, majf=0, minf=5
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued rwts: total=655360,0,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
   READ: bw=898MiB/s (941MB/s), 898MiB/s-898MiB/s (941MB/s-941MB/s), io=10.0GiB (10.7GB), run=11407-11407msec

Disk stats (read/write):
  nvme1n1: ios=654643/3, merge=0/1, ticks=8465/4, in_queue=8471, util=99.23%

接着再试试随机写入和读取,得到的结果分别是 677 MB/s 和 1412 MB/s:

# fio -filename=test -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=16k -size=10G -numjobs=1 -runtime=600 -group_reporting -name=write

Run status group 0 (all jobs):
  WRITE: bw=677MiB/s (710MB/s), 677MiB/s-677MiB/s (710MB/s-710MB/s), io=10.0GiB (10.7GB), run=15133-15133msec

Disk stats (read/write):
  nvme1n1: ios=0/645072, merge=0/2, ticks=0/10324, in_queue=10327, util=99.39%

# fio -filename=test -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=16k -size=10G -numjobs=11 -runtime=600 -group_reporting -name=read

Run status group 0 (all jobs):
   READ: bw=1412MiB/s (1481MB/s), 1412MiB/s-1412MiB/s (1481MB/s-1481MB/s), io=110GiB (118GB), run=79766-79766msec

Disk stats (read/write):
  nvme1n1: ios=7207624/15, merge=0/4, ticks=799526/11, in_queue=799540, util=99.90%

所以,本文雷电组网之后,最大写入速度估计不会偏离这个写入速度的峰值:503 MB/s 到 710 MB/s。

等稍晚些时候,选择好新硬盘后,再来做数据更新。

TrueNAS(FreeNAS)雷电组网踩坑

TrueNAS 是一款很棒的开源商业化的 NAS 操作系统,从 2005 年项目启动至今有接近二十个年头了。在 2019 年的时候,项目将 FreeNAS 的名字正是调整为了 TrueNAS Core,作为开源商业化 NAS 的一部分存在。

TrueNAS 安装测试

TrueNAS 的安装非常简单,不过系统默认没有雷电驱动,社区里虽然多有讨论,但没有有效的稳定方案可以使用,或源代码可以自行编译驱动。

所以在这个方案里中就不是很合适了,只能暂时放弃啦。

Unraid 雷电组网踩坑

Unraid 相比 TrueNAS 对于雷电支持了,但没有完全支持。

在不极深度折腾的情况下,可以得到有限的雷电支持,如果希望使用 Unraid 来使用雷电组网,那么建议锁定系统版本。

Unraid 虽然支持雷电,但是因为驱动的问题,实际使用上会有不少小问题,包括使用雷电传输时,只有一颗 CPU 在干活,以及基本会耗尽性能,如果未来官方能够将设备驱动源码公开,借助开源社区的力量,或许支持度会有转机。

Unraid 网卡驱动 BUG

考虑到使用雷电网络的稳定性,我放弃了这个方案。

Unraid 激活雷电组网

虽然我没有选择 Unraid 作为雷电 NAS 操作系统,但想到可能 Unraid 是一些同学的心头好,就留下一些资料避免后来人踩坑吧。

当我们将支持雷电的设备和安装了 Unraid 设备连接后,系统界面中默认除了 PCI 设备日志外,是没有任何变化的,你期望的是网卡页面多出一个 thunderbolt 网卡,实际上,默认什么都不会发生。

插好雷电数据线后,我们需要先使用 lspci -nnk | grep Thunderbolt 来查看雷电驱动是否正常工作:

# lspci -nnk | grep Thunderbolt

03:00.0 PCI bridge [0604]: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:15ea] (rev 06)
	Subsystem: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:2088]
04:00.0 PCI bridge [0604]: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:15ea] (rev 06)
	Subsystem: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:2088]
04:01.0 PCI bridge [0604]: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:15ea] (rev 06)
	Subsystem: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:2088]
04:02.0 PCI bridge [0604]: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:15ea] (rev 06)
	Subsystem: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:2088]
04:04.0 PCI bridge [0604]: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:15ea] (rev 06)
	Subsystem: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:2088]
05:00.0 System peripheral [0880]: Intel Corporation JHL7540 Thunderbolt 3 NHI [Titan Ridge 4C 2018] [8086:15eb] (rev 06)
	Subsystem: Intel Corporation JHL7540 Thunderbolt 3 NHI [Titan Ridge 4C 2018] [8086:2088]
39:00.0 USB controller [0c03]: Intel Corporation JHL7540 Thunderbolt 3 USB Controller [Titan Ridge 4C 2018] [8086:15ec] (rev 06)
	Subsystem: Intel Corporation JHL7540 Thunderbolt 3 USB Controller [Titan Ridge 4C 2018] [8086:2088]

从上面的日志输出中,我们能够看到通过驱动识别到的雷电设备的控制器是 Intel JHL7540,支持的雷电版本是雷电3。

如果你的设备没有输出任何日志,那么说明你的设备并不支持雷电,或者驱动有问题,需要先解决驱动问题。

如果驱动没有问题,雷电数据线也连接好了,我们将能够使用下面的命令(Linux 内核里的设备管理器)访问和收集雷电硬件信息:

udevadm info -a -p /sys/class/net/thunderbolt0

命令执行完毕后,我们可以看到类似下面的信息,包括雷电网卡的各种详细属性、连接组网的设备的详细信息、约定的网络速率等:

# udevadm info -a -p /sys/class/net/thunderbolt0

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:1c.4/0000:03:00.0/0000:04:00.0/0000:05:00.0/domain0/0-0/0-1/0-1.0/net/thunderbolt0':
    KERNEL=="thunderbolt0"
    SUBSYSTEM=="net"
    DRIVER==""
    ATTR{carrier_changes}=="1"
    ATTR{dev_id}=="0x0"
    ATTR{carrier_down_count}=="1"
    ATTR{proto_down}=="0"
    ATTR{address}=="02:4c:3f:xx:xx:xx"
    ATTR{operstate}=="down"
    ATTR{link_mode}=="0"
    ATTR{mtu}=="1500"
    ATTR{gro_flush_timeout}=="0"
    ATTR{carrier_up_count}=="0"
    ATTR{ifalias}==""
    ATTR{netdev_group}=="0"
    ATTR{napi_defer_hard_irqs}=="0"
    ATTR{ifindex}=="5"
    ATTR{broadcast}=="ff:ff:ff:ff:ff:ff"
    ATTR{type}=="1"
    ATTR{dev_port}=="0"
    ATTR{name_assign_type}=="1"
    ATTR{addr_assign_type}=="0"
    ATTR{addr_len}=="6"
    ATTR{threaded}=="0"
    ATTR{tx_queue_len}=="1000"
    ATTR{iflink}=="5"
    ATTR{flags}=="0x1002"

  looking at parent device '/devices/pci0000:00/0000:00:1c.4/0000:03:00.0/0000:04:00.0/0000:05:00.0/domain0/0-0/0-1/0-1.0':
    KERNELS=="0-1.0"
    SUBSYSTEMS=="thunderbolt"
    DRIVERS=="thunderbolt-net"
    ATTRS{prtcstns}=="0x00000003"
    ATTRS{prtcvers}=="1"
    ATTRS{prtcrevs}=="1"
    ATTRS{key}=="network"
    ATTRS{prtcid}=="1"

  looking at parent device '/devices/pci0000:00/0000:00:1c.4/0000:03:00.0/0000:04:00.0/0000:05:00.0/domain0/0-0/0-1':
    KERNELS=="0-1"
    SUBSYSTEMS=="thunderbolt"
    DRIVERS==""
    ATTRS{vendor_name}=="Apple Inc."
    ATTRS{maxhopid}=="15"
    ATTRS{vendor}=="0xa27"
    ATTRS{device}=="0xa"
    ATTRS{rx_lanes}=="1"
    ATTRS{rx_speed}=="20.0 Gb/s"
    ATTRS{unique_id}=="c377841e-xxxx-xxxx-xxxx-ed56be6d2548"
    ATTRS{tx_lanes}=="1"
    ATTRS{tx_speed}=="20.0 Gb/s"
    ATTRS{device_name}=="MacBookPro16,1"

... ...

通过 cat /etc/udev/rules.d/70-persistent-net.rules,我们可以看到系统中自动生成网卡配置:

# cat /etc/udev/rules.d/70-persistent-net.rules 
# PCI device 0x8086:0x1533 (igb)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="f4:6b:8c:xx:xx:xx", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

# PCI device 0x8086:0x15bb (e1000e)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="f4:6b:8c:xx:xx:xx", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

参考上面的配置和设备管理器的输出,我们可以创建一个新的文件 /etc/udev/rules.d/71-persistent-net.rules

# Thunderbolt0
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="02:4c:3f:xx:xx:xx", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="thunderbolt", NAME="eth3"

当完成配置信息的创建后,我们执行下面的命令,刷新设备管理器的列表和激活新增的雷电网卡:

udevadm control --reload
udevadm trigger --action=add --attr-match=address="02:4c:3f:xx:xx:xx"

当上面的命令执行完毕后,我们使用下面的命令,分别为网卡手动设置 IP 地址、掩码、 MTU,启动网卡:

ip a add 192.168.123.3/255.255.255.0 dev thunderbolt0
ip link set dev thunderbolt0 mtu 1500
ip link set dev thunderbolt0 up
# 或者使用
ifconfig 192.168.123.3 netmask 255.255.255.0 up

这个时候,连接雷电 NAS 的设备的网卡处应该会有“一些变化”了,我们在连接设备处也设置相同的 MTU、相同网段的新 IP 地址和 IP 掩码后,设备就可以联通使用啦。

激活界面中的网卡信息

虽然通过上面的设置,我们已经能够通过命令行来通过雷电网卡来传输数据了。但是 Unraid 的网络界面中,还是不会出现这个网卡,想要解决这个问题,我们需要手动执行下面的命令:

echo 1 > /sys/bus/pci/rescan

当我们触发设备的重新扫描之后,网页中就会出现一块名为 thunderbolt 的新网卡了。

为了确保设备热拔插,雷电状况展示正常,这里最好写一个脚本,定时的执行这个重新扫描操作。

Unraid 雷电组网的性能问题

如果我们使用 ethtool 来查看一般的网卡信息,将能看到网卡队列情况,这说明网卡支持将输出传输的计算任务负载均衡到多个 CPU 中进行处理,将极大的提升数据吞吐能力,和有效降低整机负载:

# root@NAS:~# ethtool -l eth0

Channel parameters for eth0:
Pre-set maximums:
RX:		n/a
TX:		n/a
Other:		1
Combined:	4
Current hardware settings:
RX:		n/a
TX:		n/a
Other:		1
Combined:	4

但是,倘若相查看或者设置雷电网卡的相关能力的时候,我们会得到“操作不被支持”的错误提示。

# root@NAS:~# ethtool -l thunderbolt0
netlink error: Operation not supported

# root@NAS:~# ethtool -L thunderbolt0 combined 8
netlink error: Operation not supported

在没有驱动支持的前提下,雷电数据传输将只消耗一颗 CPU 的资源,这也会或多或少的影响数据传输效率。

雷电 NAS 操作系统选择:Ubuntu

这里,我选择的是 Ubuntu Desktop:对于一般的硬件,包括电源节能设置、核显驱动支持等都还不错。安装 Ubuntu 的流程和以往并没有太大不同,依旧是老生常谈的三步曲:下载镜像、制作启动盘、安装系统。

关于如何制作镜像启动盘,以及基础的安装过程,参考《在笔记本上搭建高性价比的 Linux 学习环境:基础篇》中提到的内容即可。

一般来说,我们选择 LTS 可以省心很多,不过如果你想要使用更新的特性,也可以考虑非 LTS 的奇数年份发行版,比如 23.04、23.10。Ubuntu 的非 LTS 版本升级到 LTS 版本其实也是非常简单的,未来如果想要升级操作系统版本,可以参考之前的文章《抢先体验 Ubuntu 22.04 Jammy Jellyfish》来进行操作。

雷电组网速度测试

系统安装完毕之后,默认会完成自动组网,我们使用雷电线连接 Mac 和 NUC9,先进行一次传输测试。

我们可以使用年初折腾数据传输时,两篇文章中提到的方法来进行测试: 《MacBook 与其他设备的低成本高性能数据传输方案(一)》、《MacBook 与其他设备的低成本高性能数据传输方案(二)》。

相比较使用 Unraid ,Ubuntu 的好处是雷电设备连接后,能够启动自动组网,所以我们先使用默认配置进行网速测试,依旧是一端执行 iperf3 -s 启动服务,另外一端执行命令,进行实际数据发送,来探测带宽性能。为了避免磁盘性能影响带宽探测,我们使用 -Z 参数(zerocopy),来避免磁盘读写:

iperf3 -c 169.254.123.142 -f GB --omit 3 -Z

当命令执行完毕后,我们会发现速度非常的离谱,远远低于我们的预期:

Connecting to host 169.254.123.142, port 5201
[  5] local 10.11.12.90 port 56571 connected to 169.254.123.142 port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  13.2 MBytes  0.01 GBytes/sec                  (omitted)
[  5]   1.00-2.00   sec  8.77 MBytes  0.01 GBytes/sec                  (omitted)
[  5]   2.00-3.00   sec  41.8 MBytes  0.04 GBytes/sec                  (omitted)
[  5]   0.00-1.00   sec  44.8 MBytes  0.04 GBytes/sec                  
[  5]   1.00-2.00   sec  46.9 MBytes  0.05 GBytes/sec                  
[  5]   2.00-3.00   sec  46.4 MBytes  0.05 GBytes/sec                  
[  5]   3.00-4.00   sec  42.1 MBytes  0.04 GBytes/sec                  
[  5]   4.00-5.00   sec  42.7 MBytes  0.04 GBytes/sec                  
[  5]   5.00-6.00   sec  44.9 MBytes  0.04 GBytes/sec                  
[  5]   6.00-7.00   sec  44.7 MBytes  0.04 GBytes/sec                  
[  5]   7.00-8.00   sec  47.0 MBytes  0.05 GBytes/sec                  
[  5]   8.00-9.00   sec  44.9 MBytes  0.04 GBytes/sec                  
[  5]   9.00-10.00  sec  19.5 MBytes  0.02 GBytes/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.00  sec   424 MBytes  0.04 GBytes/sec                  sender
[  5]   0.00-10.13  sec   425 MBytes  0.04 GBytes/sec                  receiver

如果你也出现了这个情况,大概率是因为有线网络的路由优先级高于雷电网络,你可以调整网络的优先级来解决问题,或者让设备之间只使用雷电数据线进行连接。

我这边触发了“笔记本电脑的无线网卡”到“NUC有线网络”的数据传输链路。所以,当我将 NUC9 连接的网线拔掉,让设备之间仅有雷电连接后,再次进行测试,发现传输速度确实稍有提升。

但是,提升的速度没有达到预期,这里还需要做两个简单的操作:手动设置设备的 IP、掩码,以及 MTU(比如设置为 9000)。当完成设备相关数值的设置后,再次进行测试,能够看到我们已经能够使用万兆的速度来传输数据啦:

Connecting to host 192.199.199.110, port 5201
[  5] local 192.199.199.100 port 63400 connected to 192.199.199.110 port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  1.01 GBytes  1.01 GBytes/sec                  (omitted)
[  5]   1.00-2.00   sec  1.13 GBytes  1.13 GBytes/sec                  (omitted)
[  5]   2.00-3.00   sec  1.20 GBytes  1.20 GBytes/sec                  (omitted)
[  5]   0.00-1.00   sec  1.13 GBytes  1.13 GBytes/sec                  
[  5]   1.00-2.00   sec  1.13 GBytes  1.13 GBytes/sec                  
[  5]   2.00-3.00   sec  1.17 GBytes  1.17 GBytes/sec                  
[  5]   3.00-4.00   sec  1.19 GBytes  1.19 GBytes/sec                  
[  5]   4.00-5.00   sec  1.13 GBytes  1.13 GBytes/sec                  
[  5]   5.00-6.00   sec  1.13 GBytes  1.13 GBytes/sec                  
[  5]   6.00-7.00   sec  1.18 GBytes  1.18 GBytes/sec                  
[  5]   7.00-8.00   sec  1.12 GBytes  1.12 GBytes/sec                  
[  5]   8.00-9.00   sec  1.23 GBytes  1.23 GBytes/sec                  
[  5]   9.00-10.00  sec  1.18 GBytes  1.18 GBytes/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.00  sec  11.6 GBytes  1.16 GBytes/sec                  sender
[  5]   0.00-10.00  sec  11.6 GBytes  1.16 GBytes/sec                  receiver

iperf Done.

这里不指定 iperf3 的格式化参数,传输速度可能会更直观一些:

# iperf3 -c 192.199.199.110   -Z      
Connecting to host 192.199.199.110, port 5201
[  5] local 192.199.199.100 port 52954 connected to 192.199.199.110 port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  1.14 GBytes  9.75 Gbits/sec                  
[  5]   1.00-2.00   sec  1.16 GBytes  9.97 Gbits/sec                  
[  5]   2.00-3.00   sec  1.16 GBytes  10.0 Gbits/sec                  
[  5]   3.00-4.00   sec  1.17 GBytes  10.0 Gbits/sec                  
[  5]   4.00-5.00   sec  1.17 GBytes  10.0 Gbits/sec                  
[  5]   5.00-6.00   sec  1.16 GBytes  10.0 Gbits/sec                  
[  5]   6.00-7.00   sec  1.16 GBytes  10.0 Gbits/sec                  
[  5]   7.00-8.00   sec  1.16 GBytes  9.99 Gbits/sec                  
[  5]   8.00-9.00   sec  1.16 GBytes  9.96 Gbits/sec                  
[  5]   9.00-10.00  sec  1.17 GBytes  10.0 Gbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.00  sec  11.6 GBytes  9.97 Gbits/sec                  sender
[  5]   0.00-10.00  sec  11.6 GBytes  9.97 Gbits/sec                  receiver

iperf Done.

这个速度已经能够达到万兆光纤、万兆电口的速度啦,理论上雷电组网的速率还能够进一步挖掘,这个工作会在后续的文章中继续进行。

使用命令行设置网卡的 MTU

简单来说,MTU 会影响数据传输的效率。上文中,我们设置了 MTU 为 9000,这个数值实际上是 macOS 支持的最大值。

上面的操作,其实我们可以用命令行来完成,搭配一些简单的脚本,就能够实现雷电设备连接后的自动化操作了,核心的命令是 networksetup

# networksetup --help | grep MTU

networksetup -getMTU <hardwareport or device name>
networksetup -setMTU <hardwareport or device name> <value>
networksetup -listvalidMTUrange <hardwareport or device name>

上面的三个命令是目前 macOS 支持的 MTU 设置命令,分别是获取网卡的 MTU、设置网卡的 MTU,以及查看系统硬件支持的 MTU 数值范围。

因为命令需要使用到设备名称,所以我们需要通过 networksetup -listnetworkserviceorder 命令来获取所有的可用的网络设备和它的系统名称:

# networksetup -listnetworkserviceorder

An asterisk (*) denotes that a network service is disabled.

(1) USB ACM
(Hardware Port: USB ACM, Device: usbmodem14401)

(2) AX88179A
(Hardware Port: AX88179A, Device: en9)

(3) USB 10/100/1000 LAN
(Hardware Port: USB 10/100/1000 LAN, Device: en7)

(4) USB 10/100/1G/2.5G LAN
(Hardware Port: USB 10/100/1G/2.5G LAN, Device: en12)

(5) Link2TP
(Hardware Port: USB 10/100/1G/2.5G LAN, Device: en12)

(6) Thunderbolt Bridge
(Hardware Port: Thunderbolt Bridge, Device: bridge0)

(7) Wi-Fi
(Hardware Port: Wi-Fi, Device: en0)

(8) iPhone USB
(Hardware Port: iPhone USB, Device: en6)

假设这里我们需想要操作的网卡为 “Thunderbolt Bridge”,那么我们可以执行下面的命令,先来查看这张网卡的 MTU 信息:

# networksetup -getMTU bridge0

Active MTU: 9000 (Current Setting: 9000)

以及使用下面的命令,来设置网卡的 MTU 为 9000:

networksetup -setMTU bridge0 9000

我们不用担心设置会出错,因为在设置的时候,命令会检查你的输入是否在允许范围之内:

# networksetup -setMTU bridge0 65530

Error - 65530 is not in the valid MTU range of 1280-9000
** Error: The parameters were not valid.

SCP 传输实际测试

在不做任何调优的情况下,测试了几次,能够看到传输速度在 450~720 MB/s 之间。和文章开头提到的硬盘能力差别不是太大。

# scp -c aes128-ctr /Users/soulteary/Downloads/ubuntu-22.04.3-desktop-amd64.iso 192.199.199.110:

ubuntu-22.04.3-desktop-amd64.iso                                                                                                                                 100% 4804MB 451.6MB/s   00:10

ubuntu-22.04.3-desktop-amd64.iso                                                                                   100% 4804MB 541.9MB/s   00:08

ubuntu-22.04.3-desktop-amd64.iso                                                                                   100% 4804MB 720.7MB/s   00:06    

ubuntu-22.04.3-desktop-amd64.iso                                                                                   100% 4804MB 691.8MB/s   00:06

当然,除了硬盘本身的写入能力外,这里速度的差异应该还受到了固态磁盘可用缓存、内存缓存等影响,当然,还有加密传输算法的影响,所以相比较上面测试的 1GB/s 的速度而言,有了进一步的降低。

后续实际使用过程中,会考虑使用 SMB3 进行传输,以及更新硬盘,来减少传输性能的损失。

其他思路:ESXi 8 雷电组网支持验证

ESXi 是非常强大的虚拟化系统,在之前的文章中,我们有所提及。但可惜的是,ESXi 中默认是没有可用的雷电驱动的,网上唯一能找到的靠谱内容是多年前苹果雷电外设的内容,驱动是由硬件供应商提供的。

当然,如果我们选择将雷电直通给 ESXi 的具体虚拟机使用,也不是不行,比如将上面的 Ubuntu 操作系统安装在 ESXi 的虚拟机中,然后将雷电网卡和对应的 SSD 直通给设备使用。

相比较直接安装 Ubuntu 而言,这样做的好处是额外做了一个硬件整体的监控程序,以及能够更方便的迁移数据或在保留数据的情况下(毕竟是 NAS,数据和系统基本无依赖关系),使用创建一个操作系统虚拟机副本的方式,进行宿主系统的版本或者软件升级的验证。

新版本的 ESXi 虽然挑设备,但其实对 NUC 9 还是蛮友好的。我验证 NUC 9 使用的 ESXi 版本是 VMware-ESXi-8.0U1c-22088125-depot.zip,如果你想在 NUC9 上安装 ESXi8 ,可以参考早些时候的文章《快速构建和安装干净的 ESXi 8 镜像指南》来折腾一个干净又卫生的安装镜像。

定制 NUC9 使用的 ESXi 8

先使用 docker pull soulteary/easy-esxi-builder:2023.01.29 命令下载 ESXi 容器构建工具:

# docker pull soulteary/easy-esxi-builder:2023.01.29

2023.01.29: Pulling from soulteary/easy-esxi-builder
Digest: sha256:1dbf9eef564c4657a146887603bb38bc079e18bc7144009814bf4b301ff5931a
Status: Image is up to date for soulteary/easy-esxi-builder:2023.01.29
docker.io/soulteary/easy-esxi-builder:2023.01.29

然后将 ESXi 软件包 VMware-ESXi-8.0U1c-22088125-depot.zip、之前文章中提到的 NVMe 驱动、USB 驱动、社区网卡驱动等下在完毕,放在当前目录中,执行下面的命令,得到一个交互式的构建环境:

docker run --rm -it -v `pwd`:/data soulteary/easy-esxi-builder:2023.01.29

分别执行下面的命令,得到一个 600MB 左右的安装镜像文件:

# 添加基础软件包
Add-EsxSoftwareDepot /data/VMware-ESXi-8.0U1c-22088125-depot.zip
# 添加 NVMe 驱动
Add-EsxSoftwareDepot /data/nvme-community-driver_1.0.1.0-3vmw.700.1.0.15843807-component-18902434.zip
# 添加 社区网卡 驱动
Add-EsxSoftwareDepot /data/Net-Community-Driver_1.2.7.0-1vmw.700.1.0.15843807_19480755.zip
# 添加 USB网卡 驱动
Add-EsxSoftwareDepot /data/ESXi80U1-VMKUSB-NIC-FLING-64098092-component-21669994.zip

# 创建一个新的镜像配置
New-EsxImageProfile -CloneProfile "ESXi-8.0U1c-22088125-standard" -name "ESXi-8.0U1c-22088125-standard-nic" -vendor "soulteary"

# 将驱动打进新的镜像配置中
Add-EsxSoftwarePackage -ImageProfile "ESXi-8.0U1c-22088125-standard-nic" -SoftwarePackage "nvme-community"
Add-EsxSoftwarePackage -ImageProfile "ESXi-8.0U1c-22088125-standard-nic" -SoftwarePackage "net-community"
Add-EsxSoftwarePackage -ImageProfile "ESXi-8.0U1c-22088125-standard-nic" -SoftwarePackage "vmkusb-nic-fling"

# 保存新的镜像
Export-EsxImageProfile -ImageProfile "ESXi-8.0U1c-22088125-standard-nic" -ExportToIso -FilePath /data/ESXi-8.0U1c.iso

其他的踩坑说明

雷电 PCIe 扩展卡踩坑

在实际购买过扩展卡之后,个人观点目前市面上的雷电 PCIe 都不建议购买,首先是最高性价比的雷电4 扩展卡挑主板(主板需要固件支持雷电功能),其次是包括性价比不那么高的雷电3 扩展卡,对于 PCIe 接口有要求。

我有一台台式机是联想的“刃 9000K 2023”,这台机器虽然搭载了 Z790 芯片组,但是实际上能够进行扩展的只有一个 PCIe x4 的接口,并且主机设计上,这个接口在显卡的进风口位置,如果安装可能影响显卡的散热。

所以,网络上目前主流的大品牌的雷电 PCIe 扩展卡,在我的场景下均无法使用。包括并不仅限于能够搜索和购买到的联想本家的扩展卡。

联想出品的雷电3扩展卡

不过好在,设备还有一颗 20G/s 的 USB 接口,能够连接 20G/s 的硬盘盒,正巧我有这么一个硬盘盒,后续考虑就用这个硬盘盒来做这台台式机和这台 NAS / DAS 的临时交换空间。

内存的选择和使用

NUC9 i7 和 i9 版本的内存频率可以支持到 3200,但是 i5 版本只能支持到 2666。所以在内存选择上,没必要追求目前的高主频内存,并将高主频内存降级使用,建议使用相对便宜的,合适的内存就好,不必要完全上满,尤其是你不使用虚拟化的时候。

之前测试使用的光威64G内存

在之前测试的时候,我使用了早些时候购买的两根光威 32G 内存,虽然之前购买时还蛮贵的,现在的价格早已降至了当年的 40%。

2021 年支持的新国货订单记录

在跑测试的过程中,因为存在大量数据交换,会时不时“死机”,在排查了一众硬件后,使用 memtest 测试机器,发现了在内存上出现了一些问题。

检测出内存错误

光威厂商还是很靠谱的,大概不到一周的质检售后流程后,很快邮寄回来了两根新的内存。

售后直接换了两条新的内存

不过因为这台机器暂时没有跑比较重的虚拟化,本身 4C8T 的核心数也不算多,就换上了两根从二手市场便宜购置的 16G 内存。目前经过 memtest “烤鸡测试”,发现没有什么问题,在使用 ESXi 进行系统正式替换之前,因为没有大内存使用场景,暂时就不换内存啦。

散热的考虑

因为是 NAS / DAS(直连扩展) 用途,雷电数据线的长度有限,设备会放置在桌面,所以设备发热量的多少,体感还是比较明显的。

NUC 9 连接数据线后的实际位置

所以这里建议不使用带显卡的版本,不使用特别费电或者能够带来不必要热量的硬件扩展,包括并不仅限于万兆网卡、万兆或者 40G/56G 或更高的光纤网卡和光模块。

一根雷电线连接设备,没有额外的发热和太高的成本,真的不香吗?

安装细节拾遗

为了避免一些不必要的麻烦,建议在安装之前,前往 BIOS 关闭 “Secure Boot”。

最后

这篇笔记写于 9 月 1 日,但最近实在是比较忙,所以整理出来时,不知不觉已经月中旬了。

希望在这个月里,能够抽空将这台设备完全配置好,投入使用,更新一篇更为具体和落地的最佳实践 :D

–EOF