DockerとLinux OSのリソース共有状況の調査

2015年6月9日(火)
森元 敏雄

DockerコンテナとベースとなるLinux OSとは、カーネルや様々なリソースを共有している。リソースを個別に保持するサーバ型仮想化と比較するとリソース消費量が少なく、1台のサーバ上でより多くの仮想マシンを起動させることが可能である。

コンテナ型仮想化のメリットはわかりやすいが、同時にこの特徴は、共有されているリソースをあるコンテナが大量に消費するような状況が発生した場合、ベースOSにも影響を及ぼす可能性があるという懸念を生じさせる。この懸念を払拭し問題点を明らかにするために、DockerコンテナからベースOSのリソースを消費させる試験を行い、その影響について検証した。

本連載で性能評価などを行ってきた過程で、Dockerの動作は(若干ではあるが)Linuxディストリビューションごとに異なることもわかっている。そこで今回は、LinuxディストリビューションによるDockerのリソース使用状況の差異についても合わせて調査を実施した。

調査対象としたLinuxディストリビューション

調査対象として選択したLinuxディストリビューションを表1に示す。Dockerに関しては、バージョンによる差異の発生を抑止するため、全て同一のバージョン(1.5.0, build a8a31ef)とした。

表1:検証に使用したLinuxディストリビューション

ディストリビューションカーネル選択した理由
CentOS 6.6 x86_64kernel-centos6 2.6.32-504.el6.x86_64カーネル 2.6系の挙動を検証する
CentOS 7.0 x86_64kernel-centos7 3.10.0-123.el7.x86_64カーネル 3.0系の挙動を検証する
Ubuntu Server 14.04 x86_643.13.0-46-genericDebian系とRed Hat系の挙動の差異を検証する

実行モジュールのカーネル差異による不具合の発生を抑止するため、検証を実行するDockerコンテナもベースOSと同じディストリビューションとバージョンで作成されたものを使用している。つまり、CentOS 6.6 x86_64での検証では、CentOS 6.6上で作成されたコンテナを使っているということだ。

調査対象項目および検証方法

調査対象に選定した項目と検証方法を表2に示す。その調査対象を選定した理由と、想定する状況や発生事象についても記載しておく。

表2:調査する項目と検証の方法

調査対象項目検証方法想定する状況・発生事象
コンテナ上のファイル格納方法Dockerコンテナを生成し、コンテナ内のファイルがベースOSのディスク上のどこに格納されているかを確認するLinuxディストリビューションごとに、使用するファイルシステムとファイルの格納場所に差異が存在するのではないか?
ディスク容量コンテナ内で大容量のファイルを作成するベースOSの空きディスク容量が枯渇することで、ファイル作成や書き込みが不能にならないか?
ベースOSと共用する領域が存在する場合に、大容量ファイルを作成する
inode数コンテナ内で大量にファイルを生成するベースOSのinodeが枯渇することで、ファイル生成が不能にならないか?
メモリ使用量コンテナ内でメモリを大量に使用するアプリを実行するベースOSの空きメモリ容量が枯渇することで、システムに異常が発生しないか?
プロセス数コンテナ内で子プロセスを大量に生成するベースOSのプロセス数の制限に抵触し、プロセスが生成できない状態にならないか?

では、表2の各調査項目について検証を見ていこう。

コンテナ上のファイル格納方法

Dockerコンテナ内のファイルは原則、仮想ストレージに格納される。その仮想ストレージの形式は、ストレージドライバによって選択が可能である。各ディストリビューションの、標準で利用可能および標準インストール時に選択されたストレージドライバは、表3のようになる。

表3

ディストリビューションストレージドライバ備考
CentOS 6.6 x86_64device-mapper(標準)
vfs
dockerのオプション定義ファイル(/etc/sysconfig/docker)で変更が可能
CentOS 7.0 x86_64device-mapper(標準)
vfs
Ubuntu Server 14.04 x86_64aufs(標準)
device-mapper
vfs
インストール方法によってdevice-mapeprが選択される場合もある
dockerのオプション定義ファイル(/etc/default/docker)で変更が可能

同じバージョンのDockerをインストールしても、ベースOSのディストリビューションによって異なるストレージドライバが選択される。さらにUbuntuでは、Dockerのインストール方法によって選択されるストレージドライバが変わる。この事象については、弊社の松井による記事に詳しく記載されている。

CentOS/Ubuntuのバージョンとインストール手順によるDockerバージョンとストレージドライバの差異 - Qiita

http://qiita.com/nmatsui/items/7dc75fa6af0adde0eeec

CentOS 6.6とCentOS 7.0は、標準インストールではストレージドライバにdevice-mapperを採用している。コンテナのベースイメージやコンテナ内の仮想ディスクイメージは、Sparseファイル内に格納されている。Sparseファイル内のデータの格納にはDevice-mapper Thin Provisioningを採用しており、重複排除などにより効率化された配置が行われている。詳細はレッドハットのクラウドエバンジェリストである中井氏による資料に記載されているので、ご一読をお勧めする。

CentOS 6.6

実際に構築してみると、CentOS 6.6とCentOS 7.0 ではマウントのされ方が異なっていた。CentOS 6.6ではコンテナ内のディスクはまず、ベースOSのフォルダ内にマウントされる。そのフォルダをデバイスにマッピングし、読み込み専用のベースイメージに重ねる形でマウントしている(図1)。この方法により、同一のベースイメージから複数のコンテナを生成し、その差分を個々に保存できる状況を実現している。Dockerコンテナ内のファイルは、ベースOS上のファイルシステムの一部となっているため、ベースOSからもアクセスが可能で、ファイル自体の操作も行える。

CentOS 6.6でのマウント方式

図1:CentOS 6.6でのマウント方式

CentOS 7.0

一方CentOS 7.0ではCentOS 6.6とは異なり、ベースOS上のファイルシステムにはマウントせず、Sparseファイル上のコンテナ用の仮想ディスク領域を直接、pool領域上にマウントしている(図2)。そのため、コンテナ内のファイルシステムに対するベースOS上からの直接操作はできなくなっている。

CentOS 7.0でのマウント方式

図2:CentOS 7.0でのマウント方式

前述の中井氏の資料に、Dockerコンテナ上のファイルシステムをベースOSからマウントする方法が記載されている。実際に試したところ、読み込みは行えたが、書き込みを行おうとするとエラーになった。さらにマウント後にコンテナ側でファイルの書き込み操作を行った場合、読み込み自体もエラーとなり、再マウントを行うまで解消されなかった。本操作自体が非推奨とされていることも納得である。

Ubuntu 14.04

Ubuntu 14.04のaufsは、device-mapperとはかなり構造が異なる。Dockerコンテナに提供するファイルシステムは仮想ディスクイメージではなく、旧来のlxcと同様にベースOSのファイルシステムの一部をchrootの機能で切り出して提供している。そのため、CentOS 6.6と同様にコンテナ内のファイルはベースOSからも操作が可能である。

Ubuntu 14.04でのマウント方式

(1)コンテナの内にファイルシステムのルート / の格納フォルダ

# cat/proc/self/mountinfo
44 23 0:40 / /var/lib/docker/aufs/mnt/[コンテナID] rw,relatime - auds none rw,si=303ed1ddc4bb38b3

(2)コンテナの内にで更新されたファイルを格納するフォルダ

# ls -1/var/lib/docker/aufs/diff/[コンテナID]
/var/lib/docker/aufs/diff/[コンテナID]

(3)Doclerコンテナのマウントイメージ

/(rootfs)
└ mount/var/lib/docker/aufs/mnt/[コンテナID] /
└ mount/var/lib/docker/aufs/diff/[コンテナID] /

※コンテナの / に対してベースOSのフォルダを重ねるようにマウント(union mount)している。

またUbuntu 14.04では、/etc/default/dockerのDOCKER_OPTSに「--storage-driver=devicemapper」を加えて再起動することで、ストレージドライバをdevice-mapperに切り替えられる。このように明示的にdevice-mapperを指定した際の挙動は、CentOS 7.0と同様であった。

ただし、実行中にDocker環境のストレージドライバを切り替えると、Dockerの設定ファイルに不整合が生じ、過去に利用していたコンテナが利用できなくなる。ストレージドライバを切り替える際の不整合を避けるには、必要なイメージやコンテナをdocker exportなどのコマンドで退避した後、Dockerの起動前に/var/lib/docker以下を全て削除する必要がある。

TIS株式会社

R&D部門である戦略技術センター所属。
金融系の大規模システム開発やプライベートクラウド開発環境の構築・運用の経験を生かし、OSS製品を中心としたの技術調査・検証を担当。
> TIS株式会社

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています