TrueNAS 维护实录二:服务三天两头地出事

阅前注意

TrueNAS 系列文章涉及可能影响生产数据的危险操作,仅供测试参考,切勿生搬硬套。

一年过去了,资料服务器(NAS)又发生了哪些令人哭笑不得的事情?跟着作为半桶水运维的我来看看。本次记录的有:

  • 因实际需求和使用体验改变,服务栈有了较大变动
  • 单独为 Jellyfin 容器指定 Hosts 解析表,以免除 TrueNAS 系统升级后需重新设置 Host 的不便;
  • 被判断“不靠谱”的 SATA SSD 清退,以 Optane 组成的条带池取而代之;
  • TrueNAS 最新分支破坏了整个监测栈

一、服务栈的变更

1.1 移除或改动的服务

  • Plex:影视管理服务。去年开始,Plex 联网服务不再可直连访问。尽管可改用特殊手段连接,但考虑到 Plex 在此仅有影视剧刮削之用,不涉及播放、转码等功能,我决定予以清退。
  • Tailscale:内网穿透服务,官方服务器自去年起无法直连。考虑到使用频率极低、实用性有限,现已清退。联想私有云正作为平行替代。
  • Syncthing:这款文件同步服务起初被设定用于手机照片和收藏来的插画的同步。但随着插画增多至两万余张,其同步速度慢的短板正越发地突出;加之手机屏幕小,欣赏体验不佳,我认为其价值已然有限。本月已清退,计划以大容量存储卡和二手平板取代。至于手机照片,由于旁边的联想私有云还在工作且可同步照片,故考虑挂载并反向拉取存有照片的目录。
  • One API/ChatGPT Web:提供大模型接口封装、再分发和在线聊天的服务。由于更便捷的使用方式已经出现(例如 Chatbox 客户端和本机运算 MoE 大模型等),这套方案显得冗余,遂清退。
  • Alist:对接各类网盘专有接口、挂载网盘的中间件。近期有传闻被某黑产公司收购并加入严重威胁用户隐私和信息安全的恶意代码;尽管一部分恶意代码未被并入主线,但不能确保 Docker 镜像等下游成品不受影响。目前社区的态度普遍转为不信任;115 网盘、阿里云盘等业已宣布停止对 Alist 开放接口。有鉴于此,本月已清退 Alist,目前正观望开源分支 OpenList 的进展,待其稳定后引进(目前已有 Docker 镜像成品)。
  • File Browser:文件管理器,原镜像 hurlenko/filebrowser 上游仓库维护已经放缓,且自版本 2.31.0 以后的成品出现了显著影响使用的问题。目前已改用活跃的分支 gtstef/filebrowserGitHub)作为基础——不过这个分支同样存在问题,例如复制名称带有中括号的目录/文件有几率失败、或目录名被削除一段等。

1.2 新增的服务

  • Peer Ban Helper :自动屏蔽恶意 BitTorrent 客户端的服务,我称之为“BT 特色防火墙”。有基于 IP/客户端规则表和进度检测的基础防护功能;用 GitHub 账户授权,可启用 BTN 网络和多种动态屏蔽功能。电信网络下实用性较强;广电网络下效用减弱,但也能屏蔽一些漏网之鱼。

1.3 撰稿为止的三方服务一览

🌟 表示基于 Alpine Linux 镜像构建。

服务类别Docker 镜像镜像标签
Portainer容器管理portainer/portainer-cealpine🌟
Watchtower容器管理containrrr/watchtowerlatest
InfluxDB基础设施influxdbalpine🌟
MariaDB基础设施mariadblts
Gitea开发/备份gitea/gitealatest🌟
Nextcloud备份linuxserver/nextcloudlatest🌟
Telegraf监测telegrafalpine🌟
Grafana监测grafana/grafana-osslatest🌟
File Browser文件管理gtstef/filebrowserlatest🌟
FreshRSS订阅管理freshrss/freshrssalpine🌟
Qbittorrent下载superng6/qbittorrenteelatest
Peer Ban Helper下载/防火墙ghostchu/peerbanhelper不定
官方不推荐 latest
Jellyfin影音管理nyanmisaka/jellyfinlatest

二、Jellyfin 和 Hosts 解析表

早前提到,Jellyfin 需要连接到 The Movie DB 来刮削影视剧;早年做法是编辑 TrueNAS 系统本身的 Hosts 解析表,再以和宿主共享网络(Host)的方式启动 Jellyfin;但在 TrueNAS 系统尚处于快速迭代状态、两到四周出一个版本的情况下,维护 Hosts 稍显繁琐。而通过 Portainer 指定 The Movie DB 接口对应的主机地址后,设定将得以保留。
只需依此教程,指定 api.themoviedb.org api.thetvdb.com image.tmdb.org 的主机地址即可。

三、Docker 存储目录迁移

上期引进的 Optane 固态盘性能比起堪称鸡肋的联想 SATA SSD 不知高到哪里去了。我决定将 Docker 镜像存储目录和容器永久化存储目录迁移到那里。但是 Optane 空间有限,由一对 Optane 组成的条带池最大仅有 25.65 GB;这意味着每个字节都要精打细算。为了腾笼换鸟可没少费工夫。这里分为三部分来讲。

3.1 残余 Swap 分区的清退

当我在命令行里键入 fdisk -l,我惊奇地发现,除系统盘以外,每块硬盘——包括 Optane——都划出了 2 GB 作为交换空间(Swap)。 这是最初安装 TrueNAS 23.10 时被强行安排的,后续版本虽禁用了 Swap 却从未移除之;这导致 Optane 硬盘有多达 16% 的空间被白白浪费!于是,解放这多达 4 GB 的空间用于存储成为了第一要务。
幸运的是,Optane 硬盘上仅含有 Docker 镜像、随容器附加的参数/变量和少量缓存,均易于恢复,故当即遵照 TrueNAS 社区帖子,对该存储池予以下线、清空数据、重新分区。记录单元大小设于 4KB(默认 128K),以确保性能并在小文件较多时节约空间。

3.2 清退无用镜像和容器数据

截至 6 月 14 日,Docker 镜像和容器存储目录分别占地近 7 GB 和将近 10 GB。于是不得不处置多余的东西了。

清退了一批镜像,记于第一节。容器永久化存储方面,聚焦于随 Nextcloud 同步的上古资料(如 2021 年以前创建的文档、录音等),各类日志文件,已清退容器的数据,等等。其中:

  • 旧文档:打包、归档并备份后删除。
  • 日志文件:发现 Alist 存储了超 1 GB 的日志文件,遂更改其设置。在网页界面里未能发现和日志相关的设置,只好编辑 config.json 的相关部分:
1
2
3
4
5
6
7
8
"log": {
"enable": true, //设为 false 不会自动清理日志
"name": "data\\log\\log.log",
"max_size": 10, //每份日志 10 MB
"max_backups": 5, //保留至多 5 份日志
"max_age": 7, //至多保存 7 日
"compress": false
},

另外发现容器存储目录的快照也是占用空间的好手:由于数据库持续更新,多 5 个快照就多 5 个版本,累积可达 2~3 GB。这些资料严格上说只有 Nextcloud 同步来的文件是需要备份的,但快照 + 备份有助于快速恢复,于是设定为保留两天的快照。

3.3 迁移容器数据、重启容器

用 Rsync 便已足够。

1
rsync -aq /mnt/SSD/docker/ /mnt/Cache/docker

由于镜像库被删除,这里需要重新拉取镜像、创建容器。容器数据都被保留,只要目录映射正确,服务马上恢复如初。当然,还要像上篇那样编辑 /etc/docker/daemon.json 方可拉取镜像:

1
2
3
4
5
6
7
8
{
"data-root": "/mnt/Cache/docker-bin",
"registry-mirrors": [
"https://docker.1ms.run",
"https://hub1.nat.tf",
"https://docker.1panel.live"
]
}

尔后还要不时看看 1panel 自己维护的监测面板来检验 Hub mirrors 可用性。

尽管 daemon.json 仍会随系统升级而消失 归档,三方服务也会停止,但 Docker 本身还在——或者说,被集成到 TrueNAS。恢复过程已简化为两步:

1
2
nano /etc/docker/daemon.json
systemctl enable --now docker

至于数据安全,只要有备份,就算是 RAID 0/条带池也能横行霸道。噢,是时候做离线备份了。

四、震惊!TrueNAS 竟做出了这件不写进文档的 Notable Changes

4.1 监测栈的破坏

TrueNAS 25.04 如期在今年四月上线。 这回“Scale”这个名分去掉了,改称“社区版/Community Edition”,而“Core”干脆打入冷宫。有没有发现本文到这里为止没再提到一次“TrueNAS Scale”?

我直至 6 月 28 日才引进了 25.04.1 版本。加入了快速去重,这很好;Linux 内核更新了,也很好;打开“报告”一栏和自建的 Grafana 一看,很多监测项目都不见了,比如:

  • 处理器占用率就只说占用多少,内核、用户层、I/O wait 等等全部消失。
  • 处理器温度探头变成了“四个”,实际只有两个;还多了个平均温度,拜托你给个“CPU Package”(封装温度)也好啊,取平均值有什么意义。
  • 类似地,内存只说空余多少,ARC、服务、缓冲区等等统统消失——只有首页仪表板还留着由 ARC、服务、空闲组成的饼状图。
  • “系统”一节仅仅给了个开机时间曲线图,毫无意义。活跃线程、中断数等等也不见了。
  • ZFS 一节只剩下个 ARC 用量,其它诸如 ARC 命中率等等一并消失。
  • 少数没有变动的包括 UPS、硬盘温度、平均负载等。

TrueNAS 社区里已有人复现这个问题并试图寻求帮助,但无人问津。
另外 Netdata UI 入口被移除了;这点倒是在文档里有注明,官方称“出于安全考虑,移除了 Netdata 入口”“请自行安装 Netdata App”。考虑到以上消失的项目在 Netdata 当中都有体现,可以认为这正是由 Netdata 提供的。为了恢复这些监测项目,只好另辟蹊径。

4.2 监测栈的重建:Telegraf 原生插件混合架构

经过一夜调研,我决定改用 Telegraf 原生插件来收集运行状况。 Telegraf 设置需要调整,Grafana 面板和查询语句也要大改;为此简单学习了 Flux 语言,不排除将来切换到受支持的 SQL 或 InfluxQL 语言、或顺势更换数据库引擎(如 TimescaleDB)的可能性。

下面是经调整后的 Telegraf 设置:

Telegraf.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[global_tags]
[agent]
interval = "5s"
round_interval = true
metric_batch_size = 1000
metric_buffer_limit = 10000
collection_jitter = "0s"
flush_interval = "10s"
flush_jitter = "0s"
precision = "1ms"
debug = false
quiet = false
logfile = ""
hostname = "truenas"
omit_hostname = false
[[outputs.influxdb_v2]]
urls = ["http://localhost:9100"]
bucket = "telegraf-native"
organization = "truenas"
token = "<influx_token>"
[[inputs.cpu]]
percpu = false
totalcpu = true
collect_cpu_time = false
report_active = false
core_tags = false
[[inputs.system]]
[[inputs.diskio]]
devices = ["sd[a-z]","nvme[0-9]n1","vd[a-z]"]
[[inputs.sensors]]
[[inputs.net]]
interfaces = ["eno*", "enp0s[0-1]", "lo"]
[[inputs.zfs]]
[[inputs.mem]]
[[inputs.processes]]
[[inputs.upsd]]
[[inputs.kernel]]
[[inputs.socket_listener]]
service_address = "tcp://:19040"
data_format = "graphite"
templates = ["os.host.measurement.type.field"]

监测模块详解:

  • inputs.cpu处理器负载,含每个线程和综合负载率。仅统计整体负载。
  • inputs.diskio硬盘吞吐量。读写量随时间累加,查询时可用 difference() 来计算和上次记录的差异。限定于物理直通的 SATA、NVMe 硬盘和虚拟硬盘;没有必要对各个分区单独监测,遂排除。
  • inputs.kernel内核性能监测,提供上下文切换(Context switches)、中断数等。
  • inputs.mem内存使用情况,等同于 /proc/meminfo
  • inputs.net网络吞吐情况,此处限定于物理接口和 lo(本机回流虚拟接口),排除了 Docker 等服务建立的虚拟接口。
  • inputs.processes系统进程监测
  • inputs.sensors处理器和 PCIe 设备温度反馈
  • inputs.socket_listener:接收来自 TrueNAS 导出器的遥测数据,目前仅限于硬盘温度。原因是,在容器内始终未能调用 smartctl,无论给予容器何等权限;只好退而求其次。
  • inputs.system系统平均负载和开机时间
  • inputs.upsdUPS 状态监测。依赖宿主端口,要求容器接入宿主网络。
  • inputs.zfsZFS 性能监测

TrueNAS 方面需要重新设置导出器,如下图所示:

导出器设置

将 Telegraf 接入宿主网络,接收宿主导出器和 upsd 服务接口的数据。这样,现有面板的数据来源基本上均有平行替代。

Grafana 方面仍沿用现成模板,但做了以下更改:

  • 重写了所有查询语句;
  • 加入了 UPS 电量指示;
  • 去除了饼状图、Swap 和 ARC:L2;
  • “活跃进程”改为“活跃线程”;
  • 现在处理器温度额外收集了封装温度(例如 package_id_0);
  • 现在“开机时间”仅取最近一项记录;
  • 现在“ARC 命中率”在查询语句层面计算(未来如改用 SQL,需考虑在面板层面计算);
  • 现在“硬盘 I/O 时间”仅返回总体的访问延迟;
  • 现在“硬盘 I/O”返回真实的断面 I/O 计数;
  • 现在“网络吞吐”返回以字节计(而非比特)的吞吐量。
  • 内存方面,直接给出 total arcstats_size free sreclaimable sunreclaim buffered 的曲线,并计算 services = used - arcstats_size;计算结果和 TrueNAS 控制台首页所示基本吻合。将除 total used 以外的曲线叠加,结果略为高于 total 但基本平行;未能发现可构成恒等于内存总量 total 之等式的项目组合。

Grafana 面板设置见此,可直接导入。考虑将来开设仓库。下面是展示效果:

Grafana 面板

就这样罢,下次更新大约会安排到明年。隔壁某维基还有一大堆议程等着处理……🤦‍♀️