====== Proxmox VE 6.2と他のZFSプールを1ストレージに同居させる ====== 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わかんねーんだよ! ===== 試した環境 ===== * Proxmox VE 6.2-4 * Intel DC S3700 400GB * PVEをインストールしたストレージ(sda)。便宜上、占有ストレージと呼ぶ。 * Samsung PM963 1.92TB * PVEと他のZFSプールを同居させるストレージ(nvme0)。便宜上、共存ストレージと呼ぶ。 ===== 方針 ===== 共存ストレージ作成にあたり、まずは占有ストレージのパーティションを確認する。 # 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の移植 ==== 作成した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 ==== rpoolの移植 ==== PVEのシステムデータのコピー方法は、ZFSのミラーリングを使う方法、send/recvを使う方法の2種類がある。 === 方法1:ミラープールを経由する ==== 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 === 方法2:zfs send/recvを使う === 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 {{ :virtualization:pve_zfs_send_recv_rpool_dry_run.png |}} 問題なさそうなら、-nを外して本番実行。 # zfs send -RLce rpool@backup | zfs recv -Fduv rpool2 {{ :virtualization:pve_zfs_send_recv_rpool.png |}} 念のため移行先のrpool2の中身を見てみる。 # zfs list -r rpool2 {{ :virtualization:pve_zfs_list_rpool2.png |}} == 移行先プールの名前変更 == 共存ストレージのrpool2を新生rpoolに名称変更する。 その前に、専用ストレージのrpoolが残ったままなので、こちらはrpool_origとでもしておく。 まずは両プールを一旦アンマウント。 # zpool export rpool # zpool export rpool2 rpoolをrpool_origに名前を変えてマウント。 # zpool -R /mnt/rpool rpool rpool_orig 同じく、rpool2をrpoolに名前を変えてマウント。 # zpool -R /mnt/rpool2 rpool2 rpool == 新生rpoolのbootfsの設定 == 共存ストレージの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 ===== ESP同期設定の変更 ===== 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を、この値で置き換える。