漢なら runC で aobench を動かしたいですよね!
Requirements
Ubuntu 14.04 or later や, CoreOS, docker-machine で作られるコンテナ対応済みイメージを使うのがオススメです.
runC では checkpoint 機能を使う場合, checkpoint 対応 Linux カーネルと CRIU が必要になります.
また, 最近では runC に seccomp がデフォルトで有効になりましたが, CRIU 側の seccomp 対応が未だである(CRIU 1.7 時点)ですので, checkpoint 機能を使う場合は seccomp 無効で runC をビルドする必要があります.
Build
docker-machine の google ドライバでコンテナ対応済み linux イメージを立てていると仮定します.
まず runC をビルドします. 参考となる Dockerfile は以下の通りです.
$ cat Dockerfile
FROM ubuntu:14.04
MAINTAINER syoyo@lighttransport.com
ENV HOME /root
ENV GOPATH /root/go
ENV PATH /root/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RUN apt-get update
RUN apt-get install -y build-essential git wget curl
RUN apt-get install -y libseccomp-dev seccomp
RUN mkdir -p $GOPATH
RUN wget -qO- https://storage.googleapis.com/golang/go1.5.1.linux-amd64.tar.gz | tar -C /usr/local -xzf -
# Build runc
RUN mkdir $GOPATH/src
RUN mkdir $GOPATH/src/github.com
RUN mkdir $GOPATH/src/github.com/opencontainers
# Workaround for invalidate cache for git clone.
ADD dummyfile /data/
RUN cd $GOPATH/src/github.com/opencontainers; git clone https://github.com/opencontainers/runc
# seccomp を無効にする場合は make BUILDTAG="" とする.
RUN cd $GOPATH/src/github.com/opencontainers/runc; make
RUN cd $GOPATH/src/github.com/opencontainers/runc; make install
runC 用 aobench イメージを作る.
すでに aobench イメージが Docker registory にありますので取得し, tar 形式に変換します.
$ sudo docker pull syoyo/aobench
$ sudo docker export $(sudo docker create syoyo/aobench) > aobench.tar
$ tar -c aobench_dist -xf aobench.tar
$ runc spec # runc を実行するディレクトリは aobench_dist ディレクトリではない
config.json
を編集し, rootfs
のパスを aobench_dist
に変更, process/args
を /bin/ao
にします.
runC で実行する.
config.json
のあるディレクトリで runc start します.
$ sudo runc start
ao: ao.c:321: saveppm: Assertion `fp' failed.
おおっと! ファイルシステムへの書き込みで失敗してしまいました...
config.json
で root/readonly
が true になっているのが原因そうです. とりあえず false に変えてみます.
$ sudo runc start
ao: ao.c:321: saveppm: Assertion `fp' failed.
ぐぬぬ... ルートファイルシステムは readonly = false でもダメのようです...
(runtime.json
では mounts/cgroups
に ro
フラグが付いているからでしょうか)
適当に tmpfs
を作りマウントするようにします.
runtime.json
に tmpfs
マウントの情報を mounts
に追加します.
{
"mounts": {
"cgroup": {
"type": "cgroup",
"source": "cgroup",
"options": [
"nosuid",
"noexec",
"nodev",
"relatime",
"ro"
]
},
...
"tmpfs": {
"type": "tmpfs",
"source": "tmpfs",
"options": [
"nosuid",
"noexec",
"nodev",
"mode=1777",
"size=65536k"
]
},
config.json
に /tmp
のマウント情報を記載します. また, CWD を /tmp
に設定して, /tmp
で /bin/ao
を実行するようにします.
"process": {
...
"args": [
"/bin/ao"
],
"cwd": "/tmp"
},
"mounts": [
{
"name": "proc",
"path": "/proc"
},
...
{
"name": "tmpfs",
"path": "/tmp"
},
再度実行します.
$ sudo runc start
Output ao.ppm
Voila! runC で aobench が動きました!
プロセスの pause/resume を試す.
pause
, resume
でプロセスの中断と再開を行うことができます.
$ sudo runc start
$ sudo runc pause
# 別のターミナルを開く
$ sudo runc resume
Cool!
pause
すると, top で見ると計算がストップしているのが確認できます.
Checkpointing を試す.
Checkpoint 機能を使うことで, プロセスの状態をファイルにダンプし, 別のマシンに転送してリストアすることでプロセスのマイグレーションができます.
Checkpoint 機能を使うには, システムに CRIU http://criu.org/Main_Page がインストールされている必要があります. 今回は CRIU 1.7 で確認しました.
config.json
にて,
-
process/terminal
= false -
root/readonly
= false
を設定しておく必要があります.
$ sudo runc start
$ sudo runc checkpoint # 別ターミナル
criu failed: type DUMP errno 0
log file: /run/opencontainer/containers/tmp/criu.work/dump.log
ぐぬぬ... dump に失敗してしまいました.
seccomp 対応の runC では, CRIU 側がまだ対応できていないのが原因でした.
とりあえず runC を seccomp 無効でビルドしてみます(runc の Makefile で BUILDTAG を編集する). また, runtime.json
での seccomp
セクションを削除しておきます.
seccomp 無効の runC で再度実行してみます.
$ sudo runc start
$ sudo runc checkpoint # 別ターミナル
# checkpoint/ ディレクトリにプロセスのダンプが書かれます.
$ sudo runc restore
Voila! プロセスのチェックポイント実行に成功しました!
To be continued...
TODO
- aobench の結果ファイルの回収(ネットワーク or stdout に流す?)
- checkpoint を異なるマシン間で試す.