Proxmox VE 7あたりでインストーラでパーティションを切ってZFSルート構成が作れるようになった。したがって本記事のような面倒な手段を取る必要はなくなった。
また、/etc/kernel/pve-efiboot-uuidsは/etc/kernel/proxmox-boot-uuidsに変わったようだ。
Proxmox VEをZFSルートシステムでインストールすると、EFIシステムパーティションなどを除いたディスクの全領域が、Proxmox VE用のプールrpoolとなってしまう。
諸々の事情により、うちの環境ではパーティションを切ってrpoolと他のZFSプールを1つのストレージ上に共存させたい。UEFIとZFSの組み合わせとなれば、臆するなかれ、FreeBSDで培ったスキルを活かしてPVEの全領域プールからパーティションプールへの移行ができるんじゃね?と考え試してみた記録。
好きな構成でDebianインストールしてからProxmox VEの環境入れればいいだって?うっせー、俺はLinuxわかんねーんだよ!
共存ストレージ作成にあたり、まずは占有ストレージのパーティションを確認する。
# fdisk -l /dev/sda Disk /dev/sdh: 357.6 GiB, 384000000000 bytes, 750000000 sectors Disk model: INTEL SSDSC2BA40 Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes Disklabel type: gpt Disk identifier: FDCAC366-6C27-4210-8305-0C33EE989D55 Device Start End Sectors Size Type /dev/sda1 34 2047 2014 1007K BIOS boot /dev/sda2 2048 1050623 1048576 512M EFI System /dev/sda3 1050624 749999966 748949343 357.1G Solaris /usr & Apple ZFS Partition 1 does not start on physical sector boundary.
# zfs list rpool NAME USED AVAIL REFER MOUNTPOINT rpool 12.1G 333G 104K /rpool
4kセクタガン無視してパーティション切られててファッキューリーナスと思うが、それはさておき。
うちの環境ではBIOSブートはもう使わないので、BIOS bootは要らない。VMの仮想ディスクは専用プール(zimg)に確保するつもりなので、PVEのシステムプール(rpool)も最小限の容量とする。他に当方環境の諸々の事情を考慮し、共存ストレージは以下のパーティション構成とした。とりあえず、ESPとrpool用のパーティションがあればOK。
| 種類 | 容量 | 用途 |
|---|---|---|
| FAT32 | 512MiB | EFIシステムパーティション |
| ZFS | 100GiB | FreeBSDシステム (zroot) |
| ZFS | 1434GiB | VM用データ置き場 (zimg) |
| ZFS | 50GiB | PVEシステム (rpool) |
| - | 250GiB | 予備領域 |
共存ストレージにパーティションを作成する。
GPTを作る
# fdisk /dev/nvme2n1 Welcome to fdisk (util-linux 2.33.1). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Device does not contain a recognized partition table. Created a new DOS disklabel with disk identifier 0x5133f831. Command (m for help): g Created a new GPT disklabel (GUID: CEAAD3D1-5B58-524F-8E0D-26F1F3B2A24A).
nコマンドでパーティションを切って…
Command (m for help): n
Partition number (1-128, default 1):
First sector (256-468843600, default 256):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (256-468843600, default 468843600): +512M
Created a new partition 1 of type 'Linux filesystem' and of size 512 MiB.
tコマンドでパーティションの種類を変える
Command (m for help): t Partition number (1-4, default 4): 1 Partition type (type L to list all types): 1 Changed type of partition 'Linux filesystem' to 'EFI System'.
最終的に以下のようになる。ZFSを使う上でパーティションタイプは重要ではないが、後から見てもわかるように設定しておくのが無難。
Command (m for help): p Disk /dev/nvme2n1: 1.8 TiB, 1920383410176 bytes, 468843606 sectors Disk model: SAMSUNG MZQLW1T9HMJP-00003 Units: sectors of 1 * 4096 = 4096 bytes Sector size (logical/physical): 4096 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes Disklabel type: gpt Disk identifier: CEAAD3D1-5B58-524F-8E0D-26F1F3B2A24A Device Start End Sectors Size Type /dev/nvme0n1p1 256 131327 131072 512M EFI System /dev/nvme0n1p2 131328 26345727 26214400 100G FreeBSD ZFS /dev/nvme0n1p3 26345728 402260223 375914496 1.4T Solaris /usr & Apple ZFS /dev/nvme0n1p4 402260224 415367423 13107200 50G Solaris /usr & Apple ZFS
最後にwで書き込む。
Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Syncing disks.
作成したESPをFAT32でフォーマットする。
# mkdosfs -F 32 -S 4096 -s 1 -v -n EFI /dev/nvme1n1p1 mkfs.fat 4.1 (2017-01-24) /dev/nvme2n1p1 has 64 heads and 32 sectors per track, hidden sectors 0x0800; logical sector size is 4096, using 0xf8 media descriptor, with 131072 sectors; drive number 0x80; filesystem has 2 32-bit FATs and 1 sector per cluster. FAT size is 128 sectors, and provides 130784 clusters. There are 32 reserved sectors. Volume ID is 517202a5, volume label EFI
既存ESPと新規ESPをマウントし、中身をコピーする。
# mkdir /mnt/esp /mnt/newesp # mount /dev/sda2 /mnt/esp # mount /dev/nvme1n1p1 /mnt/newesp # cp -Rpv /mnt/esp/. /mnt/newesp/
今回はパーティションサイズが完全に一緒だったので、ddで丸コピーでもよかったかもしれない。
忘れずにアンマウント。
# umount /mnt/esp # umount /mnt/newesp
PVEのシステムデータのコピー方法は、ZFSのミラーリングを使う方法、send/recvを使う方法の2種類がある。
ZFSのミラーリングを使う方法。
現在のrpoolに共存ストレージのnvme0n1p4をミラーとして追加し、同期完了後に占有ストレージのパーティションをミラーから切り離す。
簡単かつ安全な方法だが、今回は移行先のパーティションの方が小さいので使えない。残念。参考までに実行するコマンドは以下のようになる。なお、デバイス追加時にaddを使うとストライピングとして追加され、取り外し出来なくなるので注意!!
■ミラーの追加 # zpool attach rpool ata-INTEL_SSDSC2BA400G3_xxx-part3 nvme-SAMSUNG_MZQLW1T9HMJP-00003_yyyy-part4 ■ミラーの取り外し # zpool detach rpool ata-INTEL_SSDSC2BA400G3_xxx-part3
ZFSのデータバックアップ・復元機能であるzfs send/recvを使う方法。正攻法と言えば正攻法。
使用中のデータ分のやり取りしか行わないので、小さなプールへのデータ移行が可能である。
移行にあたって、移行元プールのプロパティを確認しておく。
SOURCEがlocalとなっているプロパティが、そのプールとデータセットで独自に設定されたものなので、それらも移行先に移植する必要がある。
# zpool get all rpool | grep local rpool bootfs rpool/ROOT/pve-1 local rpool ashift 12 local (feature flagsは無視してOK) # zfs get all rpool | grep local rpool compression on local rpool atime off local rpool sync standard local
上記のプロパティを踏まえて共存ストレージに移行先プールrpool2を作る。
# zpool create -o ashift=12 rpool2 /dev/disk/by-id/nvme-SAMSUNG_MZQLW1T9HMJP-00003_yyy-part4
ここからはProxmox VEのインストーラのシェルで作業する。インストーラをDebug Modeで起動し、1度目のシェルはそのままexitし、2度目のシェルに入る。
移行元と移行先プールのマウントポイントを作り、それぞれマウントする。-RでZFSの代替ルート指定を忘れずに行うこと。
# mkdir /run/rpool /run/rpool2 # zpool import -fR /run/rpool rpool # zpool import -fR /run/rpool2 rpool2
移行元にスナップショットを作成。
# zfs snapshot -r rpool@backup
zfs send/recvでデータのコピーを行うが、まずはrecvに-nオプションを付けて、意図通りの場所に復元できるか確認する。-Fで上書き指定するので、間違うと結構悲惨なんだぜ。
# zfs send -RLce rpool@backup | zfs recv -Fduvn rpool2
問題なさそうなら、-nを外して本番実行。
# zfs send -RLce rpool@backup | zfs recv -Fduv rpool2
念のため移行先のrpool2の中身を見てみる。
# zfs list -r rpool2
共存ストレージのrpool2を新生rpoolに名称変更する。
その前に、専用ストレージのrpoolが残ったままなので、こちらはrpool_origとでもしておく。
まずは両プールを一旦アンマウント。 </code> # zpool export rpool # zpool export rpool2 </code>
rpoolをrpool_origに名前を変えてマウント。
# zpool -R /mnt/rpool rpool rpool_orig
同じく、rpool2をrpoolに名前を変えてマウント。 </code> # zpool -R /mnt/rpool2 rpool2 rpool </code>
共存ストレージのrpoolのbootfsが空のままなので、以前のrpoolの値を移植する。
# zpool set bootfs=rpool/ROOT/pve-1 rpool
最後に両プールをアンマウントする。
# zpool export rpool_orig # zpool export rpool
あとはマシンを再起動し、ブートドライブとして共存ストレージの方を選べば、以前の環境はそのままに新しいrpoolの方からProxmox VEが起動するハズ。
シェルでzfs listすると、新しいrpoolになっていることが分かる。
# zfs list -r rpool NAME USED AVAIL REFER MOUNTPOINT rpool 15.3G 32.7G 104K /rpool rpool/ROOT 15.3G 32.7G 96K /rpool/ROOT rpool/ROOT/pve-1 15.3G 32.7G 15.3G / rpool/data 96K 32.7G 96K /rpool/data
zfs send/recvの時に作ったスナップショットrpool@backupも新生rpoolにできているので、忘れずに消す。
# zfs destroy -r rpool@backup
PVEがESPの同期の時に使うUUIDの設定を変更する。変えなくてもPVE自体は動くが、update-initramfsなどをした時にESPが更新されなくなる。
blkidコマンドでパーティションのUUIDを表示する。
# blkid /dev/nvme0n1p1: LABEL_FATBOOT="EFI" LABEL="EFI" UUID="5172-02A5" TYPE="vfat" PARTUUID="381a481f-926d-834a-b607-ab8c7f30d141" /dev/nvme0n1p2: LABEL="zroot" UUID="14384939844916901067" UUID_SUB="4240071790088313073" TYPE="zfs_member" PARTUUID="618094f1-c1c8-0b4e-b685-06d67f86a449" (略) /dev/nvme0n1: PTUUID="9248b857-8f10-ca4b-a0c0-3ea559112855" PTTYPE="gpt" /dev/nvme1n1: PTUUID="fe718aa7-f8d0-c149-88db-55afb4dbe75a" PTTYPE="gpt" /dev/mapper/fbsd_disk0: PTTYPE="PMBR" /dev/mapper/fbsd_disk1: PTTYPE="PMBR"
こんな感じでずらずらと表示される。
必要なのは、対象のESPのパーティションのUUIDである。うちの環境ではnvme0n1p1なので 5172-02A5 となる。
/etc/kernel/pve-efiboot-uuidsに入っている以前のUUIDを、この値で置き換える。
ESPが複数ある場合、PVEに対応するESPを特定するには以下の手順に従う。
efibootmgr -vでUEFIの起動マネージャーの情報を表示する。
# efibootmgr -v BootCurrent: 0004 Timeout: 1 seconds BootOrder: 0004,0005,0006,0007,0008,0009,0003,0001 Boot0001 Hard Drive BBS(HD,,0x0)/VenHw(5ce8128b-2cec-40f0-8372-80640e3dc858,0200)..GO..NO..........S.T.1.8.0.0.0.N.M.0.0.0.J.-.2.T.V.1.0.3................... (中略) Boot0003* UEFI: Built-in EFI Shell VenMedia(5023b95c-db26-429b-a648-bd47664c8012)..BO Boot0004* UEFI OS HD(1,GPT,e4a89f28-6e8a-ea41-97bb-c0ae7e3e806b,0x100,0x20000)/File(\EFI\BOOT\BOOTX64.EFI)..BO Boot0005* UEFI OS HD(1,GPT,568e7df6-4e12-ce43-9ec9-c29aa5ee3440,0x100,0x20000)/File(\EFI\BOOT\BOOTX64.EFI)..BO Boot0006* (B196/D0/F0) UEFI PXE: IPv4 Intel(R) I210 Gigabit Network Connection(MAC:ac1f6be5bee2) PciRoot(0x3)/Pci(0x3,0x4)/Pci(0x0,0x0)/MAC(ac1f6be5bee2,0)/IPv4(0.0.0.00.0.0.0,0,0)..BO (後略)
BootCurrentが起動で使われたブートエントリの番号で、後続のBoot0000がブートエントリの詳細を表す。
上記ログから、Boot0004のパーティションUUIDがe4a89f28-6e8a-ea41-97bb-c0ae7e3e806bと分かる。
次に、blkidからパーティションUUIDに該当するファイルシステムUUIDを探す。
# blkid | grep e4a /dev/nvme0n2p1: LABEL_FATBOOT="EFI" LABEL="EFI" UUID="1435-AC6A" BLOCK_SIZE="4096" TYPE="vfat" PARTUUID="e4a89f28-6e8a-ea41-97bb-c0ae7e3e806b"
UUID=“1435-AC6A”がそれである。