動機
FreeBSDで作業していて、Linuxバイナリを実行したいけどLinuxulatorではうまく動かないことがある。ちょっとソースをいじれば解決することも多いのだけど、ビルドが大変だったりして面倒くさい。ならbhyveで解決できるんじゃないかな。と思ったら、まずLinuxをインストールするところではまったのでメモ。というか、Qiitaを使ってみるテスト。
前提
- FreeBSD 11.1-RELEASE-p9
- vm-bhyve v1.1-p8 (build 101073)
- Ubuntu 16.04.4 Server1
手順
vm-bhyveの設定
まずはvm-bhyve環境の立ち上げ。基本的にQuickstartを参照すればなんとかなる。今回データストアはZFSを使っているがUFSでも大差はないはず。
bhyveでLinuxを起動する方法には
- grub2-bhyve
- uefi-edk2-bhyve
の2種類があるのだけど、今回は勉強もかねてUEFIでやることに2。
> sudo pkg install vm-bhyve uefi-edk2-bhyve
> sudo zfs create tank/vm
> sudo sysrc vm_enable="YES"
> sudo sysrc vm_dir="zfs:tank/vm"
> sudo vm init
> sudo vm switch create public
> sudo vm switch add public em0
これでVM作成の準備は整った。
VMの設計
設計というほどのことではないのだが、まずVMのテンプレートを書く必要がある3。/usr/local/share/examples/vm-bhyve/に色々例が載っているのでそれを参考にすればよい。
Ubuntu用のubuntu.confとの違いで重要なのは、
- UEFIを使うので
loader="grub"
の代わりにuefi="yes"
- クロック設定を
utctime="yes"
今回使ったファイルは以下の通り。これをデータストアの.templates/以下に置く。
uefi="yes"
cpu=4
memory=8G
utctime="yes"
network0_type="virtio-net"
network0_switch="public"
disk0_type="virtio-blk"
disk0_name="disk0"
disk0_dev="sparse-zvol"
Ubuntuのインストール
まずはインストーラのISOイメージを取得。VMの作成時にディスクサイズを指定する必要があるが、現状2Gあればインストール自体はできるようだ。
> sudo vm iso ftp://ftp.riken.go.jp/Linux/ubuntu-releases/16.04.4/ubuntu-16.04.4-server-amd64.iso
> sudo vm create -t ubuntu-uefi -s 4G ubuntu
一般的にはvm-bhyveでUEFIを使うのは、VNC経由でGUIを利用したい場合らしい。しかし今回はあくまでCUIベースで作業をするため、インストーラにシリアルコンソールの使用を指示しなければいけない4。
> sudo vm install -f ubuntu ubuntu-16.04.4-server-amd64.iso
これを実行すると、まずISOイメージに入っているgrubが立ち上がるので、タイミングを逃さずeを入力してカーネルのコマンドラインを編集する。vmlinuzの行にあるquiet
を消してtext console=ttyS0,115200
に置き換えてから、Ctrl+Xで起動5。インストール自体は適当にやればいいと思うが、rootでログインできないから一般ユーザーを必ず作ることと、後々つかうためのOpenSSH serverをインストールしておくこと。
UEFI起動プロセスの補正
インストールは完了したがこのままでは一度VMを停止させたあと再起動させることができない。
これは現行バージョンのbhyveではUEFIのNVRAM (Non-Volatile RAM)が揮発性のため6、VMを停止させるとEFI System PartitionにあるUEFI用grubを読み込めなくなってしまうため。UEFI用grubをデフォルトの位置にコピーしてやれば解決する。つまりインストール直後に再起動した状態で(VMを停止させずに)一般ユーザーでログインして、以下の作業をする。
$ sudo mkdir /boot/efi/EFI/BOOT
$ sudo cp /boot/efi/EFI/ubuntu/grubx64.efi /boot/efi/EFI/BOOT/BOOTX64.EFI
もしVMを一旦停止させてしまった場合には、コンソールを有効にして起動し、
> sudo vm -f start ubuntu
Boot Failed.のまましばらくまっているとUEFI shellが起動するので、
> FS0:\EFI\ubuntu\grubx64.efi
と入力してUEFI用grubを起動し、かつeを押してvmlinuzの行にtext console=ttyS0,115200
を書き足してから起動することができる。あとは一般ユーザーでログインして、上記の作業を行えばよい。
補足
参考としてUEFIの起動プロセスの説明。UEFIから起動する場合はGPTディスクである必要があり、そのEFI System Partition (ESP)中にあるブートローダに制御が移る。ESPは昔ながらのFATファイルシステムであり、デフォルトでは\EFI\BOOT\BOOTX64.EFIがブートローダとして読み込まれる7。LinuxディストロはWindowsやFreeBSDとは違ってこれを上書きせず別の場所にブートローダを置き、UEFIのNVRAMに読み込むべきブートローダの位置を書き込んでいる。しかしbhyveではNVRAMの内容が保存されないため、デフォルト位置のブートローダを読み込もうとする。Ubuntuの場合、ESPは/boot/efiにマウントされているので、grubx64.efiをデフォルト位置にコピーしてやれば解決するというわけ。
-
Linuxディストロの中でUbuntuだけはちょっと触ったことがあるという理由で選択。本当は18.04でやりたかったのだけど、カーネルが.isoを認識できずにインストーラが途中で止まってしまう。(2018-05-22追記:2018-04-28にuefi-edk2-bhyveが更新されLinux kernel 4.15が利用できるようになったらしいので多分解決しているはず)(2018-0619追記:解決していることを確認) ↩
-
これがはまりポイントだったわけだけど。 ↩
-
テンプレートを指定せずに
vm create
して、その後vm configure
する方がエレガントだが、そのためには少なくともdefault.confが必要。 ↩ -
未確認だが起動にgrubを使う場合は自動的にCUIベースでいけるのかな ↩
-
この件はFreeBSD bhyve+vm-bhyveでCentOS7をuefiで入れてみるおよび@m_birdによる ↩
-
すでに不揮発性にするパッチが存在しておりFreeBSD 12に取り込まれる模様 ↩
-
64bit仕様の場合。32bit仕様だと\EFI\BOOT\BOOTX86.EFIとなる。 ↩