高渐离の屋

一个不起眼的个人小站

0%

从零开始搭建NAS——坑爹的TrueNAS

距离上一篇文章其实已经过了有一阵子了,本来预计是想要很快写出第二篇的,但是由于各种各样的原因就一直拖了下去。

嗯,没错,我其实是在测试NAS的稳定性,一定不是太懒的原因。截止到今天(2022-12-4),NAS已经连续运行53天了,在之前因为更新系统等原因不可避免重启了一两次,一直以来确实没出什么大问题。

还是相当稳定的

坑爹的TrueNAS Core

上次在文章末尾我提到说,我被TrueNAS Core狠狠地坑了一把。

TrueNAS是基于FreeBSD构建的操作系统,而作为皇城根下有通天纹的系统,自然是不屑于使用Docker的。FreeBSD自有jails系统。

FreeBSD jail,一种操作系统层虚拟化技术,在FreeBSD操作系统中运作。利用这个技术,FreeBSD的系统管理者,可以创造出几个小型的软件系统,这些软件系统被称为监狱(jails)

作为Docker的老前辈,平心而论,jails在2000年是具有非常划时代意义的新技术,而现有的容器技术例如LXC或者Docker,也或多或少收到了他的启发。然而今年是2022年,jails在当然的应用环境下已经显得力不从心。直接操作jails非常繁琐,因此TrueNAS提供了一个工具iocage,将jails操作简化成了类似docker的操作,还算方便。

网络坑

jails的网络基于BPF实现,作为eBPF的前身,jails可以提供3种网络模式:

  • DCHP。这个模式下的jail类似虚拟机,容器直接从DHCP服务获取IP地址,从网络拓扑上可以将jail视为独立设备。
  • 端口绑定。直接使用宿主机的网络端口,类似dockerhost模式,区别是前者只能使用一张网卡,而dockerhost可以使用所有网卡。
  • nat。类似Docker最常用的模式,使用端口转发。

乍一看好像没什么问题?直接模仿Docker无脑nat模式不就完了吗,该有的都有不是吗?让我们再来看看我需要部署的服务列表:

服务 功能 需要的端口 结果
Aria2 下载 6800 OK,下载不支持IPv6
FreeRadius Wifi 鉴权 1812 OK
Qbittorrent BT下载 51413 不支持IPv6
Emby 媒体服务器 不重要 不支持IPv6,不支持硬件加速

可以看到,在最重要的两个下载功能中,端口转发均明确表示不支持IPv6(本来V6设计就不是给你NAT的)。此外,由于每个jail都有自己的IP,众多服务也无法使用一个反向代理统一起来。

驱动坑

虽然我使用的是一块zen2的R5 4400G,在这个zen4的年代来看已经不新了。但是很遗憾,他的显卡对于FreeBSD来说还是太新了,新到只有在最新的FreeBSD 13.1才堪堪提供了支持。而很遗憾的是,TrueNAS Core的底层版本是13.0,并且直接在宿主系统上更新包是不受支持的。于是接下来我就开始了徒劳且痛苦的尝试。

首先是尝试更新内核版本,既然freebsd-update不能使用,那我就编译更新内核好了。下载好了内核源码之后,又突然发现宿主系统没有cc编译器。这也难不到我,创建一个新的jail,在里面安装编译器等工具,随后再将内核源代码挂载进去完成编译即可。

但是这么做的风险极高,首先是因为没有回滚的机会,TrueNAS Core的系统更新不能用了,此外自己编译内核也非常的灵。而事实上,当我编译完成新的内核后,虽然他识别出了我的GPU,但是运行vainfo依旧会报错,也不知道原因是什么。

另外由于TrueNAS Core和TrueNAS Scale共享一个名字,因此你能搜到的所有文档基本上都是TrueNAS Scale的,没文档的小众系统,我认为继续在上面投入是不值得的,早日弃暗投明吧。

迁移到SCALE

TrueNAS由于系统盘也使用了ZFS,因此可以非常轻松的再多个操作系统之间迁移,回滚等操作:
一个启动盘上可以有多个OS
只不过毕竟是从BSD迁移到Linux,配置文件还是有不兼容的部分,因此从Core迁移至Scale被定义为不可逆的过程。

更新过程也非常简单,和路由器刷机差不多。直接去网站的“手动下载”一项中找到.update文件下载,随后在NAS的手动更新中应用即可:
下载Update文件 手动更新

更新完后重启,再手动修改一些配置,就顺利变成Linux了!

SCALE

更新到了SCALE后,由于是熟悉的Linux,文档也众多于是接下来的流程非常的顺滑,顺利解决了我的问题。めでたしめでたし!

如果你以为是这样,那就太naive了。

K8S

世界上怎么会有这么好的事情呢。虽然TrueNAS SCALE确实用了Docker,但是又没完全用。别忘了人家名字里面有个scale,这个scale体现在哪里呢?没错,他给你整了个K8S,你可以用多个NAS组成一个K8S集群,实现动态扩容,负载均衡等等功能……

有病吧!ybb

虽然我每天都在用K8S(指自劫云),也喜欢搞起夜级的东西,但是这并不代表我要在家里面整个K8S啊!这东西我曾经尝试安装过,浪费了两天两夜最后还是没装好。kubectl那么多参数我从来就没整明白过。

不过幸好TrueNAS还是给你提供了一个GUI的,可以通过GUI管理容器的启停扩容。不过我只是简单的尝试了一下就把他抛弃了:
端口号不让低于9000
我的8443怎么办?
经过在网上的一通搜索,似乎不是只有我一个人遇到了这个问题:Containers: Minimum node port 9000?。但是很可惜,这个问题是K8S带来的,我没有任何办法修改:

According to the Jira ticket, and https://oteemo.com/2017/12/12/think-nodeport-kubernetes/, this isn’t a limitation with Scale, but with upstream Kubernetes k8s. Since the Scale applications deploy via Helm charts, they inherit the upstream k8s limits. However, I don’t see anything preventing you from running a container via Docker outside k8s.

那我就只能按照建议,直接起Docker容器咯。
另外由于部署了K8S环境,因此系统的虚拟网卡也被搞得一团乱麻,我们熟悉的docker0消失了,取而代之的是一大堆kube-bridge,kube-dummy-if,dummy0的网卡。直接用docker run命令起来的容器会直接没有网卡上不了网,但是我到此已经精疲力竭,没有心思去研究怎么把k8s的网卡挂载进入容器(多半也不支持),于是干脆直接--net=host了。

由于更新系统后这一大堆docker容器都会丢失,因此我又专门将启动的命令写到一个脚本里面,这样更新系统的时候可以快速恢复:

1
2
3
4
5
6
7
8
9
10
$ cat restore_docker.sh 
#!/bin/sh
# qbittorrent
docker run -d --restart=always --net=host --name qbittorrent -v /mnt/main/Docker/qbittorrent/config:/config -v /mnt/main/User/BT:/downloads -e SavePath=/downloads -e TempPath=/downloads -e HOME=/config -e WEBUI_PORT=3560 linuxserver/qbittorrent:latest
# nginx
docker run -d --restart=always --name nginx --net=host -v /mnt/main/Docker/nginx/nginx:/etc/nginx -v /mnt/main/Docker/nginx/www:/www -v /mnt/main/Docker/nginx/modules:/modules nginx:stable-alpine
# aria2
docker run -d --restart=always --name=aria2 --net=host -v /mnt/main/Docker/aria2/config:/config -v /mnt/main/User/Common\ Download:/downloads gaojianli2333/aria2
# freeradius
docker run -d --restart=always --net=host --name radius -v /mnt/main/Docker/freeradius/raddb:/opt/etc/raddb freeradius/freeradius-server:3.2.0-alpine

gaojianli2333/aria2容器是我自己打包的,Dockerfile如下:

1
2
3
4
5
FROM alpine:latest

RUN apk add --no-cache aria2

CMD ["aria2c","--conf=/config/aria2.conf"]

内存使用

在切换到Scale之后,NAS可用内存明显变少了,表现为图表中“Services“部分所占内存明显增多。也就是说,本就并不充裕(我没钱做到1T1G的内存配置)的ZFS专用内存更少了,而这有可能是Linux内核本身不如BSD精简的原因,也有可能是那个K8S的锅。

更加雪上加霜的是,不知道是不是OpenZFS 2.0的配置问题,系统默认只会使用12G的内存用作ZFS Cache,这和Core版本中空闲内存(也就是“Free”的部分)几乎为零形成了鲜明的对比。

为了解决这个问题,我还必须在Init Script中加上echo 30064771072 > /sys/module/zfs/parameters/zfs_arc_max这么一句来强迫ZFS使用尽可能多的内存。

总结

这样看来还真是可笑,不管是Core还是Scale,提供的容器系统最后都没有用上,最终还是回归到了手工管理Docker上。只是这样NAS系统提供的功能其实就只有ZFS和报警功能了,如果你不用ZFS或者你可以手操ZFS,那你完全可以用裸的Linux比如Ubunut或者Arch,不必硬凹NAS系统。Scale提供的K8S功能不能说完全没用,但是对于我的需求来说显然太过多余了,不过群晖等系统提供的Docker多半也有各种各样的问题(例如IPv6)。

硬件变化

另外在这几个月中,我的NAS也做了一些硬件上的改动。我的主板提供了一根PCIE X16的插槽,而这一插槽长期被X4的TL-NT521占用未免有点可惜。因此我将其替换成了一张X540-T2的FLR卡,并搭配拆分卡弄出了2个额外的M2。
拆分卡
这一套下来竟然只要200块,显得花400买全新TPLink的自己好像是个傻子,洋垃圾万岁!于是我又用卖掉TL-NT521换的钱添加了一张垃圾SSD,作为阵列的L2 ARC使用,目前来看整体命中率还是挺高的。
命中率
剩下那个槽位因为我本身内存不足,因此再添置缓存也没有多大意义,或许以后可以考虑插一个M2转SATA的卡,加点硬盘。

では、諸君は。