より深くDockerを知る 2

ベアメタル環境とDockerコンテナ環境の性能比較

コンテナ環境とベアメタル環境の差異前回は、Docker向け軽量Linux OSの主要3製品の比較を行った。Dockerを利用した環境の構築は、構築済みコンテナなどの利用により、比較的容易に行える。これは便利ではあるが、一方でコンテナ型仮想化環境には既存のベアメタル環境との差異がある。コンテナ型の仮想

佐藤 司, 森元 敏雄

2015年3月27日 16:00

コンテナ環境とベアメタル環境の差異

前回は、Docker向け軽量Linux OSの主要3製品の比較を行った。Dockerを利用した環境の構築は、構築済みコンテナなどの利用により、比較的容易に行える。これは便利ではあるが、一方でコンテナ型仮想化環境には既存のベアメタル環境との差異がある。

コンテナ型の仮想化は軽量でリソース消費量が少ないが、コンテナ型仮想化環境にも管理レイヤは存在し、その上でコンテナが稼働している以上、どうしてもベアメタル環境に比べて性能劣化が発生することが予測される(図1)。

Dockerコンテナ管理レイヤ

図1:Dockerのコンテナ管理レイヤ

今回は、同一スペックおよび同一プロダクトを利用し、構築したDocker環境とベアメタル環境上で負荷テストを実施することで、両者の性能差を比較検証する。処理性能やリソース負荷状況などの観点で比較し、その差異を表やグラフにまとめているので、ご一読いただきたい。

まずは環境をご紹介する。今回は、図2のようなテスト環境を用意した。

Dockerコンテナとベアメタルを比較するテスト環境

図2:Dockerコンテナとベアメタルを比較するテスト環境

検証環境

ベアメタル環境、Docker環境の検証の性能を同一にするため、1台の物理サーバを使用し、起動(ブート)するHDDを選択することで両環境を切り替えるようにした。

単一のサーバを用いて、起動するHDDの選択で環境を切り替える

図3:単一のサーバを用いて、起動するHDDの選択で環境を切り替える

用意したサーバのスペックを、表1に示した。

表1:検証に用いた物理サーバのスペック

CPU Intel(R) Core(TM) i7 870 @ 2.93GHz
Memory 4GB
Swap 8GB
HDD1 Western Digital 1TB (SATA3 7200rpm)
HDD2 Western Digital 1TB (SATA3 7200rpm)
NIC1 インターネットへ接続可能なネットワーク
NIC2 負荷発生端末(JMeter)とのみ接続可能なクローズドなネットワーク

ベアメタル環境、Docker環境の構成も、合わせて表2に示した。

表2:ベアメタル、Docker環境のソフトウェア構成

環境 ベアメタル環境 Docker環境
OS CentOS 6.6(64bit) CentOS 6.6(64bit)
Docker - Docker 1.4.1
アプリケーション Redmine 3.0.0 Redmine 3.0.0(コンテナで配置)
RDB MySQL 5.5.41 MySQL 5.5.41(コンテナで配置)

この環境に負荷発生端末上のJMeterから検証環境上のRedmineへのアクセス負荷を発生させ、処理性能と負荷状況を測定した。

テストシナリオ

今回は以下の条件で負荷テストを実施した。

JMeter上から実行したオペレーションは以下となる。

1.参照オペレーション

  1. Redmineのログイン画面へアクセス
  2. ユーザ名とパスワードを用いてRedmineにログイン

本オペレーションでは、原則、DBやディスクには参照の処理が行われる。CPU、ネットワーク、ディスクに平均的に負荷を発生させることを目的としている。

2.更新オペレーション

  1. Redmineのプロジェクトに対して新しいチケットを1件作成
  2. 表題と内容を記載し登録

本オペレーションでは、チケットの登録が行われるため、ディスクの更新が発生する。データ量は小さいがDB、ディスクへの負荷を発生させることを目的としている。

JMeter上から発生させる負荷量は以下となる。

  1. 低負荷
    参照、更新のオペレーションを100件/60秒の間隔で実行する
    テスト時間は60秒間で行い、それを複数回繰り返して平均を取得する
  2. 高負荷
    参照、更新のオペレーションを1000件/60秒の間隔で実行する
    テスト時間は60秒間で行い、それを複数回繰り返して平均を取得する

検証

上記の負荷テストを実施し、測定された結果は以下のとおりだ。

低負荷時の測定結果

まず低負荷時の状態として、参照、更新のオペレーションを100件/60秒の間隔で実行した結果は以下となる。

表3:ベアメタル環境 – 低負荷時

作業 1分間のオペレーション 平均
(ミリ秒)
中央値
(ミリ秒)
90%Line
(ミリ秒)
最小値
(ミリ秒)
最大値
(ミリ秒)
Error% スループット KB/sec
アクセス 100 10 10 11 8 14 0.00% 1.7/sec 7.2
ログイン実行 100 93 91 107 67 200 0.00% 1.7/sec 13.7
Projectへ遷移 100 18 18 20 16 28 0.00% 1.7/sec 8.5
チケット作成 100 20 19 23 17 32 0.00% 1.7/sec 9.1
平均 100 35.25 34.5 40.25 27 68.5 0.00% 1.7/sec 9.63

表4:Docker環境 – 低負荷時

作業 1分間のオペレーション 平均
(ミリ秒)
中央値
(ミリ秒)
90%Line
(ミリ秒)
Min
(ミリ秒)
Max
(ミリ秒)
Error% Throughput KB/sec
アクセス 100 11 11 12 10 20 0.00% 1.7/sec 7.0
ログイン実行 100 97 92 110 76 199 0.00% 1.7/sec 13.1
Projectへ遷移 100 22 22 24 18 34 0.00% 1.7/sec 8.4
チケット作成 100 18 19 20 18 28 0.00% 1.7/sec 9.0
平均 100 37 36 41.5 30.5 70.25 0.00% 1.7/sec 9.38

表3、表4で特に注目すべきは「90%Line」と「KB/sec」の箇所だ。「90%Line」は、発行したリクエストの90%が、何ミリ秒で応答するかを示す値であり、実際にユーザが体験するレスポンスタイムに最も近い。また「KB/sec」は、サーバからJMeter端末への通信速度を表しており、1秒あたりの転送量が何KB(キロバイト)だったのかを表している。両者の結果をグラフ化したものが、図4、5だ。

低負荷時の「90%Line」を比較(低いほうが高性能)

図4:低負荷時の「90%Line」を比較(低いほうが高性能)

低負荷時のデータ転送量を比較(高いほうが高性能)

図5:低負荷時のデータ転送量を比較(高いほうが高性能)

2つのグラフから明らかなように、ベアメタル環境、Docker環境の差異はそれほど大きくなく、軽い処理であれば、性能面での影響は少ないと考えられる。

高負荷時の測定結果

続いて、高負荷時の状態として参照、更新のオペレーションを1000件/60秒の間隔で実行した結果を、表5、表6に示す。

表5:ベアメタル環境 – 高負荷時

作業 1分間のオペレーション 平均
(ミリ秒)
中央値
(ミリ秒)
90%Line
(ミリ秒)
最小値
(ミリ秒)
最大値
(ミリ秒)
Error% スループット KB/sec
アクセス 1000 15 10 20 8 293 0.00% 16.6/sec 70.9
ログイン実行 1000 119 94 191 75 675 0.00% 16.6/sec 135.2
Projectへ遷移 1000 28 19 44 15 404 0.00% 16.5/sec 83.5
チケット作成 1000 29 20 41 17 438 0.00% 16.5/sec 89.4
平均 1000 47.75 35.75 74 28.75 452.5 0.00% 16.55/sec 94.75

表6:Docker環境 – 高負荷時

作業 1分間のオペレーション 平均
(ミリ秒)
中央値
(ミリ秒)
90%Line
(ミリ秒)
最小値
(ミリ秒)
最大値
(ミリ秒)
Error% スループット KB/sec
アクセス 1000 580 740 999 1 1316 26.40% 16.4/sec 51.6
ログイン実行 1000 1193 1562 1988 0 2366 31.50% 16.1/sec 90.4
Projectへ遷移 1000 1065 1450 1883 1 2295 31.60% 16.2/sec 56.8
チケット作成 1000 1031 1450 1875 1 2298 34.40% 16.2/sec 59.4
平均 1000 967.25 1300.5 1686.25 0.75 2068.75 30.98% 16.23/sec 64.55

高負荷状態では、大きく差が生じる結果となった。レスポンスタイムの指標である「90%Line」で見ると、Docker環境はベアメタル環境と比較してなんと20倍以上の劣化が起きていた。

さらにレスポンスのタイムアウトの発生率(Error%)も、ベアメタル環境が0%であったのに対し、Docker環境は平均30%とかなり高い値を示した。これは、実際に運用していた場合、60秒間にアクセスした1000人のうち300人にアクセスエラーを返しているということになる。

1000件/60秒というアクセス頻度は、通常のWebサーバでCore i7程度のCPU性能があればそれほど高負荷とは言えない状況である。この結果からは、Docker環境を本番環境として利用することは厳しく、何らかの対策が必要だと考えられる。

高負荷時のデータも同様にグラフにしたので、確認していただきたい。

高負荷時の「90%Line」を比較(低いほうが高性能)

図6:高負荷時の「90%Line」を比較(低いほうが高性能)

高負荷時のデータ転送量を比較(高いほうが高性能)

図7:高負荷時のデータ転送量を比較(高いほうが高性能)

低負荷の状態では、ベアメタルと大きな性能差は発生しないDockerコンテナ環境であるが、高負荷状態となると、著しく性能劣化することが見て取れる。

Diskの負荷を検証する

ここまではJMeterを利用して主にレスポンスやネットワークについて見てきたが、Diskの状況についても測定を行っている。今回は、測定にMuninを用意してDisk負荷状況を監視した。

ベアメタル環境でのDisk負荷状況

MuninによるDisk負荷の監視(ベアメタル環境)

図8:MuninによるDisk負荷の監視(ベアメタル環境)

図8の青枠で囲まれている部分が低負荷のテストシナリオを、赤枠で囲まれているところが高負荷のテストシナリオを実施した部分だ。

どちらも負荷をかけた時にはRead I/O Wait timeが跳ね上がっている、筆者はこのテストを実施するまではRead I/O Wait timeが性能のボトルネックになり得ると予想していたが、実際にはベアメタル環境であれば1000アクセス+1000書き込み/60秒程度までなら、そこまでの劣化は発生しないようだ。

Docker環境でのDisk負荷状況

MuninによるDisk負荷の監視(Docker環境)

図9:MuninによるDisk負荷の監視(Docker環境)

図9はDocker環境での結果で、同じく青枠が低負荷、赤枠が高負荷のテストシナリオを実施した結果だ。図8とは縦軸のスケールが異なる点に注意しよう。

測定結果のグラフを見ると、ベアメタルより負荷が少ない状況となっている。その一方でHTTPレスポンスはリクエストの30%がエラーとなっており、「422:Unprocessable Entity」や「502:Bad Gateway」などが発生している。

今回のDiskの負荷状況の測定だが、Dockerを稼働させたベースのCentOS上で測定している。そのため、Disk I/Oの負荷は標準設定時に利用されるDockerコンテナのファイルシステム(CentOS6.6はdevice-mapper)部分がボトルネックとなるであろうと予想したが、実際にはベースOS側には波及することがなかったため図9のように負荷が少なかったと推察される。

まとめ

今回の検証結果から、低負荷時やピーク負荷が予想できる場合であれば、Dockerコンテナを利用したシステムでもベアメタル環境と遜色ないパフォーマンスが発揮されることがわかった。しかし高負荷時になると、やはりベアメタル環境の安定性に分がある。とはいえ、Docker環境でも対策がないわけではない。挙げられる対策といえば、IO負荷が高いファイル等はコンテナの外のファイルを使う手法や、負荷分散のために分散システムとする手法、障害対応力を上げるためのコンテナのクラスタリングなど、できることはたくさんある。また、このようなDockerの弱点をカバーするために、各社こぞってDockerのツールを作成、改善しているところだ。

次回以降では、今回の性能劣化の原因と推察されるDockerのファイルシステムについて検証を行い、原因の分析を行うとともに、性能改善の対策と効果についても検証し、理解を深めていきたい。

追記

CentOS 6.6環境でのDockerがデフォルトで利用するファイルシステムを「AUFS」と記載しておりましたが「device-mapper」の誤りでした。ご指摘くださった皆様ありがとうございました。お詫びして訂正いたします。

次々回の連載では、CentOS 6系でDockerコンテナを標準で利用されるdevice-mapperで発生する問題点とその対策について公開を予定しております。

<編集部より>記事内容に誤りがあったため修正しました。(2015.03.30)

この記事のキーワード

この記事をシェアしてください

人気記事トップ10

人気記事ランキングをもっと見る