追記: 2018/5/21
本記事の最後に「再起動するとブートローダのところで止まる」と書きましたが、UEFIファームウェアパッケージを最新のものに更新することで、FreeBSD-CURRENTが正常に起動することを確認しました。パッケージのバージョンは以下のとおりです。

$ pkg info | grep uefi
uefi-edk2-bhyve-20180318       UEFI-EDK2 firmware for bhyve
uefi-edk2-bhyve-csm-20180318   UEFI-EDK2 firmware for bhyve with CSM

もし、同様の不具合に遭遇した場合、パッケージの更新で状況が改善する可能性がありますので、試してみるとよいと思います。


まえがきでは、FreeBSDが提供する仮想化機構について簡単に説明しました。また、仮想化機構の一つであるbhyveを用いて仮想マシン(Virtual Machine, VM)を管理するためのシェルスクリプト、vm-bhyveについてもあわせて紹介しました。

本記事では、vm-bhyveを用いて、FreeBSD-CURRENTが動作するVMを構築する手順について見ていきます。基本的には、vm-bhyveのREADMEのQuick-Startにそって進めます。

必要なソフトウェアのインストール

まず、vm-bhyveをインストールします。また、FreeBSDをUEFI (Unified Extensible Firmware Interface)モードで起動することにしましたので、UEFIファームウェアもあわせてインストールします。(bhyveそのものは、ベースシステムにすでに組み込まれていますのでインストールは不要です。)

pkg install vm-bhyve bhyve-firmware

VMディレクトリ(あるいはファイルシステム)の作成

次に、vm-bhyveのVM設定ファイルやVMのディスクイメージを格納するディレクトリ(あるいはファイルシステム)を作成します。vm-bhyveはZFSに対応していますので、VMの格納場所をZFS上に置くのであれば、ファイルシステムを作成するほうがおすすめです。

以降、本記事では、VM格納用のファイルシステムとしてztank/vmsを使用します。また、本ファイルシステムのマウントポイントを/mnt/tank/vmsとします。

vm-bhyveの初期化

以下のコマンドを実行して、vm-bhyveの初期設定を行ないます。

sysrc vm_enable=YES
sysrc vm_dir="zfs:ztank/vms"
vm init

ZFSを使用しない場合は、2行目をsysrc vm_dir="/<path>/<to>/<vms>"としてください。

仮想スイッチの作成

bhyve上のVMが外部のネットワークと通信を行えるように、仮想スイッチを作成します。

vm-bhyveのREADMEやマニュアルには、vm switchコマンドを用いて仮想スイッチを作成する手順が示されています。しかし、本手順にしたがって仮想スイッチを作成すると、(VM上の)ゲストOSから(bhyveを動作させている)ホストOS上のサービスへのアクセスに問題が生じることがわかっています。(例えば、ゲストOSからのpingにホストOSが応答しない、ゲストOSからホストOS上のsamba共有ディレクトリにアクセスできない、など。詳しくは以下の記事を参照。)

この問題を回避するため、本記事ではマニュアルで仮想スイッチを作成します。まず、vm-bhyveのシステム設定ファイルを以下の内容で作成します。

この状態で、仮想スイッチの一覧コマンドvm switch listを実行してみてください。

# vm switch list
NAME            TYPE       IDENT       VLAN      NAT          PORTS
public          manual     bridge0     n/a       n/a          n/a

仮想スイッチにリストにpublic(タイプはmanual)が追加されています。

さて、マニュアルで仮想スイッチを作成するということは、publicという名前の仮想スイッチがbridge0というネットワークインターフェイスを使う、ということ以外はvm-bhyveは関知しません。bridge0のメンバーとなる物理ネットワークインターフェイスの名前をはじめとする、各種設定は手動で行なう必要があります。また、上記した問題も解決する必要があります。

上記問題の解決策は、ひと言でいうと「ブリッジインターフェイスにアドレスを割り当てる」ことです。FreeBSDハンドブックのBridgingの節に以下の記述があります。

If the bridge host needs an IP address, set it on the bridge interface, not on the member interfaces. The address can be set statically or via DHCP.

ブリッジインターフェイスを持つホスト(今回、bhyveのホストOSが稼働しているマシン)にIPアドレスを割り当てる場合は、「ブリッジのメンバーインターフェイスではなく、ブリッジインターフェイス自体にアドレスを割り当てる」ということですね。さらに、IPv6アドレスについては、ブリッジインターフェイスにリンクローカルアドレス割り当てられるように、auto_linklocalフラグを指定します。(参考: Bhyve + IPv6)

説明が長くなりましたが、以上の要領をまとめたブリッジまわりのマニュアル設定を以下に示します。(em0はお使いの環境の物理ネットワークインターフェイス名に合わせて読み替えてください。) 以下の例ではIPv4/IPv6アドレスともに、スタティックにアドレスを割り当てていますが、DHCP (Dynamic Host Configuration Protocol)やSLAAC (Stateless Address Autoconfiguration)を用いることも可能です。

以上で仮想スイッチの設定は終了です。ブリッジインターフェイスを有効にするため、ここでいったんFreeBSDマシンを再起動しておきましょう。

VMのテンプレート作成

FreeBSDをUEFIモードで起動させることにしましたので、VMのテンプレートファイルを作成します。(Legacyモードで起動させる場合は本項の作業は不要です。)

vm-bhyveをインストールしたときに、サンプルのテンプレートファイルもあわせてインストールされていますので、これをVMのテンプレートディレクトリにコピーします。

cp /usr/local/share/examples/vm-bhyve/* /mnt/tank/vms/.templates/
cd /mnt/tank/vms/.templates
cp freebsd.conf freebsd-uefi.conf

FreeBSD向けのテンプレートfreebsd.confをコピーして、FreeBSD UEFIモード起動用のテンプレートを作成しましょう。ここでは、freebsd-uefi.confというファイル名にしておきます。後ほどVMを作成する際に、この名前でテンプレートを指定します。ファイル中のコメント末尾に(*)を付したものは、お好みに合わせて調整してください。

VMの作成とインストール

次はいよいよFreeBSDのインストールです。インストールに先立って、必要なイメージファイルをダウンロードします。FreeBSD-CURRENTをインストールするので、現時点で最新のスナップショットイメージをダウンロードします。

vm iso ftp://ftp.jp.freebsd.org/pub/FreeBSD/snapshots/ISO-IMAGES/12.0/FreeBSD-12.0-CURRENT-amd64-20180322-r331345-disc1.iso

先ほど作成したテンプレートを指定してVMを作成します。ここでは、VM名をfreebsd-currentとしました。

vm create -t freebsd-uefi freebsd-current

VMの一覧を表示するコマンドvm listを実行してみましょう。

# vm list
NAME            DATASTORE       LOADER      CPU    MEMORY    VNC                  AUTOSTART    STATE
freebsd-current default         uefi        4      4G        -                    No           Stopped

いま作成したVMがリストに表示されていますね。このVMを格納する場所として、ディレクトリfreebsd-currentが作成され、その中にVM設定ファイルと空のディスクイメージが格納されています。ディレクトリの内容は以下のようになっています。

$ ls -l /mnt/tank/vms/freebsd-current
total 5
-rw-r--r--  1 root  wheel  68719476736  3月 23 21:42 disk0.img
-rw-r--r--  1 root  wheel          278  3月 23 21:42 freebsd-current.conf

最後に、イメージファイルを使ってFreeBSD-CURRENTをインストールします。

vm install freebsd-current FreeBSD-12.0-CURRENT-amd64-20180322-r331345-disc1.iso

このコマンドを実行すると、VMがVNCでの接続待ち状態になりますので、VNCクライアントを用いてVMに接続してください。VNCクライアントとしては、先日の記事でご紹介したRemminaがおすすめです。RemminaでのVNC接続を行なう際に、一点だけ注意があります。色数の設定を24 bpp以上にしないと画面がうまく表示されないようなので、ご注意ください。(下図)

RemminaのVNC設定画面

VNCで接続するとおなじみのスプラッシュ画面からインストーラに進みますので、いつものようにインストール作業を行なえばOKです。

FreeBSDの起動画面

FreeBSDのインストーラ画面

VMの運用

無事、インストールできましたでしょうか? あとは、以下のようなコマンド群を用いて、起動、終了などの運用を行なうことができます。

vm start freebsd-current       # VMの起動
vm stop freebsd-current        # VMのシャットダウン
vm reset freebsd-current       # VMの強制リセット
vm poweroff freebsd-current    # VMの強制パワーオフ
vm destroy freebsd-current     # VMの削除

また、ホストOSの起動時にVMも自動的に起動させたい場合は、以下のコマンドを実行します。

sysrc vm_list+="freebsd-current"
sysrc vm_delay=5

VMのリストを表示させてみるとAUTOSTARTの欄がYesになりました。

# vm list
NAME            DATASTORE       LOADER      CPU    MEMORY    VNC                  AUTOSTART    STATE
freebsd-current default         uefi        4      4G        -                    Yes [1]      Stopped

追伸:
FreeBSD-CURRENTの最近のスナップショットをいくつか試してみたのですが、インストールは成功裡に終了するものの、再起動をかけるとブートローダのところで止まってしまいますね…。11.1-RELEASEならば、インストールもその後の再起動も成功します。CURRENTを動かすことが目的ならば、11.1-RELEASEをインストール→自力でソースからビルドしてCURRENTに更新、のほうが早そうな気がします…。

参考文献

  1. vm-bhyve, https://github.com/churchers/vm-bhyve
  2. strange network problem about bridge #146, https://github.com/churchers/vm-bhyve/issues/146
  3. Bhyve + IPv6 can’t ping from guest to host until host ping guest, https://forums.freebsd.org/threads/bhyve-ipv6-cant-ping-from-guest-to-host-until-host-ping-guest.62851/
  4. Bridging, https://www.freebsd.org/doc/handbook/network-bridging.html
  5. Bhyve + IPv6, https://nbari.com/post/bhyve-ipv6/