root@ultra4:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
vda 253:0 0 10G 0 disk
├─vda1 253:1 0 1M 0 part
├─vda2 253:2 0 191M 0 part /boot/efi
├─vda3 253:3 0 763M 0 part /boot
└─vda4 253:4 0 9.1G 0 part
└─vda4_crypt 252:0 0 9G 0 crypt
└─vg-gen 252:1 0 9G 0 lvm /
vdb 253:16 0 200G 0 disk
└─vdb1 253:17 0 200G 0 part
我的vbd1现在是zfs数据集,可以把swap放在sdb1? 有什么建议
你提到的 sdb1 应该是指 lsblk 输出里的 vdb1(虚拟化环境下的第二块盘)。
要把 Swap 放到已经作为 ZFS 的 vdb1 上,技术上完全可行,但有一点非常重要的架构风险需要你知晓。
核心核心核心警告:内存死锁风险 (Memory Deadlock)
Linux 官方和 ZFS 社区不极其推荐将 Swap 放在 ZFS 之上。
为什么?
当系统内存耗尽(OOM)时,操作系统会尝试把内存数据写入 Swap。但 ZFS 是一个非常复杂的底层文件系统,它在写入数据时(计算校验和、管理 ARC 缓存、压缩等)自身也需要申请系统内存。
这就可能陷入一个死锁套娃:系统内存不足 → 触发 Swap → ZFS 写入 Swap 却需要申请内存 → 系统无内存可给 → 整个系统瞬间卡死挂起。
如果你评估了风险,或者系统本身内存很充裕(只是想挂个 Swap 兜底),请务必使用 Zvol(ZFS 卷) 来做 Swap,而绝对不要在 ZFS 数据集里直接建一个 swapfile。
以下是具体的实施步骤和优化建议:
方案一:在 ZFS 中创建 Zvol 作 Swap(不破坏现有 ZFS)
如果你的 vdb1 已经存了数据,无法重新分区,可以用这个方法。我们需要通过一系列严格的参数来压榨 ZFS 的内存开销,以降低死锁概率。
1. 获取你的 ZFS 存储池(Pool)名称
zpool list
假设你的 Pool 名字叫 mypool。
2. 创建一个精心优化过的 Zvol
运行以下命令(这里以创建 16GB 的 Swap 为例):
sudo zfs create -V 16G \
-b $(getconf PAGESIZE) \
-o compression=off \
-o logbias=throughput \
-o sync=always \
-o primarycache=metadata \
-o secondarycache=none \
-o com.sun:auto-snapshot=false \
mypool/swap
参数为什么这么配?
-b $(getconf PAGESIZE):强制块大小与系统内存页(通常是 4K)对齐。compression=off:关闭压缩,避免写 Swap 时消耗额外的 CPU 和内存。sync=always:强迫数据立即落盘,不留在内存缓存里。primarycache=metadata:最关键! 绝不让 ZFS 把 Swap 数据又缓存到自己的 ARC 内存里(那成了内存左手倒右手,毫无意义)。
3. 格式化为 Swap 分区
Zvol 创建后,会在 /dev/zvol/ 下生成一个块设备:
sudo mkswap -f /dev/zvol/mypool/swap
4. 写入 /etc/fstab 实现开机自启
打开 /etc/fstab:
sudo nano /etc/fstab
添加或修改为以下这行:
/dev/zvol/mypool/swap swap swap defaults 0 0
5. 启用并验证
sudo swapon /dev/zvol/mypool/swap
swapon --show
方案二:最完美的终极建议(重新分区)
如果你的 vdb1 目前是空的,或者里面的数据可以先备份出来,强烈建议把 vdb 彻底重新分区:
- 划分一个 16G - 32G 的裸分区(比如
vdb1),直接格式化为标准的 Linux Swap(不经过 ZFS)。 - 剩下的 180G 左右空间划分成另一个分区(比如
vdb2),用来给 ZFS 做存储池。
这样做的优势:Swap 读写直接走块设备驱动,绕过了 ZFS 复杂的内存管理,100% 免疫内存死锁风险,性能也是最高的。
修改swapfile位置的步骤:
修改 Linux 中的 Swap 文件路径并扩大容量,核心流程是先关闭旧 Swap → 创建并配置新 Swap → 修改 fstab 配置 → 开启新 Swap → 删除旧文件。
以下是详细的操作步骤(假设你要将新 Swap 文件存放在 /mnt/new_swapfile,且容量扩大到 8GB):
1. 关闭当前的 Swap 空间
首先,需要安全地关闭系统目前正在使用的旧 Swap 文件:
sudo swapoff /swapfile
2. 创建新的大容量 Swap 文件
使用 fallocate 或 dd 命令在目标路径创建新文件。这里以创建 8GB 容量为例:
- 推荐方法(速度极快):
sudo fallocate -l 8G /mnt/new_swapfile
- 备用方法(如果你的文件系统是 XFS 等不支持 fallocate 的老版本,可以使用 dd):
sudo dd if=/dev/zero of=/mnt/new_swapfile bs=1M count=8192
```
### 3. 设置正确的安全权限
Swap 文件必须严格限制权限,只允许 root 用户读写,否则系统会报错且存在安全隐患:
```bash
sudo chmod 600 /mnt/new_swapfile
4. 将文件格式化为 Swap 格式
把刚刚创建的大文件初始化为 Swap 分区格式:
sudo mkswap /mnt/new_swapfile
输出中会显示类似 Setting up swapspace version 1, size = 8 GiB... 的提示。
5. 修改 /etc/fstab 配置文件
编辑备份好后的 /etc/fstab 文件,让系统在开机时自动挂载新的 Swap 文件。
使用你习惯的文本编辑器打开它:
sudo nano /etc/fstab
找到原本的那一行:
/swapfile swap swap defaults 0 0
将其修改为新的路径(注意:只需改路径,后面的参数保持不变):
/mnt/new_swapfile swap swap defaults 0 0
保存并退出编辑器。
6. 启用新的 Swap 文件
sudo swapon /mnt/new_swapfile
7. 验证是否修改并扩大成功
运行以下命令检查当前的 Swap 状态和容量:
swapon --show
或者查看内存使用情况:
free -h
你应该能看到路径已经变成了 /mnt/new_swapfile,且总容量变成了 8GB 左右。
8. 清理旧的 Swap 文件
确认新 Swap 正常工作后,就可以把原本根目录下的旧文件删掉以释放硬盘空间了:
sudo rm /swapfile
避坑小提示:如果你的新路径存放在 Btrfs 文件系统上,直接创建 Swap 文件会复杂一些(需要创建独立子卷并禁用写时复制
chattr +C)。如果是常见的 Ext4 或 XFS 文件系统,直接按照上述步骤操作即可。