メモのページ - チラシの裏メモ 3枚目

通信技術や気になった事を黙々とメモし続ける

MirageOS Unikernelを少しかじってみた

Alpine Linuxと同程度もしくはもっと小さいサイズのOSは無いかネット上をふらふら彷徨っていたら、ユニカーネル(Unikernel)という物に出くわした。
特定のプログラムを動作させるだけの極小OS、極小カーネルに興味を持ち、自分用PCで動作しそうなものをVirtualboxの中のUbuntu Serverに突っ込んで遊んでみたくなった。
Unikernelと言っても種類は様々有るが、開発活動が活発であり、且つ自分の環境にて導入が容易と思われるMirageOSを選択。
今まで触れた事が有る小さなOSと言えばQNX Neutrino。32bit版のCisco IOS XRのカーネル部分に採用されているUNIX系OSで、MirageOSより少しだけ大きいサイズだったような気がしたが、ライセンス適用が面倒な点と、IOS-XRvのshellモードで気軽に触れる事が可能で新鮮味が無いという事で却下。
以下は、MirageOSのインストールからhello worldプログラムの実行までやってみた時のメモ。


当方の環境
ホストOS:Windows7 32bit版 / RAM: 4GB / CPU: Intel Core i3-2350M 2.30GHz
ゲストOS:Ubuntu Server 18.04.3 x86 64bit版
UnkernelなOS:Mirage OS 3.7.6
Virtualbox:5.2.32
Ubuntu Serverは既にデプロイ済みである事とする。
PCのCPU仮想化支援機構はBIOSにて既に有効設定済みである事とする。

MirageOSのインストール手順は、以下のサイトを参考に進めた。
(https://qiita.com/t-imada/items/6ee299653ac063532b4f MirageOS のインストールから Hello World までを試す)
自分の環境ではhvtオプション下でのHello Worldが正常に実行出来なかった為、VirtioオプションでコンパイルしHello World実行プログラムを生成させて実行した。


そもそも、Unikernelとは
詳細は下記リンク先を参照という事で、ここでは簡潔に。
・ユニカーネル(Unikernel)とは、特定のアプリケーションを動かす為の軽量OS。アプリケーションとOSは1対1で紐付けされている為、他のアプリケーションを動かす為には、そのアプリケーション用のOSが必要となる。
・Unikernelの利点。ターゲットとなるアプリケーションに最適化されている点、起動が高速且つ消費メモリが非常に少ない点、カーネルのサイズが非常に小さい為にセキュリティの脆弱性リスクが非常に低い点の3つが挙げられる。
・Unikernelにはログインユーザは存在しない。
また、Unikernelはshellを持たない為、Unikernelにログインしプログラムを起動させる事は出来ない。※そもそも「Unikernelにログイン」自体が無い。
・MirageOSの場合。Unikernelを実行する際、アプリケーションの実行に必要な最小限のライブラリが自動で選択、ダウンロードされる。ライブラリが構成ファイルやアプリケーションファイル(config.mlとunikernel.ml)と共にコンパイルされ、特定のアプリケーションに特化したUnikernelが構築される。


...では、早速Mirage OSに触れてみる
まずはMirageOS導入の為の準備から。
最初に、MirageOS導入先のUbuntu ServerにてCPU仮想化支援機構の有効無効を確認。
lscpuコマンドで確認可能だが、Ubuntu Serverのデプロイ直後はインストールされていない為、lscpuコマンドを含んでいるutil-linuxをインストールした。

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install util-linux


インストール完了後、以下のコマンドを打ちCPU仮想化支援機構が有効になっている事を確認。
自分の環境では、Virtualization typeがnoneではなくfull、Hypervisor vendorはKVMになっていて、Ubuntu ServerにてCPU仮想化支援機構が有効になっている事がわかる。

$ lscpu
:
Hypervisor vendor:   KVM
Virtualization type: full
:


以下のコマンドを打ち、KVMモジュールを読み込ませる。

$ sudo modprobe kvm



次に、OCamlやopamのインストール。
MirageOS上で実行するプログラムはOCamlという関数型プログラミング言語で記述される。MirageOSのインストール前に、OCamlおよびコンパイラocamlと管理ツールopam、それらを動作させる為に必要なツールをインストール。
外部のリポジトリを利用する為、add-apt-repository ppa:avsm/ppaを最初に打つ。

$ sudo add-apt-repository ppa:avsm/ppa

Latest stable versions of OCaml and OPAM.
More info: https://launchpad.net/~avsm/+archive/ubuntu/ppa
Press [ENTER] to continue or Ctrl-c to cancel adding it.
:
省略
:
$ sudo apt-get update
0% [Working]            Hit:1 http://jp.archive.ubuntu.com/ubuntu bionic InRelease
0% [Connecting to ppa.launchpad.net (2001:67c:1560:8008::15)]
Hit:2 http://jp.archive.ubuntu.com/ubuntu bionic-updates InRelease
:
省略
:
$ sudo apt-get install opam ocaml gcc make bubblewrap m4 pkg-config qemu-kvm libvirt-bin bridge-utills virt-manager

Reading package lists... 0%Reading package lists... 100%Reading package lists... Done
:
省略
:
The following package was automatically installed and is no longer required:
  libdumbnet1
Use 'sudo apt autoremove' to remove it.
The following additional packages will be installed:
:
:
Processing triggers for libgdk-pixbuf2.0-0:amd64 (2.36.11-2) ...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
$



opamの環境設定
ocamlおよびopamのインストール完了後、opamの環境設定に進む。
今回は試用につき細かな環境構築は考慮に入れておらず、自動設定で進める為、質問されたらEnterキーを叩くのみ。
完了後、opam環境を有効にする為 eval `opam config env`コマンドを叩く。

$ opam init
[NOTE] Will configure from built-in defaults.
Checking for available remotes: rsync and local, git.
  - you won't be able to use mercurial repositories unless you install the hg command on your system.
  - you won't be able to use darcs repositories unless you install the darcs command on your system.

<><> Fetching repository information ><><><><><><><><><><><><><><><><><><><><><>
Processing  1/1: [default: http]Processing  1/1: [default: http][default] Initialised
:
:
Do you want opam to modify ~/.profile? [N/y/f]
(default is 'no', use 'f' to choose a different file) 
A hook can be added to opam's init scripts to ensure that the shell remains in sync with the opam environment when they
are loaded. Set that up? [y/N] n

<><> Creating initial switch (ocaml-system>=4.02.3) <><><><><><><><><><><><><><>
:
:
? installed base-threads.base
? installed base-unix.base
? installed ocaml-system.4.05.0
? installed ocaml-config.1
Processing 11/12: [ocaml: ocaml 4.05.0]? installed ocaml.4.05.0
Done.
# Run eval $(opam env) to update the current shell environment
$
$ eval `opam config env`
$


インストールされたopamコンパイラのバージョンを確認。
しかし、下記リンク先に記載されている、動作に必要となるバージョンを満たしていない為、新しいバージョンで再度インストール。

$ opam switch list
#  switch   compiler             description
→  default  ocaml-system.4.05.0  default
$ 

$ opam switch create 4.07.0

<><> Gathering sources ><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
Processing  5/6: [ocaml-base-compiler.4.07.0: dl]
Processing  6/6: [ocaml-base-compiler.4.07.0: dl]
[ocaml-base-compiler.4.07.0] downloaded from cache at https://opam.ocaml.org/cache
:
省略
:
Processing 11/12: [ocaml: ocaml 4.07.0]
? installed ocaml.4.07.0
Done.
# Run eval $(opam env) to update the current shell environment
$ 


インストール後、再度opam switch listコマンドを打ち新しいバージョンのopamが有効になっている事を確認。

$ opam switch list
#  switch   compiler                    description
→  4.07.0   ocaml-base-compiler.4.07.0  4.07.0
   default  ocaml-system.4.05.0         default
$


ここで、インストール済みの各ツールを確認。
あれ? インストール済みのツールの数が参照したサイトと違う。これしかインストールされていないのか...

$ opam list
# Packages matching: installed
# Name              # Installed # Synopsis
base-bigarray       base
base-threads        base
base-unix           base
ocaml               4.07.0      The OCaml compiler (virtual package)
ocaml-base-compiler 4.07.0      Official release 4.07.0
ocaml-config        1           OCaml Switch Configuration
~$


いえいえ大丈夫。MirageOSのインストールの際、他のツールやライブラリ等は後程一緒にインストールされます。


MirageOSのインストール
opam install mirageコマンドを打ち、MirageOSとMirageOSの実行に必要なツールをインストール。
自分の環境では、完了まで約30分程要した。

$ opam install mirage
The following actions will be performed:
  ? install seq                base    [required by fmt]
  ? install conf-m4            1       [required by ocamlfind]
  ? install ocamlbuild         0.14.0  [required by astring, bos]
  ? install dune               2.5.1   [required by mirage]
:
省略
:
  ? install mirage-runtime     3.7.6   [required by mirage]
  ? install functoria          3.1.0   [required by mirage]
  ? install mirage             3.7.6
===== ? 33 =====
Do you want to continue? [Y/n] y
:
:
Processing 63/66: [functoria: dune build]? installed functoria.3.1.0
Processing 65/66: [mirage: dune build]? installed mirage.3.7.6
Done.
# Run eval $(opam env) to update the current shell environment
$


インストール完了後、再度opam listコマンドを打つと色々なツールがずらーりずらり...

$ opam list
# Packages matching: installed
# Name              # Installed # Synopsis
astring             0.8.3       Alternative String module for OCaml
base-bigarray       base
base-bytes          base        Bytes library distributed with the OCaml compiler
base-threads        base
base-unix           base
bos                 0.2.0       Basic OS interaction for OCaml
cmdliner            1.0.4       Declarative definition of command line interfaces for OCaml
conf-m4             1           Virtual package relying on m4
cppo                1.6.6       Code preprocessor like cpp for OCaml
domain-name         0.3.0       RFC 1035 Internet domain names
dune                2.5.1       Fast, portable, and opinionated build system
dune-configurator   2.5.1       Helper library for gathering system configuration
dune-private-libs   2.5.1       Private libraries of Dune
fmt                 0.8.8       OCaml Format pretty-printer combinators
fpath               0.7.2       File system paths for OCaml
functoria           3.1.0       A DSL to organize functor applications
functoria-runtime   3.0.3       Runtime support library for functoria-generated code
ipaddr              4.0.0       A library for manipulation of IP (and MAC) address representations
logs                0.7.0       Logging infrastructure for OCaml
lwt                 5.3.0       Promises and event-driven I/O
macaddr             4.0.0       A library for manipulation of MAC address representations
mirage              3.7.6       The MirageOS library operating system
mirage-runtime      3.7.6       The base MirageOS runtime library, part of every MirageOS unikernel
mmap                1.1.0       File mapping functionality
ocaml               4.07.0      The OCaml compiler (virtual package)
ocaml-base-compiler 4.07.0      Official release 4.07.0
ocaml-config        1           OCaml Switch Configuration
ocaml-syntax-shims  1.0.0       Backport new syntax to older OCaml versions
ocamlbuild          0.14.0      OCamlbuild is a build system with builtin rules to easily build most OCaml projects.
ocamlfind           1.8.1       A library manager for OCaml
ocamlgraph          1.8.8       A generic graph library for OCaml
ocplib-endian       1.1         Optimised functions to read and write int16/32/64 from strings and bigarrays
ptime               0.8.5       POSIX time for OCaml
result              1.5         Compatibility Result module
rresult             0.6.0       Result value combinators for OCaml
seq                 base        Compatibility package for OCaml's standard iterator type starting from 4.07.
sexplib0            v0.13.0     Library containing the definition of S-expressions and some base converters
stdlib-shims        0.1.0       Backport some of the new stdlib features to older compiler
topkg               1.0.1       The transitory OCaml software packager
$ 


インストールされたMirageOSのバージョンを確認。
...あれ? opam環境は上記で有効にした筈だが、もう忘れたようなので再度有効にし、mirageコマンドを実行。

$ mirage --version

Command 'mirage' not found, but can be installed with:

sudo apt install mirage

$ 
$ eval `opam config env`
$ mirage --version
v3.7.6
$



Hello Worldプログラムのコンパイルとインストール
ここではOCamlでHello Worldプログラムを1から書くのではなく、MirageOSの公式githubからホームディレクトリに持ち出す。
clone完了後、lsコマンドを打つとmirage-skeletonディレクトリが作成されている事が確認出来る。
このmirage-skeletonディレクトリ配下にHello Worldのアプリケーションファイル(unikernel.ml)と構成ファイル(config.ml)が有る為、cdコマンドで移動する。

$ git clone https://github.com/mirage/mirage-skeleton.git
Cloning into 'mirage-skeleton'...
remote: Enumerating objects: 121, done.
remote: Counting objects:   0% (1/121)
remote: Counting objects:  1% (2/121)
remote: Counting objects:   2% (3/121)
:
省略
:
Resolving deltas:  99% (1587/1602)
Resolving deltas: 100% (1602/1602)
Resolving deltas: 100% (1602/1602), done.
$ 
$ ls
mirage-skeleton
$
$ cd mirage-skeleton/tutorial/hello
$
$ ls
config.ml  unikernel.ml
$


Virtioオプションを付け、Hello Worldプログラムのコンパイルを実行。
コンパイル完了まで3つのコマンドを打つ必要が有る。
最初はVirtioオプションを付けてmirage configureコマンドを叩き、コンパイルに必要なファイルの生成。

$ mirage configure -t virtio
Scanned 0 directories          Done: 0/0 (jobs: 0)        hogehoge@ubuntu:~/mirage-skeleton/tutorial/hello$ 
$ 


次にmake dependコマンドを打ち、依存関係の有るopamツールおよびUbuntuのパッケージを自動でインストール。
make depend以下は自動で出力される。
途中で数回質問されているようなのだが、こちらが返答する必要は無く勝手に進んでインストールされる。

$ make depend
opam pin add -k path --no-action --yes mirage-unikernel-hello-virtio . && opam depext --yes --update mirage-unikernel-hello-virtio ; opam pin remove --no-action mirage-unikernel-hello-virtio
Package mirage-unikernel-hello-virtio does not exist, create as a NEW package? [Y/n] y
Processing: [mirage-unikernel-hello-virtio.~dev: rsync][mirage-unikernel-hello-virtio.~dev] synchronised from file:///home/hechtia/mirage-skeleton/tutorial/hello
[WARNING] Failed checks on mirage-unikernel-hello-virtio package definition from source at
          file:///home/hechtia/mirage-skeleton/tutorial/hello:
  warning 37: Missing field 'dev-repo'
  warning 49: The following URLs don't use version control but look like version control URLs:
              "https://github.com/mirage/mirage-skeleton.git#master"
mirage-unikernel-hello-virtio is now pinned to file:///home/hechtia/mirage-skeleton/tutorial/hello (version ~dev)
Opam plugin "depext" is not installed. Install it on the current switch? [Y/n] y
The following actions will be performed:
  ? install opam-depext 1.1.3
:
省略
:
Processing 79/80: [mirage-bootvar-solo5: dune build]? installed mirage-bootvar-solo5.0.6.0
Done.

<><> mirage-fs.3.0.1 installed successfully <><><><><><><><><><><><><><><><><><>
=> This package will be retired in MirageOS 4.0. Please use mirage-kv instead.

<><> mirage-types.3.7.6 installed successfully ><><><><><><><><><><><><><><><><>
=> This package will be retired in MirageOS 4.0. Please use individual signatures (mirage-net / mirage-clock / etc.)
   instead.

<><> mirage-types-lwt.3.7.6 installed successfully ><><><><><><><><><><><><><><>
=> This package will be retired in MirageOS 4.0. Please use individual signatures (mirage-net / mirage-clock / etc.)
   instead.
$


最後に、makeコマンドを打ちHello Worldのアプリケーションバイナリファイルhello.virtioと仮想マシンのバイナリファイルsolo5-virtio-runを生成。
※ここで言うアプリケーションバイナリファイルとはMirageOS側、仮想マシンとはUbuntu側を指す。
生成後、lsコマンドの実行でhello.virtioが当フォルダ内に有る事を確認。solo5-virtio-runは別のディレクトリ内に有る。whichコマンドでsolo5-virtio-runファイルが有る場所を探す事が出来る。

$ make
mirage build
Scanned 0 directories        Done: 0/0 (jobs: 0)       config.exe: [WARNING] pkg-config solo5-bindings-virtio --variable=ld returned nothing, using ld
$
$ ls
_build     dune        dune.config   hello_libvirt.xml  key_gen.ml  Makefile                            myocamlbuild.ml
config.ml  dune.build  dune-project  hello.virtio       main.ml     mirage-unikernel-hello-virtio.opam  unikernel.ml
$
$ which solo5-virtio-run
/home/hogehoge/.opam/4.07.0/bin/solo5-virtio-run
$



Hello Worldプログラムの実行
ついにHello World実行まで漕ぎ着けた。
ここでは、仮想マシンバイナリファイルsolo5-virtio-runでアプリケーションバイナリhello.virtioを実行させる。
アスキーアートのロゴの出力とhelloが4回出力されれば、MirageOSのインストールおよびHello Worldプログラムの生成は成功となる。

ターミナルツールに出力されているアスキーアートのSolo5とは。
Solo5とはUnikernel向けのサンドボックス環境の事。Unikernelを動作させる為のセキュアな環境と、UnikernelとSolo5が接する箇所の共通的なAPを提供する。

$ solo5-virtio-run hello.virtio
+ exec qemu-system-x86_64 -cpu Westmere -m 128 -nodefaults -no-acpi -display none -serial stdio -device isa-debug-exit -kernel /home/hechtia/mirage-skeleton/tutorial/hello/hello.virtio
            |      ___|
  __|  _ /  |  _ / __ /
/__ / (   | | (   |  ) |
____//___/ _|/___/____/
Solo5: Bindings version v0.6.4
Solo5: Memory map: 128 MB addressable:
Solo5:   reserved @ (0x0 - 0xfffff)
Solo5:       text @ (0x100000 - 0x1d0fff)
Solo5:     rodata @ (0x1d1000 - 0x201fff)
Solo5:       data @ (0x202000 - 0x2a1fff)
Solo5:       heap >= 0x2a2000 < stack < 0x8000000
Solo5: Clock source: TSC, frequency estimate is 2298037280 Hz
2020-05-16 03:09:22 -00:00: INF [application] hello
2020-05-16 03:09:23 -00:00: INF [application] hello
2020-05-16 03:09:24 -00:00: INF [application] hello
2020-05-16 03:09:25 -00:00: INF [application] hello
Solo5: solo5_exit(0) called
$


成功した。ただし一発で成功したのではなくここまで辿り着くまで5回、トライ&エラーを繰り返した。
Ubuntuとopamのバージョンが古くなければ、make dependで動作に最適なバージョンのmirageやその他のツールを引っ張ってきてくれるので導入は楽だと思う。

次はMirageOSで何をやってみるか。下記リンク先の動作例を試すか、OCamlに手を出すか...


Hello Worldを再度試行したい場合
当手順実施後は必要なツールは既に揃っている為、~/mirage-skeleton/tutorial/helloディレクトリに移動しsolo5-virtio-run hello.virtioを叩けば、solo5のロゴとhello4発が出力される。
solo5-virtio-run hello.virtioを実行しても想定どおりの出力が無い場合は、eval `opam config env`を叩き、再度solo5-virtio-run hello.virtioを実行する。


MirageOSに触れて気が付いた事
・Hello Worldやmirage-wwwやstatic website tlsなどチュートリアル用アプリが豊富で、思っていたより敷居は高くなかった。OCamlを使ったプログラミングの経験が全く無くても動かす事が出来た。
・Debian GNU/LinuxやUbuntu Linuxのapt-getコマンドの如く、opam installコマンドやmake dependコマンドで、MirageOSを動作させる為のパッケージが自動でインストールされる為、動作に必要なパッケージをユーザが探して個々にインストールする必要は殆ど無いので楽。
・何らかの事情でパッケージを個々にインストールする必要が生じた場合、opam searchコマンドで探し、opam installコマンドでインストールする事が出来る。
・日本国内の先達の方々が残してくださったブログやQiitaの記事は、コマンドの単なる羅列ではなくコマンドのオプションやコマンド実行時の説明をしっかりと残してくださり、大変参考になった。
・マニュアルは揃っている方だと思う。勿論、Cisco SystemsやJuniper Networksのオンラインドキュメント程の量や質には何年かけても辿り着けないと思うが、これから入門する人にとって必要最低限の量や内容は揃っている。
・UnikernelsはMirage OSの他に、Click OSやOSv等乱立しているが、今のところあれこれ手を出す予定は無い。趣味レベルの段階につきMirageOSやOCamlで精一杯。
・かつてクラウドOSと呼ばれていた時期が有ったようだが(https://cloud.watch.impress.co.jp/docs/column/virtual/666595.html)、今はユニカーネルが一般的なようだ。
・これがOSと言われてもしっくりと来ないのは、Ubuntu Serverの上で動作させている為と思われる。Xen Server等を自宅環境に用意し、その上でMirageOSを動作させれば、Unikernelのアーキテクチャに関してもう少し理解しやすくなるのだろうか。
・Unikernelsを覗く時、Unikernelsもまたこちらを覗いているのだ。プログラミング経験ゼロの自分は泥沼に嵌るのか、早々に撤退するのか...




参照したサイト等
以下は、MirageOS入門を後押ししてくれたサイト。検索していなければUnikernelやMirageOSに出会う事は無かった。著者様に感謝致します。
https://qiita.com/t-imada/items/5fda04ba462f80857788 MirageOS Unikernelの概要
https://qiita.com/t-imada/items/6ee299653ac063532b4f MirageOS のインストールから Hello World までを試す
https://qiita.com/t-imada/items/ed6a76f5b257f5608ad0 Unikernelな情報 (in Japanese)

ユニカーネル関連
https://mirage.io/ MirageOS Unikernel
https://github.com/mirage MirageOS (github)
http://unikernel.org/ Unikernels
https://github.com/Solo5/solo5 Solo5

以下は、当記事公開後にMirageOSでやってみた内容
https://debslink.hatenadiary.jp/entry/20200526/1590495778 追記:MirageOS Unikernelで通信プログラムの実行
https://debslink.hatenadiary.jp/entry/20200718/1595076105 追記:Ubuntu 20.04でMirageOS Unikernel
https://debslink.hatenadiary.jp/entry/20200726/1595768920 追記:MirageOS UnikernelでWebサーバ
https://debslink.hatenadiary.jp/entry/20200815/1597493701 追記:MirageOS Unikernelでデータベース