Dockerコンテナのパフォーマンス劣化とチューニング
テスト5:Apacheのチューニングを実施する
これまでにDockerコンテナの実行環境や構成に対して様々な対策を施し、レスポンスの改善や問題点を確認してきたが、新たなアプローチとしてコンテナ内のアプリケーションの設定によるチューニングによる性能改善を検証する。ここでは、Redmineを稼働させる為に使用しているApacheおよびRuby on RailsアプリケーションをApacheと連携させるPhusion Passengerのチューニングに着目してみる。
コンテナ自体はテスト1と共通である。チューニングはRedmineコンテナに接続し、コマンドラインから直接設定を変更した。変更点は、プロセスの並行処理可能数の向上を目的として、Apacheの最大子プロセス数の上限とPassengerの最大プロセス数の上限の増加である。
設定項目 | 変更前 | 変更後 |
---|---|---|
MaxSpareServers(mpm_prefork_module) | 10 | 25 |
MaxClients(mpm_prefork_module) | 150 | 200 |
PassengerMaxPoolSize | 6 | 15 |
この状態で再度負荷テストを行う。結果を表9に示した。
作業 | 1分間のオペレーション | 平均(ミリ秒) | 中央値(ミリ秒) | 90%Line(ミリ秒) | 最小値(ミリ秒) | 最大値(ミリ秒) | Error% | スループット | KB/sec |
---|---|---|---|---|---|---|---|---|---|
アクセス | 2000 | 137 | 22 | 279 | 10 | 2945 | 0.00 | 28.6 | 133.9 |
ログイン実行 | 2000 | 327 | 235 | 610 | 58 | 3209 | 0.00 | 28.6 | 175.8 |
Projectへ遷移 | 2000 | 200 | 39 | 431 | 17 | 4222 | 0.00 | 28.3 | 156.5 |
チケット作成 | 2000 | 138 | 42 | 310 | 19 | 3713 | 0.00 | 28.4 | 149.5 |
平均 | 2000 | 200.5 | 84.5 | 407.5 | 26 | 3522.25 | 0.0 | 28.48 | 153.93 |
テスト5で取得できたiostatの最大値
avg-cpu: %user %nice %system %iowait %steal %idle 23.42 0.00 3.17 13.57 0.00 59.83 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sda 0.00 3.33 0.33 86.00 16.00 3096.33 72.10 1.37 15.92 14.00 15.93 11.32 97.77 dm-1 0.00 0.00 0.33 75.67 16.00 3095.83 81.89 1.39 18.25 14.00 18.26 12.86 97.77 dm-2 0.00 0.00 0.67 94.33 2.67 3076.00 64.81 3.95 41.39 7.00 41.63 9.11 86.57 dm-4 0.00 0.00 0.00 19.33 0.00 1021.33 105.66 1.20 62.28 0.00 62.28 9.83 19.00 dm-5 0.00 0.00 0.67 74.33 2.67 2430.67 64.89 3.08 40.85 7.00 41.16 13.13 98.47
エラー割合は0%となり、「90%Line」の値も大幅に改善されている。Docker環境自体が変更出来ない場合でもプロダクト側の設定をチューニングすることで、パフォーマンスの改善が図れることがわかった。
ただしプロセスを増やした場合、必然的にこれまでテストを実施してきたコンテナと比べてホスト側のCPUやメモリリソース等をより多く消費してしまうこととなる。リソース量に上限を設けたければ、docker runコマンドの「-c」や「-m」オプションが有効だ。
まとめ
テスト中に得られた値と比較するため、Dockerコンテナのディスクイメージ格納用の領域として使用したハードディスクそのものの性能を測定してみた。
[root@host_server~]# dd if=/dev/zero of=/dev/sda bs=1MB count=1024 1024+0 records in 1024+0 records out 1024000000 bytes (1.0 GB) copied, 3.90083 s, 263 MB/s
ddコマンドによる単純なシーケンシャルwriteだが、1GBのファイルを一つ作成するにあたって263MB/secの書き込み速度が出ている。実際にテスト1中に取得したiostatの結果と比べて見よう。
avg-cpu: %user %nice %system %iowait %steal %idle 43.82 0.00 5.27 7.56 0.00 43.35 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sda 0.33 1.67 3.00 140.67 102.67 3229.83 46.39 1.04 7.22 10.33 7.15 5.77 82.97 dm-1 0.00 0.00 3.33 110.67 102.67 3229.50 58.46 1.05 9.25 13.10 9.13 7.27 82.87 dm-2 0.00 0.00 1.67 276.33 26.67 3328.00 24.13 1.12 4.03 19.40 3.93 2.81 78.23 dm-3 0.00 0.00 1.33 264.33 5.33 3340.00 25.18 1.25 4.70 9.25 4.67 3.16 83.83
取得した値を見るとディスクの使用率(%util)は非常に高いが、一方で書き込みデータ量(wkB/s)はディスク自体の性能から見ると少ないことがわかる。つまり、ハードディスクの物理的な性能不足ではなく、データ量に比べてI/Oリクエストの処理件数が非常に多いことにより、処理性能の劣化が発生していると推察される。
これまでの性能対策の結果のまとめとして、Redmineに対する処理性能の評価を行った「90%Line」「Error%」「KB/sec」を各テストの平均値を比較したい。
90%Line(ミリ秒) | Error% | KB/sec | |
---|---|---|---|
テスト0:ベアメタル環境 | 74 | 0.00% | 94.75 |
テスト1:Redmineコンテナ立ち上げてテストを行う | 26704 | 9.31% | 73.1 |
テスト2:DockerのData Spaceを別の物理ディスクに置き換え、テストを行う | 18052 | 5.66% | 96.43 |
テスト3: コンテナで利用する一部のファイルをホストOSへ切り出してテストを行う | 156 | 0.00% | 58.08 |
テスト4:コンテナをRedmineとMySQLの2つに分離してテストを行う | 33793 | 20.87% | 54.18 |
テスト5:Apacheのチューニングを実施し、テストを行う | 407 | 0.00% | 153.93 |
まず、レスポンスタイムの平均値である90%Lineの数値を確認する。
テスト4のコンテナをRedmineとMySQLの2つに分離してテストを行ったケースが一番低いスコアとなっている。今回のケースではDiskの性能が十分に出ていないところにコンテナを分割で配置し、コンテナ間通信のネットワーク負荷も発生させたことで、さらにレスポンスが悪化した形になっている。
テスト2のDockerのファイルシステムに物理デバイスを割り当てる方式だが、Dockerが標準で利用するLoopbackデバイスにdevicemapperとしてファイルシステムをマウントする方式に比べて、30%以上の改善が見られる。ファイルによる仮想ディスクと比較して、大幅に性能が改善されていると考えられる。
テスト3では、比較的IOの高いファイルをホストOS側へ配置することによって、Dockerのファイルシステム(devicemapper)の影響を受けていない。iostatの結果からもわかるように、他のテスト結果に比べて秒間Write回数が多いのにも関わらず、Diskビジーの割合が低くベアメタル環境に近いレスポンスタイムとなっている。
次にリクエストがエラーとなったError%を確認する。
コンテナを分離したテスト4のケースが、一番高いエラー率を示した。レスポンスタイムの悪化からタイムアウトなどのエラーが多発したことが原因だと考えられる。テストケース2は、90%Lineからもレスポンスタイムの改善が見受けられ、その改善によりエラー発生率が約半減している。テスト3、テスト5は、ともにベアメタルと比較するとレスポンスタイムの若干の劣化はあるものの、エラー発生率は0%となっており、Docker環境においても環境やプロダクトのチューニングにより、ベアメタルと同等の性能を確保できることがわかる。
今回の検証を終えて得られた筆者の結論は、以下のようになる。
『Dockerコンテナは、設定やチューニング次第で十分処理性能を確保できる』
Dockerコンテナのパフォーマンスを引き出す上でボトルネックとなるのは、予測していたDiskIO速度の低下であった。さらにコンテナ間の通信速度も、性能劣化の一因となることも判明した。DiskIOに対しては『Dockerコンテナ用ファイルシステムを個別ストレージにする』方法や『DiskIOが多い領域を外部ファイルシステムに配置する』方式が有効である。
さらにDiskIOがボトルネックになる可能性があることを考慮し、コンテナ内のプロダクトのチューニングを行うのも非常に有効だ。コンテナ間通信のネットワーク負荷による性能劣化に関しては、必要な機能を一つのコンテナにまとめることで解消が可能である。
ただ、いずれの方式もDockerの標準インストール状態からは乖離するため、利用できるハードウェア環境や実行するプロダクトに応じて、環境構築を行う必要がある。またこれ以外にも、Docker専用に開発され、性能対策が施されているRed Hat Enterprise Linux 7 Atomic Hostなどの製品の利用も一つの選択肢である。
現在盛んに利用されているサーバ仮想化環境やパブリッククラウドも、発表された当初はビジネスシーンで使うには性能が不足で、信頼性に対してリスクが高いと考えられていた。しかし昨今のクラウドの性能や信頼性の向上で、クラウドの利用は非常に盛んとなっており、全てのシステムをクラウドに移行した、又は移行を決定した企業も多く出てきている。
そしてDockerも、これらの技術と同様の進化が起きるだろう。現状では様々な課題があるDockerだが、今後は利用が拡大し、性能や信頼性のさらなる向上が期待される。今後もDockerと周辺技術の利用を続け、より良い利用方法や安定稼働させる環境づくりなど様々な形でトライして行きたい。