ファイルサーバのリプレイス 2020 その 3

リプレースが終わって、もうどれくらい経ったのだろうか。動き始めてしまうと、構築の時の苦労なんて忘れてしまいます。とはいえ何年か後に、どうしてこんなことになったのか問い詰めたいという自分自身のために、参照情報を残しておきます。

今回はブートローダカーネルのお話です。

ブートローダの話の前に、カーネルの作り方について少し考える必要があります。ハンドブックと異なり、 OpenRC ではなく systemd を使いたいので、systemd のユーザランドを持つ stage3 を選択しました。このユーザランドを使うためには、当然カーネルも systemd の要求を満たす必要があります。個人的には Linux の make menuconfig はあまり好きではなく(略)。例によって Gentoo Wiki で大抵の情報は集まります。

systemd
https://wiki.gentoo.org/wiki/Systemd

せっかくなので、 docker が動くようにもしておきましょう。

Docker
https://wiki.gentoo.org/wiki/Docker

当然、 ZFSカーネルが機能を持たなくては扱うことができないので、設定します。

ZFS
https://wiki.gentoo.org/wiki/ZFS

今回は MBR(Master Boot Record) ではなく UEFI(Unified Extensible Firmware Interface) から boot するようにしたいので、 UEFI へのインターフェースをカーネルに持つようにします。

EFI System Partition
https://wiki.gentoo.org/wiki/EFI_System_Partition

Efibootmgr
https://wiki.gentoo.org/wiki/Efibootmgr

この段階では、上記のドキュメントの全てに目を通す必要はなく、 Kernel の設定部分を参照するだけで大丈夫です。他の部分は、あとでまた参照することになります。

次は、いよいよブートローダの設定になります。結論から説明すると、今回はブートローダを導入することはしません。UEFI の機能とファイルシステムに直接カーネルを設定します。まず、この UEFI で用いる特別なパーティション ESP(EFI System Partition) が必要なわけですが、 FAT32 とか VFAT と呼ばれるファイルシステムである必要があります。実はここで少しはまりました。こんな大事な規格に Microsoft の独自規格が採用されるわけがない、なんてことはないのです。

忘れずにファイルシステムを作って /boot に mount します。

# mkfs.fat -F 32 /dev/nvme0n1p2
# mount /boot

ブートローダを利用しないということは、直接 UEFI からカーネルが boot してストレージなどのリソースを管理し、ファイルシステムを認識した上で、ファイルシステムにあるプログラムを実行して OS として起動します。これでは、異なるストレージやパーティションに存在するファイルシステムを boot のプロセス中に参照することができません。そのため、ブートローダを使う場合には、任意の boot 可能なプログラムを実行し、 RAM ディスクという MS-DOS 時代はたくさん使ったあの仕組みに似た方法で、いったんファイルシステムを mount します。

という仕組みがあって、デュアルブートや起動前にカーネルを選択することのない環境であってもブートローダを使っていたのではなかろうかと、今では思うわけです。

今回は root パーティションの場所をあらかじめカーネルに持たせます。 / を mount しているブロックデバイスですね。さらに、今回は root パーティションさえ mount できれば /usr も /var も同じパーティションにあります。そのため、カーネルが root パーティションを mount できてしまえば、必要なプログラムへの参照には困らないことになります。なので、以下のページについてもカーネルの設定をみておけば大丈夫です。

EFI stub kernel
https://wiki.gentoo.org/wiki/EFI_stub_kernel

ここ 10 年くらいで /dev のブロックデバイスに UUID を振って識別するようにしているディストリビューションもあるようです。ユースケースがあまり思いつかないのですが、オンプレミスで使う限りは今まで通り /dev/sda1 とかっていう、人間が識別できる名前のほうが良いと思っています。確かにデバイスファイルの名前が変わることはあります。しかし、いずれも新しくデバイスを追加削除したり、カーネルを変えたときに限られます。大抵は人間の手が入った時なんじゃないかな、と思うわけです。朝起きたらデバイスファイルの名前が変わってるとか、ほんと何それ怖い、なのですが、あなたの知らない世界はまだまだたくさんあるのかもしれません。

さて、実はカーネルの構築はまだ終わっていません。ここまで設定したら、いよいよカーネルを然るべき場所に置き、UEFI に認識してもらうための設定を行います。

# cd /usr/src/linux
# make -j7 && make -j7 modules_install
# mount /boot
# make install

とか。 -j7 は make が同時に実行するジョブの最大数です。 20 年くらい前は CPU の数、またはコアの数 + 1 がちょうど良い、と言われていました。今回は 6 コアの CPU なので 7 という数字になります。

/boot に作ったカーネルがあります。 ESP に使ってもらえうよう、 efibootmgr というプログラムで設定します。詳細はこのページにあるので、今回は最後まで読みましょう。

Efibootmgr
https://wiki.gentoo.org/wiki/Efibootmgr

ファイルを然るべきところに置いて、 UEFI に設定します。

# cd /boot
# mkdir -p efi/boot/
# cp vmlinuz-5.4.48-gentoo efi/boot/bootx64.efi
# efibootmgr --create --disk /dev/nvme0n1 --part 2 --label "Gentoo" --loader "\efi\boot\bootx64.efi"

ファイルシステムFAT32 なので、パスは \ で区切られます。モヤモヤする。--part 2 では /boot に mount するブロックデバイスがストレージの 2 番目のパーティションにあることをプログラムに教えています。

ここまでの設定が無事に終われば、マザーボードの設定からこのエントリ Gentoo が見えるようになるはずです。見えたら、 boot の優先順位を 1 番にしてあげれば、内部のストレージから起動するようになります。多分、ここが一番ハマりどころだと思います。あちこちにトラップがあるので、 UEFI のエントリに登録されなかったり、登録されてもカーネルが boot しなかったり、カーネルが boot しても panic が起きたり、ユーザランドが動いても root ユーザのパスワードを設定していなかったり、楽しいですね!

次はいよいよ ZFS とリプレース作業そのものです。