はじめに
gVisorとは、KubeCon2018でローンチが発表されたOpen Container Initiative (OCI)に準拠したコンテナのランタイム runsc
を含むプロジェクトのこと。
OCIについては、この記事 にわかりやすくまとめてある。
上記の記事にある図の runc
というものが、今デフォルトで利用されているランタイムで、 runc
の部分をよりセキュアに(ホストカーネルと隔離して)実行させようとしているのが runsc
。
どうやってホストカーネルと隔離するかは、gVisorのREADMEにまとまっている。要するにDockerアプリケーションからのシステムコールをgVisorが一度受け取り、それをホストカーネルに渡す仕組みになっている。
https://github.com/google/gvisor から引用
注意点としては、まだ動かないかもしれないけど、動かなかったら教えてね、くらいのふわっとした状況だということ。
ためしてみる
今のところ、Linuxでの動作しか保証していないようなので、Linuxの環境を作る。今回はGCEで Ubuntu 16.04 LTS を選んだ。
Ubuntu 18.04 LTSだと、Docker, Bazelが正式にサポートされてない。また Container-Optimized OSはDockerバージョンが17.03と、gVisorの推奨するDockerバージョンを満たしていない。
※いずれも2018/05/04時点
Dockerのインストール
Get Docker CE for Ubuntu | Docker Documentation
ドキュメント通りにコマンドを実行すればいい。
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https ca-certificates \
curl software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce
Bazelのインストール
Installing Bazel on Ubuntu - Bazel
こちらもドキュメント通り行う。
$ sudo apt-get install pkg-config zip g++ zlib1g-dev unzip python
$ curl -OL https://github.com/bazelbuild/bazel/releases/download/0.13.0/bazel
-0.13.0-installer-linux-x86_64.sh
$ chmod +x bazel
-0.13.0-installer-linux-x86_64.sh
$ ./bazel
-0.13.0-installer-linux-x86_64.sh
gVisorのビルド
Installation < 略
$ sudo apt-get install git
$ git clone https://gvisor.googlesource.com/gvisor gvisor
$ cd gvisor
$ bazel build runsc
<ビルドにめっちゃ時間かかる>
$ sudo cp ./bazel-bin/runsc/linux_amd64_pure_stripped/runsc /usr/local/bin
Dockerのruntimeに runsc
を追加
/etc/docker/daemon.json
を作成し、以下の内容を記入。
{
"runtimes": {
"runsc": {
"path": "/usr/local/bin/runsc"
}
}
}
sudo systemctl restart docker
でdockerデーモンを再起動し、設定を反映。
runtimeに runsc
を設定して実行
$ sudo docker run --runtime=runsc -it ubuntu /bin/bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
a48c500ed24e: Pull complete
1e1de00ff7e1: Pull complete
0330ca45a200: Pull complete
471db38bcfbf: Pull complete
0b4aba487617: Pull complete
Digest: sha256:c8c275751219dadad8fa56b3ac41ca6cb22219ff117ca98fe82b42f24e1ba64e
Status: Downloaded newer image for ubuntu:latest
<コンテナ内>
root@e1d3ad2716a8:/# echo hello
> hello
プロセスを見てみると、containerdはrunscを起動させているっぽい。一応 立ち上げたubuntuコンテナで、for文など試してみたけど問題なく動いた。
$ ps -auwx | grep docker
...
root 18501 0.0 0.0 9060 3760 ? Sl 16:51 0:00 docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/e1d3ad2716a8e38c72fc5c8091e7bf39b8047301a512d66a989537e2b11a5d4b -address /var/run/docker/containerd/docker-containerd.sock -containerd-binary /usr/bin/docker-containerd -runtime-root /var/run/docker/runtime-runsc
gVisorのコードについて
https://github.com/google/gvisor/tree/master/runsc/cmd
ここでOCIに準拠したruntimeのインタフェースを定義している。
https://github.com/google/gvisor/tree/master/pkg/sentry
このあたりでシステムコールまわりの処理をしているっぽい。
セキュリティについて #1
他にセキュリティを強固にするためのランタイムに Kata Containersというものがある。(1pagerはこちら
これはそもそもVM上にあるコンテナが対象で、コンテナごとに軽量カーネルをつくる。超軽量なので、軽量カーネルなしのコンテナと同じパフォーマンスが出るらしい。 <100ms boot time
と書いてあるので確かに爆速だ。
コードは見れていないが、VMと同程度のセキュリティが担保されそう。
セキュリティについて #2
2018年のDocker・Mobyという須田さんのプレゼンにもセキュリティについて触れている。 P.55から。 資料自体が、とても面白い。
runcをrootlessにするという考えもあるという話。
今回調べた結果、すでに色々なアプローチをとられていることがわかったので、どこかのタイミングでまとめたい。
Podmanというrootlessのアプローチのプロダクトも出ている。
感想
最近はもはや何かを実行するときはコンテナの中で実行することが多い。ローカルには基本的に言語の実行環境をインストールせず、コンテナで実行環境のバージョンなどを指定して実行するようになった。
もちろんanyenvなどを使ってバージョン管理する方法もあるけど、ローカルの依存関係が複雑になっていくのが嫌だ。
あとコンテナにしておけば、k8sで簡単に並列処理できるし。
その反面、使うコンテナに含まれるセキュリティホールについては意識していなかったので、gVisorの需要は高い。
gVisorがMacに対応されたら、デフォルトのランタイムをrunscに変えるだろう。