X86移动云ZFS

在我使用的 Apple ARM架构芯片M1 Pro MacBook Pro,我期望构建完全虚拟化的多服务器集群架构。对于底层存储,希望在一个 卷管理 上构建出存储给虚拟机使用。

有两种候选文件系统:

经过实践探索( 使用zfs-dkms在arch linux(ARM)编译安装ZFS ), Asahi Linux 内核激进采用v6.1,尚未得到 OpenZFS 支持,所以

存储构想

我考虑采用 ZFS 来构建物理主机的文件系统原因:

准备工作

磁盘分区

按照 ZFS管理准备 完成文件系统分区:

X86移动云ZFS磁盘parted划分分区: 所有剩余磁盘空间全部作为 zpool-data 分区
parted -a optimal /dev/nvme0n1 mkpart primary 64GB 1024GB
parted /dev/nvme0n1 name 3 zpool-data

完成后检查 parted /dev/nvme0n1 print 可以看到新增加的第3个分区:

X86移动云ZFS磁盘parted划分分区: 新建的第3个分区作为zpool
Model: SAMSUNG MZVL21T0HCLR-00B00 (nvme)
Disk /dev/nvme0n1: 1024GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name     Flags
 1      1049kB  256MB   255MB   fat32        ESP      boot, esp
 2      256MB   64.0GB  63.7GB  xfs          primary
 3      64.0GB  1024GB  960GB                primary

Docker准备

停止Docker服务,为存储驱动修改做准备
sudo systemctl stop docker
sudo systemctl stop docker.socket
  • /var/lib/docker 备份并清理该目录下所有内容:

备份/var/lib/docker目录
sudo cp -au /var/lib/docker /var/lib/docker.bk
sudo rm -rf /var/lib/docker

安装ZFS

受限于ZFS的CDDL license,需要额外的工作来完成 ZFS安装 。之前在 ARM移动云计算构建 中我采用 使用zfs-dkms在arch linux(ARM)编译安装ZFS ;而现在在 X86移动云计算构建 系统中,由于 archzfs repo 提供 x86_64 安装包,所以参考 OpenZFS Getting Started: Arch Linux 使用软件仓库安装。

使用 archzfs repo 安装

  • 导入 archzfs 仓库key:

导入 archzfs 软件仓库密钥
curl -L https://archzfs.com/archzfs.gpg |  pacman-key -a -
pacman-key --lsign-key $(curl -L https://git.io/JsfVS)
curl -L https://git.io/Jsfw2 > /etc/pacman.d/mirrorlist-archzfs
  • 添加 archzfs 软件仓库,并更新 Pacman 仓库:

添加 archzfs 软件仓库
tee -a /etc/pacman.conf <<- 'EOF'

#[archzfs-testing]
#Include = /etc/pacman.d/mirrorlist-archzfs

[archzfs]
Include = /etc/pacman.d/mirrorlist-archzfs
EOF

# 更新pacman仓库
pacman -Sy
  • archzfs 软件仓库提供了多种安装包组合,执行安装:

安装 archzfs 提供多种安装包组合,选择 zfs-linux 是面向Arch Linux默认内核和最新OpenZFS稳定版本
# pacman -S zfs
:: There are 16 providers available for zfs:
:: Repository archzfs
   1) zfs-archiso-linux  2) zfs-dkms  3) zfs-dkms-git  4) zfs-dkms-rc  5) zfs-linux  6) zfs-linux-git  7) zfs-linux-hardened  8) zfs-linux-hardened-git
   9) zfs-linux-lts  10) zfs-linux-lts-git  11) zfs-linux-lts-rc  12) zfs-linux-rc  13) zfs-linux-vfio  14) zfs-linux-vfio-git  15) zfs-linux-zen
   16) zfs-linux-zen-git

Enter a number (default=1): 5
resolving dependencies...
looking for conflicting packages...

Packages (2) zfs-utils-2.1.7-1  zfs-linux-2.1.7_6.1.6.arch1.1-1

Total Download Size:   30.47 MiB
Total Installed Size:  41.92 MiB

:: Proceed with installation? [Y/n]

我选择 5 ( zfs-linux )安装

配置ZFS

  • 在分区 /dev/nvme0n1p 构建 zpool ( 名为 zpool-data )并挂载到 /var/lib/docker/ 目录(开启 ZFS压缩 ):

zpool create创建名为zpool-data存储池,挂载到/var/lib/docker
# 在NVMe 分区3创建zpool,命名为zpool-data
sudo zpool create -f zpool-data -m /var/lib/docker /dev/nvme0n1p3

# 存储池开启压缩,2015年后openzfs默认压缩算法LZ4,这里明确设置lz4
sudo zfs set compression=lz4 zpool-data
  • 此时检查zfs存储可以看到上述名为 zpool-data 的存储池:

zfs list检查存储
sudo zfs list

输出显示如下:

zfs list检查存储显示zpool-data
NAME         USED  AVAIL     REFER  MOUNTPOINT
zpool-data   140K   860G       24K  /var/lib/docker

此时zfs卷已经挂载,使用 df -h 可以看到:

Filesystem      Size  Used Avail Use% Mounted on
...
zpool-data      861G  128K  861G   1% /var/lib/docker
  • 修改 /etc/docker/daemon.json 添加zfs配置项(如果该配置文件不存在则创建并添加如下内容):

/etc/docker/daemon.json 添加ZFS存储引擎配置
{
  "storage-driver": "zfs"
}
  • 启动Docker并检查Docker配置:

启动Docker并检查 docker info
sudo systemctl start docker
sudo docker info

docker info 输出显示如下:

docker info显示使用了ZFS存储(启用压缩)
Client:
 Context:    default
 Debug Mode: false

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 20.10.22
 Storage Driver: zfs
  Zpool: zpool-data
  Zpool Health: ONLINE
  Parent Dataset: zpool-data
  Space Used By Parent: 163328
  Space Available: 923954676224
  Parent Quota: no
  Compression: lz4
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc io.containerd.runc.v2 io.containerd.runtime.v1.linux
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 9ba4b250366a5ddde94bb7c9d1def331423aa323.m
 runc version:
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
  cgroupns
 Kernel Version: 6.1.6-arch1-1
 Operating System: Arch Linux
 OSType: linux
 Architecture: x86_64
 CPUs: 8
 Total Memory: 15.54GiB
 Name: xcloud
 ID: IUMZ:2YIT:GWWW:7W73:OKSF:Q6OD:JXWN:NWZ5:IFBG:OKGY:YEIV:RL7V
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

配置ZFS自动启动

对于 Docker ZFS 存储驱动 需要通过 配置ZFS自动启动 确保操作系统启动时自动import zpool。并且由于 /var/lib/docker/var 子目录,还必须采用 zfs-import-cache + zfs-mount-generator :

  • 针对 zpool-data zpool存储池,采用 zfs-mount-generator 自动启动ZFS:

使用zfs-mount-generator自动启动ZFS: zpool-data 存储池
ZPOOL=zpool-data

mkdir /etc/zfs/zfs-list.cache

systemctl enable zfs-import-cache
systemctl disable zfs-mount

systemctl enable zfs.target
systemctl enable zfs-zed.service
systemctl start zfs-zed.service

touch /etc/zfs/zfs-list.cache/${ZPOOL}

# 触发 /etc/zfs/zfs-list.cache/${ZPOOL} 更新
zfs set canmount=off zpool/${ZPOOL}
zfs set canmount=on zpool/${ZPOOL}

/home迁移到ZFS

采用 ZFS快速起步 构建存储目录并将/home迁移到ZFS

  • root 身份登陆,并确保 /home 目录没有用户访问,将 /home 目录重命名:

将/home目录重命名(备份)
mv /home /home.bak
  • 由于 zpool-data 存储池已构建,所以直接创建卷 home ,并且创建 home 卷下面的子(用户目录):

创建 zpool-data 存储池的 home 卷
#zfs create zpool-data/home
#zfs set mountpoint=/home zpool-data/home

# 采用一条命令创建挂载好目录的ZFS卷
zfs create -o mountpoint=/home zpool-data/home

# 为每个用户创建独立的子卷,对于ZFS来说会自动形成层次结构的目录挂载
zfs create zpool-data/home/huatai
  • 恢复 /home/huatai 目录数据:

恢复/home/huatai目录数据
chown huatai:staff /home/huatai
chmod 700 /home/huatai
su - huatai

(cd /home.bak/huatai && tar cf - .)|(cd /home/huatai && tar xf -)

下一步