NFS Server¶
- Hostname 与 DNS:见 ACSA hosts
- 操作系统:Proxmox VE 8 (Debian 12)
登录权限¶
由于 NFS 没有计算资源,仅作存储用途,因此配置 sshd 只允许管理员登录:
HostKey /etc/ssh/ssh_host_ecdsa_key
HostCertificate /etc/ssh/ssh_host_ecdsa_key-cert.pub
TrustedUserCAKeys /etc/ssh/ssh_user_ca
PasswordAuthentication no
ChallengeResponseAuthentication no
AuthenticationMethods publickey
AllowGroups root sudo
Glados¶
截至 2025 年 1 月使用的 NFS 服务器,现在用作 ACSA-MED,替代不堪重负的群晖。
iDRAC 授权¶
我们于 2024 年 3 月 13 日从淘宝上花¥60 给这台机器购买了 iDRAC 9 Enterprise License,这样我们终于有远程 KVM 可以用了(没错戴尔把这么基础的功能加钱卖)。 这份授权文件在这,以备不时之需。
为了能让 Telegraf 从 IPMI 获取传感器信息,telegraf
用户被添加进了 sys
组,并且根据 Telegraf 文档创建了相应的 udev 规则:
KERNEL=="ipmi*", MODE="660", GROUP="sys"
ZFS¶
在之前使用 RAID 卡自带的 RAID 功能时,它只能提供非常基础的管理并且并不适合我们的使用场景。因此我们现在选择将它调到 HBA 模式,使用 ZFS 做为 RAID+LVM+caching 的 all-in-one 的解决方案。
RAID¶
Zeus¶
作为集中存储的服务器,其吞吐能力是比较重要的,因此我们使用的方案为 3*RAID-Z2。在这种情况下会损失6块盘的容量,最大故障冗余是每组两块盘。
zpool create rpool -O canmount=off -O xattr=sa -O relatime=on -O compress=zstd raidz2 /dev/sd[a-h] raidz2 /dev/sd[i-p] raidz2 /dev/sd[q-x] cache nvme0n1
Glados¶
作为医疗数据的存储服务器,一方面其型号限制了硬盘数量,另一方面它不需要很高的 IOPS,因此我们选择直接对全部 8 块硬盘使用 RAID-Z2
FYI(Legacy things)¶
We choose RAID-10 over RAID-6 for performance reasons (see this article). In ZFS this is accomplished using "mirror vdev group" setup:
zpool create rpool mirror /dev/sdc /dev/sdd mirror /dev/sde /dev/sdf mirror /dev/sdg /dev/sdh
This way /dev/sdc
and /dev/sdd
are mirrored together as one vdev (RAID-1), and three vdevs like this are added together to form a large pool (RAID-0, with minor differences).
Caching¶
默认情况下,ZFS 使用系统总内存的一半作为可调替换缓存(Adaptive Replacement Cache, ARC),其统计信息可以通过 arc_summary
命令查看。
ARC 的内存使用可以通过 ZFS 模块的参数 zfs_arc_min
和 zfs_arc_max
进行调整。因为服务器上有很多内存没有使用,我们将 ACR 设置为 4 GB 到 432 GB (Glados 上为 80 GB)。持久化变更直接修改 modprobe config 文件 /etc/zfs.conf
。
options zfs zfs_dmu_offset_next_sync=1
options zfs zfs_arc_min=4294967296
options zfs zfs_arc_max=85899345920
options zfs zfs_arc_dnode_limit_percent=40
options zfs zfs_arc_lotsfree_percent=5
options zfs zfs_vdev_async_read_max_active=8
options zfs zfs_vdev_async_read_min_active=2
options zfs zfs_vdev_scrub_max_active=5
options zfs zfs_vdev_max_active=20000
options zfs l2arc_noprefetch=0
options zfs l2arc_headroom=8
要在线更改这些值,直接写入到相应的 sys
文件:
echo 463856467968 > /sys/module/zfs/parameters/zfs_arc_min
需要注意并不是所有的参数都可以在线更改,细节请查阅 ZFS 文档。
ZFS 同样支持添加额外的高速存储(比如 SSD)作为读cache(写 cache / 写 buffer 是另一个问题),叫做 Level-2 ARC (L2ARC)。添加一个 cache 设备的命令为 zpool add rpool cache /dev/nvme1
。
写 cache(buffer) 叫做 "separate log" 设备(SLOG)。它不需要很大,因此我们直接使用系统磁盘的 LVM 一部分空间。
Compression¶
ZFS 支持在 volume 上和 dataset 上的透明压缩,我们在 NFS 共享的 home 目录上使用中等程度的压缩。
zfs set compression=zstd rpool/home
根据简单的测试,Zstd level 6 在提供不错的压缩率的同时操作仍然是 I/O 瓶颈。更高的压缩等级在特定的重度写入下可能变为 CPU 瓶颈,且压缩率提升较小,因此我们选择 Zstd-6 作为 home 目录的压缩等级。
根据该幻灯片第七页的描述,低 Zstd 等级对压缩率的影响很小,但性能差距很大,因此我们使用默认压缩等级(compression=zstd,等价于 level 3)来压缩数据。
常见的 compression=on
设置使用了一种较旧的算法 LZ4,尽管速度仍然很快,但已不再被认为是现代算法。
Snapshots¶
ZFS 支持即时快照,我们使用这一功能来防止数据意外丢失。快照是只读的,可以通过每个 dataset 根目录下的隐藏 .zfs
目录访问。例如:
ibug@snode0:~$ ls /staff/ibug/.zfs/snapshot/
20240408 20240412 20240415 20240419 20240422 20240426 20240429
这些快照目录下的文件可以复制回原始位置,并且它们是只读的。
我们每周为整个主目录创建两次快照(在每周一和周五的凌晨 5:17),并保留 7 个快照。这是通过 cron 和自定义脚本完成的。
#!/bin/sh
DATASET=rpool/home
DATE=$(date +%Y%m%d)
SNAPSHOT="$DATASET@$DATE"
if zfs list "$SNAPSHOT" >/dev/null 2>&1; then
echo "Already taken snapshot today"
exit 0
fi
zfs snapshot -r "$SNAPSHOT"
# retain latest snapshots
RETENTION=7
zfs list -t snapshot "$DATASET" |
tail -n +2 | head -n -$RETENTION | awk '{print $1}' |
xargs -rn 1 zfs destroy -rv
Extra: MegaCli¶
过时信息
MegaCli is most useful when using the disk controller in RAID mode. In HBA mode, we can access individual disks directly, and smartctl
provides more details on disks.
Download the ZIP from here. There's an RPM package under Linux
directory. Use rpm2cpio
to convert it to a CPIO archive, then cpio -idv < package.cpio
to extract.
The package contains 3 files under /opt/MegaRAID/MegaCli/
. Other than the bundled files, libncurses5
is required (install from apt
). You can symlink MegaCli64
to /usr/local/sbin
for typing less.
Usage:
- All information:
MegaCli64 -AdpAllInfo -aAll
- Physical disk information:
MegaCli64 -PdList -aAll
- Logical disk and physical disk information:
MegaCli64 -LdPdInfo -aAll
NFS Tuning¶
为了实现更好的读写性能,我们将 NFS server 的线程数调整至 256(默认为16)。
RPCNFSDCOUNT=256
Networking¶
Proxmox VE 使用 Debian 的 ifupdown
配置系统,但是提供了一个改进版本 ifupdown2
。
我们还使用 NFS 作为“网关”来为其他主机提供互联网访问,因此需要将默认的 main
路由规则从优先级 32766 移动到优先级 2,这就是在接口 lo
上进行设置的原因。
auto lo
iface lo inet loopback
up ip rule add table main pref 2 || true
up ip rule delete table main pref 32766 || true
auto eno1
iface eno1 inet manual
auto eno2
iface eno2 inet manual
auto vmbr0
iface vmbr0 inet static
address 222.195.72.127/24
gateway 222.195.72.254
bridge-ports eno1 eno2
bridge-stp off
bridge-fd 0
iface vmbr0 inet6 static
address 2001:da8:d800:112::127/64
gateway 2001:da8:d800:112::1
Because IB needs opensmd
to work correctly, so we add a pre-up
line to start the service.
因为 IB 需要 opensmd
才能正常工作,需要把 opensmd.service
设置为开机启动。
systemctl enable --now opensmd.service
solution
添加 pre-up
启动服务
auto ibp175s0
iface ibp175s0 inet static
pre-up systemctl start opensmd.service
address 10.1.13.1/24
mtu 2044
VXLAN¶
由于 InfiniBand 无法进行桥接,为了将网关虚拟机连接到同一广播域的集群中,我们在 ib 接口上创建了一个 VXLAN 接口,以便可以将其桥接到 vmbr8
上。
要添加 VXLAN 接口,我们需要将以下配置添加到 /etc/network/interfaces
文件中。
auto vxlan0
iface vxlan0
pre-up ip link add $IFACE type vxlan id 1 group 239.1.1.1 dev ibp175s0 || true
post-down ip link delete $IFACE || true
mtu 1500
然后将 vxlan0
添加到 vmbr8
的 bridge-ports
列表中,即:
- bridge-ports none
+ bridge-ports vxlan0
Mounting NFS over RDMA¶
nfs-kernel-server
的默认配置不会启用 RDMA,且 RDMA 连接无法使用和 TCP/UDP 相同的端口,所以我们将 2050 端口分配给 NFS over RDMA。
要启用 NFS over RDMA,我们需要更改 /etc/nfs.conf
并取消注释下面两行:
rdma=y
rdma-port=2050
在 NFS 客户端上,加载 xprtrdma
内核模块并把挂载选项 proto=rdma,port=2050
添加到 NFS 挂载点。
Error: could not insert 'rpcrdma': invalid argument
Just install the mlnx-nfsrdma-dkms
package. No reboot needed.
Routing service for other hosts¶
Legacy things, since we use VXLAN to provide internet for the cluster now.
See /etc/wireguard/wg0.conf
for details.
iptables
fails randomly
For unknown reasons, Proxmox VE switches back to iptables-legacy
randomly, which causes the routing service to fail. A temporary fix is to switch back to iptables-nft
and restart the service.
update-alternatives --set iptables /usr/sbin/iptables-nft
update-alternatives --set ip6tables /usr/sbin/ip6tables-nft
systemctl restart iptables
We've deployed a permanent fix
By inserting the update-alternatives
commands before the iptables service starts, we can ensure that the correct iptables is used.
[Service]
ExecStartPre=-/usr/bin/update-alternatives --set iptables /usr/sbin/iptables-nft
ExecStartPre=-/usr/bin/update-alternatives --set ip6tables /usr/sbin/ip6tables-nft
We also mask pve-firewall
to prevent it from interfering with our setup.
systemctl mask pve-firewall.service
Records¶
2024-03-24 SSD replacement¶
- Poweroff the server
- Insert the new Intel Optane 900p 208G, with its half-height bracket pre-installed
- Power on the server, but boot PXE instead. Select Arch Linux to get a shell
e2fsck -f /dev/pve/root
resize2fs -p /dev/pve/root 14G
lvreduce -L 16G pve/root
resize2fs -p /dev/pve/root
- Now reboot into the OS and prepare the new disk
fdisk /dev/nvme0n1
g
to create a new GPT partition tablen
, Enter, Enter,+100M
to create a 100M EFI partitiont
,uefi
to set the partition typen
, Enter, Enter, Enter to create a new partition with the rest of the spacet
, Enter,lvm
to set the partition type to LVMw
save and exit
- Configure the new EFI system partition:
mkfs.vfat /dev/nvme0n1p1
vim /etc/fstab
and change the UUID of/boot/efi
to the new oneumount /boot/efi
,mount /boot/efi
grub-install --target=x86_64-efi
to install GRUB
- Migrate the root partition to the new disk:
pvcreate /dev/nvme0n1p2
vgextend pve /dev/nvme0n1p2
pvmove /dev/sdb2 /dev/nvme0n1p2
- this one takes some time, but with SSD it should be fastvgreduce pve /dev/sdb2
- (Optional)
pvremove /dev/sdb2
- (Optional)
blkdiscard -f /dev/sdb
- Pull out the old disk from the server
- Insert the two 18 TB WD Gold disks
- Add them to the ZFS pool:
zpool add rpool mirror sda sdb