概要
本記事ではMirageOS Unikernel 環境を仮想化支援機構(on x86_64 or aarch64 アーキ)が有効化されたLinuxマシンへインストールし、MirageOS Unikernelの第一歩であるHello Worldアプリ実行までを説明していきます。
Ubuntu18.04LTS(amd64 or aarch64) がインストールされた物理マシンが用意されていることを想定します。(Intel VT-x もしくは AMD-V の Nested が有効化された仮想マシン上のUbuntuでも動作するはずですが、実機で試しておらず...)。
MirageOS Unikernel のアプリケーション(Hello Worldアプリ)を、Linux KVM(Kernel Virtual Machine) を利用して起動させます。
(参考サイト)
MirageOS Documentation and guides - Installation
Building a MirageOS hello world
0. CPU仮想化支援機構のチェック
#####Intel社 もしくは AMD社製のx86系CPUを利用している場合
lscpu
コマンドを用いて仮想化支援機構が有効化されているか確認します。lscpu
コマンドがない場合には、インストールします。
$ apt-get install util-linux
lscpu
コマンドを実行すると、CPU仮想化支援機構が有効化されている場合には "Virtualization" という項目の行に "VT-x" もしくは "AMD-V" と表示されているはずです。
(もし表示されていない場合には、こちらなどを参考にBIOS設定を確認する必要があります。)
$ LC_ALL=C lscpu | grep Virtualization
Virtualization: VT-x # Intel社製CPU
もしくは
Virtualization: AMD-V # AMD社製CPU
さらに、Ubuntu が提供しているx86_64用カーネルはLinux KVMがモジュール化されているため、modprobe
コマンドを実行して読み込んでおきます。
# for Intel社製CPU
$ modprobe kvm
$ modprobe kvm_intel
# for AMD社製CPU
$ modprobe kvm
$ modprobe kvm_amd
ARMアーキテクチャCPUの場合
手元にあった Raspberry Pi 3 に Ubuntu18.04LTS(aarch64) をインストールしてみたところ、lscpu
コマンドでは上手く "Virtualization" が表示されませんでした。代わりに、dmesg
コマンドの結果からCPU仮想化支援機構が有効化されていることを確認します。
"Hyp mode initialized successfully" と表示されれば有効化されています。
$ dmesg | grep kvm
[ 4.399887] kvm [1]: 8-bit VMID
[ 4.405636] kvm [1]: Invalid trigger for IRQ4, assuming level low
[ 4.410233] kvm [1]: Hyp mode initialized successfully
1. 依存関係のあるパッケージのインストールと環境設定
MirageOS Unikernel は OCaml という関数型言語でアプリケーションレイヤをユーザが記述するため、コンパイラと管理ツールが必要です。コンパイラは"ocaml"、管理ツールは"opam"というパッケージ名です。
特に、Ubuntu18.04LTSのデフォルトで提供されるopamパッケージはバージョンが1.2.2と古いため、外部のリポジトリ ppa:avsm/ppa を利用してバージョン2.0.0以降がインストールされるようにします。
他にも必要なパッケージがあるため、ここでインストールしておきます。
$ sudo add-apt-repository ppa:avsm/ppa # 外部リポジトリ利用
$ sudo apt-get update
$ sudo apt-get install opam ocaml gcc make bubblewrap m4 pkg-config
次に、opam
コマンドとOcamlコンパイラに関わる設定をします。具体的には、opam init
コマンドでopam環境を初期化し、.bashrc(もしくは.bash_profile)ファイルに eval `opam config env`
を追加します。
$ opam init
$ tail ~/.bashrc
...
...
eval `opam config env`
次のステップに進むには、一度ログアウトして上記.bashrcファイルの変更を有効化させるか、またはeval `opam config env`
を実行しておきます。
なお、このopam
コマンドはOCaml環境を簡潔に管理するためのツールであり、異なるOCamlコンパイラのバージョンに切り替えたり、OCaml向けライブラリのインストール/アンインストール(Pythonにおけるpip
コマンドと同じ仕組みです)など色々な機能を持っています。opam
コマンドについての詳細な説明はこちら。
$ opam switch list
# switch compiler description
→ 4.07.0 ocaml-base-compiler.4.07.0 4.07.0
system ocaml-system.4.05.0
$ opam list
# Packages matching: installed
# Name # Installed # Synopsis
astring 0.8.3 Alternative String module for OCaml
base v0.11.1 Full standard library replacement for OCaml
...
...
tcpip 3.5.1 OCaml TCP/IP networking stack, used in MirageOS
topkg 1.0.0 The transitory OCaml software packager
uchar 0.0.2 Compatibility library for OCaml's Uchar module
2. MirageOS Unikernel のインストール
実のところ、本ステップはMirageOS Unikernel自体のインストールではありません。MirageOS Unikernelはユーザが記述するアプリケーションコードがあって初めてコンパイルできるものなので、ここでのインストールは「ユーザ記述のアプリケーションコードをコンパイルするためのプログラムやモジュール、ライブラリのインストール」のことを指します。
インストール作業はとても簡単です。下記のコマンドを実行して、mirageパッケージをインストールするだけです。1. にて紹介したopam
コマンドを早速利用します。
$ opam install mirage
mirage
コマンドを使えるようになりました。
$ mirage
NAME
mirage - The mirage application builder
SYNOPSIS
mirage COMMAND ...
...
...
3. Hello World な Mirage Unikernel アプリケーションのコンパイルと実行
Hello World な Mirage Unikernel アプリケーションのコードは、サンプルがあるので github から clone します。
$ git clone https://github.com/mirage/mirage-skeleton.git
この "mirage-skeleton" というリポジトリには、Hello World 以外にもDHCPサーバアプリなど幾つかのアプリケーションコードが登録されています。
次に、Hello World アプリケーションコードのあるディレクトリへ移動します。config.ml
と unikernel.ml
という2つのファイルがあります。前者は構成ファイル、後者はアプリケーションコードファイルです。
$ cd ./mirage-skeleton/tutorial/hello
$ ls
config.ml unikernel.ml
アプリケーションソースコード(unikernel.ml)を見てみると、 "hello"文字列を出力するための Logs.info()
関数がloop()
再帰関数によって4回実行されるように記述されています。
open Lwt.Infix
module Hello (Time : Mirage_time_lwt.S) = struct
let start _time =
let rec loop = function
| 0 -> Lwt.return_unit
| n ->
Logs.info (fun f -> f "hello");
Time.sleep_ns (Duration.of_sec 1) >>= fun () ->
loop (n-1)
in
loop 4
end
コンパイルしてみます。コンパイルまでには3コマンド実行します。
# ターゲットプラットフォームの設定(ここでは hvt) と コンパイルに必要なファイルの生成
$ mirage configure -t hvt
$ ls
_build config.ml key_gen.ml main.ml Makefile mirage-unikernel-hello-hvt.opam myocamlbuild.ml unikernel.ml
# 依存関係のあるパッケージのインストール
$ make depend
# MirageOS Unikernel アプリケーションバイナリの生成 と 仮想マシン(hvt)バイナリの生成
$ make
$ ls
_build config.ml key_gen.ml Makefile mirage-unikernel-hello-hvt.opam solo5-hvt
_build-solo5-hvt hello.hvt main.ml Makefile.solo5-hvt myocamlbuild.ml unikernel.ml
ここで、hello.hvt
は MirageOS Unikernel アプリケーションバイナリファイルであり、solo5-hvt
は仮想マシンバイナリファイルです。この2つを用いて、Linux KVMを利用して仮想CPU上でアプリケーションバイナリを実行させます。
このとき、Linux KVM利用のために /dev/kvm
ファイルをオープンする必要があるため、 sudo
コマンド経由での実行となります。sudo
コマンドでの実行が不便な場合は /dev/kvm
ファイルにreadとwriteのユーザ権限を付与してください(もちろん自己責任の範囲で...)。
$ sudo ./solo5-hvt ./hello.hvt
| ___|
__| _ \ | _ \ __ \
\__ \ ( | | ( | ) |
____/\___/ _|\___/____/
Solo5: Memory map: 512 MB addressable:
Solo5: unused @ (0x0 - 0xfffff)
Solo5: text @ (0x100000 - 0x20efff)
Solo5: rodata @ (0x20f000 - 0x236fff)
Solo5: data @ (0x237000 - 0x303fff)
Solo5: heap >= 0x304000 < stack < 0x20000000
2019-01-11 16:42:35 -00:00: INF [application] hello
2019-01-11 16:42:36 -00:00: INF [application] hello
2019-01-11 16:42:37 -00:00: INF [application] hello
2019-01-11 16:42:38 -00:00: INF [application] hello
Solo5: solo5_exit(0) called
無事に "hello" という文字列が4回出力されました!!
なお、アスキーアートと"Solo5:"で始まる文字列は仮想マシン(hvt)側のログ出力です。
4. コードの構成を理解したいときは...
こちらにネットワークアプリケーションを題材とした記事がありますので、参考にしてみてください。