法楽日記

デジタル散策記&マインド探訪記

Ubuntu 16 on xhyve on MacOS X

MacOS X 10.13 (High Sierra) 上で xhyve を利用して Ubuntu 16 を動かしてみました。本当は Ubuntu 18 を動かしたかったのですが、エラーが発生して起動できず、その原因の見当がつきません…。そこで今回は、代わりに Ubuntu 16 を動かすことにしました。

なお、xhyveFreeBSDbhyve を移植したもので、MacOS XHypervisor.framework を利用しているそうです。

本稿は、下記記事を参考にして作業した結果をまとめたものです。


xhyve のインストール

今回は MacPortsxhyve を利用しました。(長い目で見ると、Github 上の最新版を利用した方が安心かもしれません)

$ port info xhyve
xhyve @20181126 (emulators)

$ sudo port install xhyve

準備

今回はサーバー用の Ubuntu 16.04.5 LTS をインストールしました。

xhyve を用いて Linux を起動するためには、起動用ファイルシステムの他に、Linux カーネルと初期化用ファイルが必要となるそうです。

そこで、Ubuntu 16 のインストール用の ISO イメージからこの二つのファイルを事前に取り出しておく必要があります。その手順を shell script にまとめました。状況によりマウント・ポイントは変化する可能性がありますので、あくまで参考資料として掲載します。

#!/bin/sh

# See https://www.pagetable.com/?p=831

TMPVOLUME="ubuntu16-tmpvolume.iso"
BOOTVOLUME="../isoimages/ubuntu-16.04.5-server-amd64.iso"
UBUNTU_MNT="/Volumes/Ubuntu-Server 16"
UBUNTU_TGT="ubuntu16"

dd if=/dev/zero bs=2k count=1 of="$TMPVOLUME"
dd if="$BOOTVOLUME" bs=2k skip=1 >> "$TMPVOLUME"
hdiutil attach "$TMPVOLUME"

mkdir "$UBUNTU_TGT"
cp -p "$UBUNTU_MNT/install/vmlinuz" "$UBUNTU_TGT"
cp -p "$UBUNTU_MNT/install/initrd.gz" "$UBUNTU_TGT"
umount "$UBUNTU_MNT"

rm "$TMPVOLUME"

Ubuntu 16 のインストール

まず、インストール先のディスク・イメージを作成します。今回は 32G バイトで作成しました。

#!/bin/sh

MYIMAGE="storage.img"
SIZE="32g"

mkfile -n "$SIZE" "$MYIMAGE"

次に、このディスク・イメージに Ubuntu 16 をインストールします。そのための xhyve の引数例を、下記のインストール用 shell script に示します。

#!/bin/sh

MYIMAGE="storage.img"

XHYVE_DIR=".."
ISOIMAGE="$XHYVE_DIR/../isoimages/ubuntu-16.04.5-server-amd64.iso"
KERNEL="$XHYVE_DIR/ubuntu16/vmlinuz"
INITRD="$XHYVE_DIR/ubuntu16/initrd.gz"

CMDLINE="earlyprintk=serial console=ttyS0 acpi=off"

xhyve \
    -A \
    -m 2G \
    -c 2 \
    -s 0:0,hostbridge \
    -s 2:0,virtio-net \
    -s 3:0,ahci-cd,"$ISOIMAGE" \
    -s 4:0,virtio-blk,"$MYIMAGE" \
    -s 31,lpc \
    -l com1,stdio \
    -f kexec,"$KERNEL","$INITRD","$CMDLINE"

インストール時の操作は上述の記事を参考にしました。その記事によると、インストーラーから質問されたときは大概デフォルト通りでよいそうです。中でも「Install the GRUB boot loader to the master boot record”」に「YES」と答えることはとても重要だそうです。ただし例外はあると思いますので、わかる範囲で質問を理解した上で答えた方がよいと思います。

インストールが完了して、インストーラーから抜ける直前に、インストールされたファイルの一部を MacOS Xファイルシステムにコピーする必要があります(xhyve を用いて Linux を起動するために必要なファイルです)。

そのためには、インストール完了時に「Installation complete」の画面で、「Go Back」→「Execute a shell」と選択して、shell を起動します。そして以下を行います(Ubuntu 16 の ifconfig が表示する IP アドレスをメモしておいてください)。

# cd /target
# sbin/ifconfig
# tar -c boot | nc -l -p 1234

次に、MacOS X の Terminal で以下を行います(nc の第1引数は Ubuntu 16 の IP アドレスです)。これにより Ubuntu 16 の /boot ディレクトリ以下が Ubuntu 16 から MacOS X にコピーされます。

$ cd <somewhere>
$ nc 192.168.64.8 1234 | tar -x

コピーが完了したら、インストーラーから起動した shell を「exit」コマンドで抜けて、インストーラーも終了させます。


Ubuntu 16 の起動

今インストールした Ubuntu 16 を起動するための xhyve の引数例を、下記の起動用 shell script に示します。Linux カーネルと初期化用ファイルには、インストールの最後に Ubuntu 16 から取り出したものを指定します。

#!/bin/sh

MYIMAGE="storage.img"
KERNEL="boot/vmlinuz-4.4.0-131-generic"
INITRD="boot/initrd.img-4.4.0-131-generic"
CMDLINE="earlyprintk=serial console=ttyS0 acpi=off root=/dev/vda1 ro"

xhyve \
    -A \
    -m 2G \
    -c 2 \
    -s 0:0,hostbridge \
    -s 2:0,virtio-net \
    -s 4:0,virtio-blk,"$MYIMAGE" \
    -s 31,lpc \
    -l com1,stdio \
    -f kexec,"$KERNEL","$INITRD","$CMDLINE"

--

Ubuntu 18 への upgrade

上述したように、本当は Ubuntu 18 をインストールしたかったのですが、Ubuntu 18 の ISO イメージを起動しようとすると、下記エラーによりインストールできませんでした。

[    0.824062] ---[ end Kernel panic - not syncing: No working init found.  Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance.

そこで今回は Ubuntu 16 をインストールしました。

一旦 Ubuntu 16 がインストールできると、下記コマンドにより Ubuntu 18 に upgrade できます。

$ sudo do-release-upgrade

ただし、xhyve の引数で指定する Linux カーネルと初期化用ファイルは、Ubuntu 16 のものを使い続けないと起動できません(上述の Ubuntu 18 起動時と同じエラーが発生してしまうからです)。はたしてこれで Ubuntu 18 として問題なく動作するのかどうか、どこかに落とし穴はないのか、若干の不安が残ります…

もしかしたら、xhyve の MacPorts 版ではなく、Github の最新版で試してみると症状が変わるかもしれませんが、残念ながら今日は余力が残ってないのでこの辺で…


リンク集