読者です 読者をやめる 読者になる 読者になる

$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

Dockerが利用しているAUFSとLXC

tech operation

最近Dockerをいろいろ触ってみていて以下の様な記事を書いたりしました。

とは言え僕自身は仮想化やファイルシステムについて全く知識がなくて、LXCとAUFSっていうのを使っていい感じになってるんでしょっていう雑な知識だけでDockerを使っていたので、もうちょっと調べようと思って調べてみました。

このレイヤーに関してはあまり詳しくないので、間違いがあったら指摘していただけると嬉しいです。

Docker

https://github.com/dotcloud/docker/blob/master/README.md#under-the-hood この辺を見ると以下のように書いてあります。

Under the hood, Docker is built on the following components:

・The cgroup and namespacing capabilities of the Linux kernel;
・AUFS, a powerful union filesystem with copy-on-write capabilities;
・The Go programming language;
・lxc, a set of convenience scripts to simplify the creation of Linux containers.

なるほど、とりあえずdockerは

  • Goで動いてて
  • cgroupとかnamespaceみたいなLinux kernel機能使って
  • AUFSというunion filesystemを使ってて
  • LXCっていうやつでLinux containersを作ってコンテナを立ちあげている

という感じなんですね。まあよくわからないけどまあなんかいい感じにしてるんでしょう。

というわけでとりあえずAUFSとLXCあたりを調べてみることにします。

AUFSとDocker

AUFSってなんなの?

まずAUFS(というかunion filesystem)ってなんなのかというところですが、Linuxキーワード - AUFS とは:ITproや、Docker = LXC + aufs + GitHub Culture - teppeis blogあたりに書いてあったことがとりあえずは導入にはわかりやすかったです。

異なるファイルシステムのファイルやディレクトリを透過的に重ねて、ひとつのファイルツリーを構成できるファイルシステム

あと、実際にAUFSを利用している例としてはOSのLiveCDとかが分かりやすいですね。

  • CD-ROMに記録してあるOS部分をreadonlyとして利用
  • メモリ空間にwritableなfile systemを用意して、それを重ねあわせる
  • ファイルシステムに変更があった場合はメモリ空間の方を変更して、書き込みができているように見せる

その他にも仙石浩明の日記: NFS と AUFS (Another Unionfs) を使って、ディスクレス (diskless) サーバ群からなる低コスト・高可用な大規模負荷分散システムを構築するのような使い方をされています。

さらにちゃんと調べるにはhttp://aufs.sourceforge.net/あたりを読んでおくと良さそうだけど、難しそうなので読んでません。

DockerでのAUFS利用

とはいえこれを使ってDockerではどうやってcommitとか差分管理を実現しているの?よくわからん!とか言ってたら、r7kamuraくんが参考情報をくれました。






まずこの図を見ることでわかったような気持ちになりました。http://docs.docker.io/en/latest/terms/layer/参照。

  • それぞれのImageやcommitの階層がAUFSの一つの層として扱われている
  • コンテナを立ち上げるとその層(最上段の層)がread+writeな層になり、その下の層はread-onlyな層になる
  • どの層の上に乗っているかはcommit sha1とかで管理している?
  • commitはコンテナの一番上のread+write層をread-onlyにする行為に見える。さらにそこからコンテナを使うとその上にread+writeの層を一層かぶせるように見える

こういう感じで差分管理を実現しているのかなーと思いました。docker pullするとdependency layerとか出てきたり、並列にダウンロード出来るのもこの辺のlayerがあるおかげっぽく見えますね。

更にunion filesystemの仕組みを知るにはUnionMountとUnion-type Filesystem(1) - O'Reilly Japan Community Blogあたりが非常にわかりやすそうでした。

LXCとDocker

LXCってなんなの?

まずLXCってなんなのと思って、一次ソースっぽいところを見ると、

http://linuxcontainers.org/

LXC is a userspace interface for the Linux kernel containment features.
Through a powerful API and simple tools, it lets Linux users easily create and manage system or application containers.

って書いてありました。まだなんなのかよくわからないですね。ユーザ空間のインターフェースで、なんかアプリケーションのコンテナとかを作ったり管理したりするのを簡単にできるみたいです。


まあとりあえず日本語の解説見たいと思っていたら、仮想化やLXCについて分かりやすいスライドがありました。Lxc で始めるケチケチ仮想化生活?!
仮想化についてはp5が分かりやすく、p6以降にLXCについて分かりやすい説明がされています。

それによると以下のようなイメージでした。

  • LXCはコンテナ型仮想化
  • 複数のユーザ空間を作ることで、ユーザプロセスから見えるリソースを分割する
  • ホストOSとゲストOSのkernelは共通
  • ホストOSからはゲストOSのプロセスがそのまま見える

さらに詳しく知りたい場合はLXC入門 - Osc2011 nagoyaあたりのスライドが分かりやすいです。また実例としてさくらVPSでLXCを動かすみたいなのもありました(さくらVPSでLXCを使って安価に複数台構成を実現する - orangain flavor)。

DockerでのLXC利用

Dockerの場合は結局管理しているAUFSのファイルシステムとLXCを組み合わせて、Dockerコンテナを作っているように見えます。LXCを使えば、ユーザ空間の分離ができるので、コンテナごとにシステムの分離が出来るというイメージなのかな。あとcgroupもできるのでリソース制限とかも簡単に出来るっぽい?

さらに詳しく知るにはDocker を読む - Kato Kazuyoshiあたりを読んだり、ソースを読んだほうが良さそうでした。

疑問

一つ疑問として、kernelをホストOSとゲストOSで共有するなら、それらのOSでkernelのversionが違った場合にどうなるのかというものがありました。





感覚的にはlxc-startとかその辺がインターフェースとして使われているので、その仕様を満たせばkernelのversionが違っても問題ないという感じなんですかね。

まとめ

今回はDockerで使われているAUFSやLXCなどについて調べてまとめてみました。このへんの内容初めて調べたので間違っているところも多いかもしれません。おかしなところがあれば指摘いただけると嬉しいです。

あともしかしたら id:y_uukiがさらにゲストOSがLXCでどうやって作られるかとか書いてくれるかもしれません。