跳至內容

在 ZFS 上安裝 Arch Linux

出自 Arch Linux 中文维基

這篇文章詳細描述了將 Arch Linux 安裝在 ZFS 文件系統上所需的步驟。

注意:盲目地照搬這篇教程上的操作是行不通的。您有必要花時間了解作業系統的啟動過程以及創建存儲池和數據集的過程。下面是一些可能幫助到您的連結:

由於 ZFS 不是 Linux 的原生文件系統(例如:不包含在主線內核之內)且 Arch Linux 是一個滾動更新發行版,總有些時候外部倉庫內的對應一定內核版本的內核模塊軟體包版本會稍落後於 Arch 倉庫中的版本,這有時會導致 ZFS 模塊(或其 dkms 變種包)在最新版本的內核上無法編譯。如果您想要一直使用最新版本的內核的話,將 Arch 安裝在 ZFS 上可能並不是很理想。

可能的解決方案見 ZFS#安裝

安裝

[編輯 | 編輯原始碼]

要在 ZFS 上安裝 Arch Linux,您需要使用帶有 ZFS 內核模塊的安裝介質。您可以使用現有的 Arch Linux; 或者,如果您沒有現有的 Arch Linux 系統,您也可以使用啟用了「共享文件夾」的虛擬機軟體,如 VirtualBox 或 VMWare。

在自定義 archiso 安裝介質中嵌入 ZFS 模塊

[編輯 | 編輯原始碼]

要構建自定義的ISO, 安裝 archiso。依照 archiso#準備自定義配置文件 來準備一個自定義的配置文件(下文中以 archlive 為例)。

首先,編輯 軟體包列表 packages.x86_64 並在其中加入 linux-lts 內核與下列 ZFS 軟體包:

packages.x86_64
...
linux-lts
linux-lts-headers
libunwind
zfs-utils
zfs-dkms

請確保從列表中移除 linuxbroadcom-wl (後者會拉取 linux 包) 。

您還需要編輯 pacman.conf 並在其中加入:

...
[archzfs]
SigLevel = TrustAll Optional
Server = https://github.com/archzfs/archzfs/releases/download/experimental

您還需要編輯以下文件來將 vmlinuz-linuxinitramfs-linux.img 的條目改為 vmlinuz-linux-ltsinitramfs-linux-lts.img:

archlive/airootfs/etc/mkinitcpio.d/linux.preset
archlive/efiboot/loader/entries/01-archiso-linux.conf
archlive/efiboot/loader/entries/02-archiso-speech-linux.conf
archlive/syslinux/archiso_pxe-linux.cfg
archlive/syslinux/archiso_sys-linux.cfg
archlive/grub/loopback.cfg
archlive/grub/grub.cfg
警告:如果您未編輯這些文件,您的 ISO 將 無法 啟動。

接下來我們要創建 isobuildwork 兩個目錄來開始構建 ISO 鏡像:

# mkdir isobuild
# mkarchiso -v -r -w /tmp/archiso-tmp -o isobuild ~/archlive

You should now have an archlinux-YYYY.MM.DD.x86_64.iso in the archlive/isobuild directory.

Burn this file to your installation media of choice.

注意:
  • You may wish to recreate this media occasionally if the zpool status -v output shows, after an update, that the zpool needs to be updated to support newer features.
  • You should use the linux-lts and linux-lts-headers for the actual installation for best compatibility. You also should use the unofficial archzfs repository for binary packages for zfs-utils and zfs-dkms updates, not the AUR packages. If you do choose to use the AUR packages, there will be times when a new mainline and zen Linux kernel, do not support ZFS, and may break you system. Due to this, the linux-lts kernel is strongly recommended for the actual installation section.
警告:Do not redistribute these custom ISOs as they will violate the GPL and CDDL licenses!

Be sure to test your new ISO with a virtual machine and test the ISO. Simply run:

# modprobe zfs
# zpool status

If it fails, then your zfs module did not build correctly, and you will have to try again. To build a custom ISO, install archiso. Follow archiso#Prepare a custom profile to prepare a custom profile (named archlive in the following example).

First, edit the package list file packages.x86_64 to add the linux-lts kernel and the following ZFS packages:

packages.x86_64
...
linux-lts
linux-lts-headers
libunwind
zfs-utils
zfs-dkms

Make sure to remove linux and broadcom-wl (which would pull in the linux package) from the list.

You will also need to edit pacman.conf and append:

...
[archzfs]
SigLevel = TrustAll Optional
Server = https://github.com/archzfs/archzfs/releases/download/experimental

You will also need to edit the following files to change vmlinuz-linux and initramfs-linux.img entries to vmlinuz-linux-lts and initramfs-linux-lts.img:

archlive/airootfs/etc/mkinitcpio.d/linux.preset
archlive/efiboot/loader/entries/01-archiso-linux.conf
archlive/efiboot/loader/entries/02-archiso-speech-linux.conf
archlive/syslinux/archiso_pxe-linux.cfg
archlive/syslinux/archiso_sys-linux.cfg
archlive/grub/loopback.cfg
archlive/grub/grub.cfg
警告:If you fail to edit these entries your ISO will not boot.

Now we will make an isobuild and work pair of directories to start the build process:

# mkdir isobuild
# mkarchiso -v -r -w /tmp/archiso-tmp -o isobuild ~/archlive

You should now have an archlinux-YYYY.MM.DD.x86_64.iso in the archlive/isobuild directory.

Burn this file to your installation media of choice.

注意:
  • You may wish to recreate this media occasionally if the zpool status -v output shows, after an update, that the zpool needs to be updated to support newer features.
  • You should use the linux-lts and linux-lts-headers for the actual installation for best compatibility. You also should use the unofficial archzfs repository for binary packages for zfs-utils and zfs-dkms updates, not the AUR packages. If you do choose to use the AUR packages, there will be times when a new mainline and zen Linux kernel, do not support ZFS, and may break you system. Due to this, the linux-lts kernel is strongly recommended for the actual installation section.
警告:Do not redistribute these custom ISOs as they will violate the GPL and CDDL licenses!

Be sure to test your new ISO with a virtual machine and test the ISO. Simply run:

# modprobe zfs
# zpool status

If it fails, then your zfs module did not build correctly, and you will have to try again.

對目標磁碟驅動器進行分區

[編輯 | 編輯原始碼]

ZFS 支持 GUID 分區圖與主啟動記錄分區表。要決定使用哪種分區圖類型,請參考分區#選擇 GPT 還是 MBR

ZFS 會管理自己的分區,所以只需創建一個最簡單的分區類型即可。創建 ZFS 文件系統的分區類型應為類型 bf00 ,或「 Solaris 根目錄分區」。

分區類型

[編輯 | 編輯原始碼]

Although for some legacy machines you, in the past, with MBR based partitioning methods, could create a zfs bootable root partition, it is not recommended to use ZFS in this manner due usage of GPT partitioning differences. It is recommended to use a separate /boot partition to avoid issues with bootloaders and ensure best compatibility.

在 BIOS(或一台以 Legacy 模式啟動的)設備上使用 GUID 分區圖與 GRUB 啟動引導器的示例:

Part     Size   Type
----     ----   -------------------------
   1       2M   BIOS boot partition (ef02)
   2       1G   Linux Partition (8300)
   3     XXXG   Solaris Root (bf00)

You may also use this method of partitioning with Grub and rEFInd. This method is the most recommended by the author for best compatibility with all systems.

Part     Size   Type
----     ----   -------------------------
   1       1G   EFI System Partition (ef00)
   2     XXXG   Solaris Root (bf00)

You can choose to separate Linux swap partition, or using a zvol, see ZFS#Swap volume, as swap.

If you wish to create a traditional swap partition, see Partitioning#Example layouts.

格式化目標磁碟驅動器

[編輯 | 編輯原始碼]

如果您已為啟動引導分區以及非 ZFS 文件系統創建了合適的分區,那麼現在請將這些分區格式化。不要對剛創建的 Solaris 根分區以及您的 BIOS 啟動分區做任何操作。Solaris 根分區將由 ZFS 管理,而 BIOS 啟動分區則會由您的啟動引導器管理。

設置 ZFS 文件系統

[編輯 | 編輯原始碼]

首先,確認 ZFS 內核模塊已經被加載,

# modprobe zfs

創建根存儲池

[編輯 | 編輯原始碼]

創建存儲池並設置好數據集的默認選項。存儲池上新創建的任何數據集都會保留這個存儲池創建時使用 -O 設定的選項。默認選項在在 ZFS 上安裝 Debian Buster. 第二步: 磁碟格式化中有詳細說明。

注意:物理扇區大小為512位元組的磁碟驅動器應使用 -o ashift=9 參數,而物理扇區大小為4096位元組的磁碟驅動器應使用 -o ashift=12 參數。要獲得每個 SCSI/SATA 磁碟驅動器的物理扇區大小,可以運行 lsblk -S -o NAME,PHY-SEC。如果想查看所有設備的物理扇區大小,可從命令中刪去 -S。若使用 NVMe 驅動器,使用 nvme id-ns /dev/nvmeXnY -H | grep "LBA Format" 來獲取正在使用的邏輯塊地址。大部分 NVMe 驅動器使用512位元組的邏輯塊大小,見 OpenZFS: NVMe low level formatting 以將其大小改為4096位元組。
警告:應始終注意現代的大部分設備的物理扇區大小為4096位元組,但有些設備會將自己的物理扇區大小報告為512位元組,尤其是固態驅動器(SSD)。即使在報告扇區大小為512位元組、實際物理扇區大小為4096位元組的設備上選擇 ashift=9一定會導致嚴重的性能下降。在物理扇區大小為512位元組的設備上選擇 ashift=12 不會導致性能下降,但可能使磁碟可用容量減少。如果您不確定的話,對於現代設備,應使用 ashift=12,或者您可以搜索您設備對應的正確值。對於有關的討論,參見 OpenZFS issue #967 ;對設置較高的 ashift 值可能出現的問題,見 OpenZFS issue #2497
警告: In this next section, using a standard device name such /dev/nvme0n1p2 instead of /dev/disk/by-id/<device number> to create the zpool, may lead to import problems. If you want to learn your devices correct by-id prior to this section, run:

ls -lh /dev/disk/by-id/

and take note of the correct by-id value to use rather than the standard device naming scheme such as:

lrwxrwxrwx 1 root root 9 Aug 12 16:26 ata-ST3000DM001-9YN166_S1F0JKRR -> ../../sdc

# zpool create -f -o ashift=12         \
             -O acltype=posixacl       \
             -O relatime=on            \
             -O xattr=sa               \
             -O dnodesize=auto         \
             -O normalization=formD    \
             -O mountpoint=none        \
             -O canmount=off           \
             -O devices=off            \
             -R /mnt                   \
             zroot /dev/disk/by-id/id-to-partition-partx

壓縮與原生加密

[編輯 | 編輯原始碼]

以下命令創建的存儲池會在所有數據集上默認啟用壓縮與原生加密:

# zpool create -f -o ashift=12         \
             -O acltype=posixacl       \
             -O relatime=on            \
             -O xattr=sa               \
             -O dnodesize=auto         \
             -O normalization=formD    \
             -O mountpoint=none        \
             -O canmount=off           \
             -O devices=off            \
             -R /mnt                   \
             -O compression=lz4        \
             -O encryption=aes-256-gcm \
             -O keyformat=passphrase   \
             -O keylocation=prompt     \
             zroot /dev/disk/by-id/id-to-partition-partx

The options after -O control ZFS behavior. A detailed explanation of them can be found in the zfsprops(7) man page.

警告:
  • 使用 ZFS 時應始終使用設備的 by-id 名稱,否則導入存儲池時會發生錯誤。
  • 除使用 by-id 名稱外,也可以考慮使用 by-partuuid 或 by-uuid名稱,因為即使一個內置磁驅動器被移入USB移動硬碟盒,這些名稱的值也不會發生改變,反之亦然。(這僅當 ZFS 在磁碟上的某個分區中才有效,若 ZFS 占據整個磁碟則無效)

創建您的數據集

[編輯 | 編輯原始碼]

ZFS 使用數據集的概念來管理您的存儲,而非使用傳統的磁碟分區。與磁碟分區不同,數據集沒有固定的大小, 每個數據集也可以有各自不同的屬性,例如壓縮。普通的 ZFS 數據集由 ZFS 自動掛載,而傳統的數據集則需由 fstab 或 使用 mount 命令掛載。

ZFS 最實用的功能之一便是啟動環境。啟動環境使您可以創建系統的可引導快照,您也可以通過簡單地重啟到某啟動環境來將整個系統回滾到那個快照。這使得系統更新變得更加安全,對軟體開發與測試來講也十分有用。要使用如 beadm, zectlAUR (用於 systemd-boot), or zedenvAUR (用於 GRUB) 等的啟動環境管理器來管理啟動環境,您的數據集必須有正確的配置。其關鍵是將您存放數據的目錄 (如 /home) 與系統數據分別放在相互獨立的不同數據集中,且不要在存儲池根目錄中存放數據,因為放在存儲池根目錄的數據以後將不能被移動。

您總是至少應該為您的根目錄創建一個數據集,且多數情況下您也會想要把 /home 存放在一個單獨的數據集中。您也可以自行選擇是否要無視啟動環境而始終保留完整的日誌文件。如果您使用的某些軟體會在 /home 之外存放數據 (如資料庫伺服器),您應整理數據集的結構,使得這些軟體的數據目錄與根目錄數據集分離開來。

以下的示例命令會創建一個只分根目錄數據集與 /home 數據集的最基本可用於啟動環境使用的配置。數據集使用其所在的存儲池在創建時設定的默認選項。

# zfs create -o mountpoint=none zroot/data
# zfs create -o mountpoint=none zroot/ROOT
# zfs create -o mountpoint=/ -o canmount=noauto zroot/ROOT/default
# zfs create -o mountpoint=/home zroot/data/home

創建根目錄數據集時您也可以不指定掛載點,畢竟無論如何 GRUB 啟動引導器會將其掛載至 / 。這也使得您可以通過克隆舊版數據集並將其放入 GRUB 啟動菜單來直接從舊版的根目錄啟動。這種情況下,您可以使用以下命令來創建您的根目錄數據集:

# zfs create -o mountpoint=/roots/default zroot/ROOT/default

您可以將 /root 存儲在您的 zroot/data/home 數據集中。

# zfs create -o mountpoint=/root zroot/data/home/root

系統數據集

[編輯 | 編輯原始碼]

為系統目錄創建數據集時,使用canmount=off選項。

示例請參見 Debian-Buster-Root-on-ZFS#step-3-system-installation

注意:若要將如 zroot/var/log 的數據集掛載至 /var/log,應考慮使用 zfs-mount-generator 而非 zfs-mount.service。這會修復文件系統掛載順序,在 這裡 有詳細介紹。
 # zfs create -o mountpoint=/var -o canmount=off                 zroot/var
# zfs create                                                    zroot/var/log
# zfs create -o mountpoint=/var/log/journal -o acltype=posixacl zroot/var/log/journal
# zfs create -o mountpoint=/var/lib -o canmount=off             zroot/var/lib
# zfs create                                                    zroot/var/lib/libvirt
# zfs create                                                    zroot/var/lib/docker
注意:systemd-journald requires a mountpoint to be created otherwise systemd-journald.service will fail at boot systemd#systemd-tmpfiles-setup.service fails to start at boot

導出並導入您的存儲池

[編輯 | 編輯原始碼]

要驗證您的設置,將您所有的 ZFS 存儲池先導出後再重新導入。

警告:不要跳過這一步,否則您再導入存儲池時必須使用 -f 參數。這會使導入的存儲池卸載。
注意:如果您使用交換分區的話,這一步可能會失敗。您需要先使用 swapoff 命令將其關閉。
# zpool export zroot
# zpool import -d /dev/disk/by-id -R /mnt zroot -N
注意:-d 並不是設備的實際 ID,而是包含著軟連結的 /dev/by-id 目錄。

如果這個命令執行失敗並且您被要求使用數字 ID 來導入某個存儲池,運行 zpool import 來找到您存儲池的 ID,然後使用類似下方的命令導入存儲池:

# zpool import 9876543212345678910 (您的设备的 ID) -R /mnt zroot

如果您啟用了原生加密選項,先加載 ZFS 密鑰。

# zfs load-key zroot

由於根目錄數據集使用 canmount=noauto 參數,您需要先將其手動掛載,然後再掛載其他數據集。

# zfs mount zroot/ROOT/default
# zfs mount -a

現在 ZFS 文件系統已準備完畢以待使用。

配置根目錄文件系統

[編輯 | 編輯原始碼]

如果您使用了傳統類型的數據集,則您需要將其寫入 /etc/fstab

為根目錄所在的子文件系統設置 bootfs(啟動文件系統),以便啟動引導加載器找到作業系統。

# zpool set bootfs=zroot/ROOT/default zroot

如果您還沒有 /etc/zfs/zpool.cache,請手動創建:

# zpool set cachefile=/etc/zfs/zpool.cache zroot

切記要將 zpool.cache 文件放入您的新系統中。稍後 ZFS 守護進程啟動時需要這個文件。

# mkdir -p /mnt/etc/zfs
# cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache

安裝並配置 Arch Linux

[編輯 | 編輯原始碼]

按照安裝指南安裝系統。若有涉及 ZFSonLinux 所需的特殊操作,將會在此列出。

  • 首先使用 mount 命令掛載所有的傳統類型數據集以及非 ZFS 的引導或系統分區。
  • 安裝基本系統。
注意:You may wish to opt for linux-lts for your kernel of choice during the pacstrap portion. Make sure to also add libunwind to pacstrap to resolve a dependency for zfs-utilsAUR.
  • 安裝指南#生成 fstab 文件中所描述的方式對 ZFS 來說絕非必要。通常 ZFS 會自行掛載自己的分區,所以除非用戶使用了傳統型數據集,fstab 文件中不需要任何有關 ZFS 的部分。 要為文件系統生成 fstab,運行:
# genfstab -U -p /mnt >> /mnt/etc/fstab
# arch-chroot /mnt
  • 編輯 /etc/fstab
注意:
  • 如果您選擇為系統目錄創建傳統數據集,將其在 fstab 中保留。
  • 將除交換空間與 EFI 系統分區以外的所有非傳統型數據集注釋掉。可以使用較簡單的 /dev/zvol/zroot/swap 來取代交換空間的 UUID。
注意:For simplicity, and better compatibility, this guide only recommends using the zfs-dkmsAUR package for usage with linux-lts.
  • 創建初始 ramdisk 前,先編輯 /etc/mkinitcpio.conf,並將 zfs 加至 MODULES:
MODULES=(zfs)

接下來在 HOOKS 中將 zfs 加至 filesystems 前。同時也應把 keyboard hook 移動至 zfs 前,這樣如果出現問題,您仍可在終端中輸入。若您不使用 Ext3 或 Ext4,您也可以移除 fsck。您的 HOOKS 一行看起來應類似如下示例:

HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block zfs filesystems)
警告:Recent installations of Arch Linux uses a systemd initramfs. The ZFS hook provided by zfs-utilsAUR is only compatible with busybox-based initramfs images. Unless you plan to use a different ZFS hook compatible with systemd-based initramfs images, please make sure that you are using a busybox-based initramfs by putting base udev at the beginning of the HOOKS array instead of systemd.

安裝並配置啟動引導加載器

[編輯 | 編輯原始碼]
  • Add ZFS to your kernel command line

You can now set up your boot loader. You also need to add a kernel parameter to make ZFS bootable:

root=ZFS=zroot/ROOT/default rw

配置 systemd ZFS 掛載

[編輯 | 編輯原始碼]

要確保您的系統能夠正常地重新啟動,您需要啟用 zfs.target 以便自動掛載存儲池與生成 hostid。

注意:
  • 這一節內容的前提是假設您仍在 arch-chroot 環境中。
  • Usage of zpool.cache is still required by zfs-utils to achieve a bootable system, although zpool.cache has been considered a candidate for deprecation [See: https://github.com/openzfs/zfs/issues/1035], however at this time, it is still the default and recommended method to achieving a bootable system.

分別為每個您想要自動掛載的存儲池執行:

# zpool set cachefile=/etc/zfs/zpool.cache pool(存储池名)

啟用 zfs.target

要在系統啟動時自動掛載 ZFS 存儲池,您需要啟用 zfs-import-cache.servicezfs-mount.servicezfs-import.target

當根目錄文件系統為 ZFS 時,掛載根文件系統的過程中設備的 hostid 將不可用。對此有兩個解決方案。 您可以將您的 spl hostid 寫入啟動引導器的啟動內核參數中。例如向內核參數中加入 spl.spl_hostid=0x00bab10c。要獲取您的 hostid 數字,運行 hostid 命令。

另一個(建議的)解決方案是在 /etc/hostid 內寫入一個 hostid ,然後重新生成 initramfs,這個過程中您的 hostid 將會被複製到 initramfs 映像中。要安全寫入 hostid 文件,您需要運行 zgenhostid 命令。

要使用 libc 生成的 hostid(建議的操作):

# zgenhostid $(hostid)

要使用自定義的 hostid,運行以下命令。注意,hostid 必須是8個字符的十六進制數字。

# zgenhostid deadbeef

要讓 zgenhostid 工具生成一個 hostid :

# zgenhostid

完成後別忘了重新生成 initramfs

卸載文件系統並重新啟動

[編輯 | 編輯原始碼]

我們離成功不遠了!如果您使用傳統類型的啟動引導分區,先運行:

# umount /mnt/boot 

如果未使用傳統的單獨引導分區,應直接運行:

# zfs umount -a
# zfs umount zroot/ROOT/default
# zpool export zroot

現在,重新啟動系統。

警告:如果您沒有正確將存儲池導出,重新啟動後 ZFS 將拒絕在 ramdisk 環境中導入存儲池,從而使您卡在 busybox 終端界面。

從 USB 存儲設備加載密鑰

[編輯 | 編輯原始碼]

可以將密鑰存儲在 USB 存儲設備上並在啟動時加載:

在 USB 存儲介質的初始字節處存儲密鑰:

# dd if=your_password_file (您的密钥文件) bs=32 count=1 of=/dev/disk/by-id/usb_stick (USB 存储设备)

要創建 ZFS 分區,您可以使用上文所述的輸入密鑰的方式,或直接使用 dd 命令配合管道寫入 USB 存儲設備中存儲的密鑰:

# dd if=/dev/disk/by-id/usb_stick bs=32 count=1 | zfs create -o encryption=on -o keyformat=passphrase zroot/ROOT

下一步就要更改 zfs hook。zfs 默認會詢問密鑰。您需要將獲取密鑰的方式改為通過從您存放著密鑰的 USB 設備中 dd 來獲取。要達成這個目的,將 /usr/lib/initcpio/hooks/zfs 中的以下行:

# ! eval zfs load-key "${encryptionroot}"; do

改為:

# ! eval dd if=/dev/disk/by-id/usb_stick bs=32 count=1 | zfs load-key "${encryptionroot}"; do

您剛剛更改了您的 zfs hook,所以不要忘記重新生成 initramfs。現在 zfs 應該能在啟動時從您的 USB 設備中加載密鑰。

故障排除

[編輯 | 編輯原始碼]

系統因 "無法導入 zroot :存儲池不存在(cannot import zroot: no such pool available)" 而無法啟動

[編輯 | 編輯原始碼]

您可以嘗試以下步驟,看看是否有幫助。

  • 使用 archzfs 倉庫中提供的內核模塊,不要使用 dkms 版本。您可以在成功啟動後再改為使用 dkms 變種。
  • 移除 /etc/zfs/zpool.cache 並運行:
# zpool set cachefile=none zroot

Zpool refuses to export saying it's busy

[編輯 | 編輯原始碼]

Arch-chroot will mount specific kernelspace file systems in the system. If these are not unmounted, the zpool may refuse to dismount properly. If this happens, remount the ZFS partition and run findmnt -R /mnt

Then run umount -f /path/to/partition against the partition still mounted.

This should allow the zpool to export.

另請參閱

[編輯 | 編輯原始碼]