0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

runc・gVisor・Kata+Cloud Hypervisor・cchv+Cloud Hypervisorを、同じPostgreSQLとnginxで比べた

0
Last updated at Posted at 2026-11-01

顧客のデータベースを、1つずつ専用のmicroVMの中で動かしています。「それにいくらかかるのか」を知るために、4つのランタイムで同じPostgreSQLと同じnginxを、1台のマシンで、同じ制限・同じ負荷で動かして測りました。

4つのうちのcchvは、自作です。containerd-cloudhypervisorの略で、コンテナごとに専用のCloud HypervisorのmicroVMを作るランタイムです。設定も自分で決めています。その点を頭に置いて、数字を読んでください。測定のスクリプトは公開しています(KoedoDB/cchvの bench/runtime-comparison)。同じ手順で再現できます。

何を比べたか

ランタイム 中身
runc Dockerの既定。ホストのカーネルの上のコンテナ。基準。
gVisor(runsc、release 20261019.0) コンテナとホストの間に置くユーザー空間のカーネル。既定の設定。
Kata Containers 4.3.1(Cloud Hypervisor) コンテナごとに1つのmicroVM。Kata自身の設定(ファイルはvirtio-fs)。
cchv v0.4.3(Cloud Hypervisor) コンテナごとに1つのmicroVM。ルートファイルシステムは読み取り専用のイメージ、データはブロックデバイス。

マシンは、借りている専有サーバーです。Xeon E3-1270 v6(4コア8スレッド)、32 GB、NVMe 2本のRAID1。PostgreSQL 18.6とnginx 1.29を、それぞれコンテナで、マシン本来のDockerには触れない2つ目のDockerの上で動かしました。

公平にするために

最初の測定は公平ではなく、やり直しました。効いたのは2つです。

  • CPUをそろえる。 PostgreSQLは3 CPU、nginxは2 CPU(quota)を、4つ全部に与えた。
  • VMの大きさ。 microVMは、コンテナの制限の上に、自分の分のオーバーヘッドを足します。実際のVMの大きさは、毎回、ハイパーバイザーのコマンドラインから確かめ、結果と一緒に記録しました。Kataは、制限に必ず1 vCPUを足し、外から変えられません。同じ3 CPUを与えると、KataのVMは4 vCPUで、cchvの3 vCPUより1つ多くなります。そこで、Kataは両方の形で載せます。
    • CPUをそろえる(VMは1 vCPU大きい)。 コンテナ3 CPU、VMは4 vCPU。追加の1 vCPUはコンテナの制限の外にあり、ゲストのカーネルがネットワークとI/Oに使えます。Kataに有利です。
    • VMの大きさをそろえる。 コンテナの制限を2 CPUに下げ、VMをcchvと同じ3 vCPUにする。VMは同じ大きさですが、Kataはコンテナが使えるCPUがcchvより1つ少なくなります。Kataに不利で、cchvがよく見えます。どちらの行も中立ではありません。

Kataの本当の値は、2つの行の間にあります。数字は、すべて3回の中央値です。

PostgreSQL

pgbench、16クライアント、スケール100。tpcb は書き込み(WALとデータファイル)、select は読み取りだけ、commit は1クライアントができるだけ速くコミットし続ける負荷です。

tpcb tps tpcb p99 select tps commit tps
runc 4,992 44.4 ms 32,674 4,933
gVisor 1,995 37.1 ms 12,454 3,449
Kata、3 CPU(VMは4 vCPU) 4,127 19.9 ms 28,050 3,851
Kata、2 CPU(VMは3 vCPU、cchvと同じ) 2,825 35.5 ms 18,790 3,712
cchv 3,966 8.8 ms 27,282 3,550
  • cchvは、データベースを専用のVMに入れたまま、runcのスループットの約80%に届きます。gVisorは、書き込みも読み取りも約40%です。
  • VMの大きさをKataと同じにした場合(Kataは自分の分に1 vCPUを足すので、コンテナのCPUが1つ少なくなる。PostgreSQLでもnginxでもKataに不利な行です)で、かつKataのファイルがvirtio-fs(既定)のとき、cchvは約1.4倍速いです。この差の多くはファイルの経路の差で、次の節のとおり、Kataにブロックデバイスを渡すと縮みます。CPUをそろえた場合(VMはKataの方が1 vCPU大きい)と比べると、スループットはKataが数%上です(書き込み4%、読み取り3%、コミット8%)。一方、書き込みのp99は、cchvがKataの半分以下(8.8 msと19.9 ms)です。
  • 書き込みテストのp99は、cchvが最も低いです。
  • 残りの20%の行き先: コンテナの中でUnixソケットで読むと、cchvはruncと並びます。差は、VMに入るネットワークの経路にあります(読み取りで約12%)。キューの数、コアのスケジューリング、TAPのキューの規則を調べましたが、どれも動かせませんでした。

Kataにブロックデバイスを渡したとき

cchvはデータベースにブロックデバイスを渡します。Kataの既定はvirtio-fsです。差のどれだけが経路で、どれだけがVMかを見るために、Kataのデータをvirtio-blk(O_DIRECT)にして測り直しました。この記事の他の表と同じ条件(cchv v0.4.3、3回の中央値、nginxは50接続)で、Kataは両方の大きさです。コンテナのCPUをそろえた行(VMは1 vCPU大きい)と、VMの大きさをそろえた行(コンテナのCPUが1つ少ない)です。上と同じく、どちらの行も中立ではありません。VMの大きさは、毎回ハイパーバイザーのコマンドラインで確かめました。

PostgreSQL tpcb tps select tps commit tps nginx 1 KB rps nginx 100 KB rps nginx 10 MB rps
Kata、virtio-blk、CPUをそろえる(コンテナはPostgreSQL 3 CPU・nginx 2 CPU、VMは4と3 vCPU) 4,588 27,299 3,571 51,322 1,742 14
Kata、virtio-blk、VMの大きさをそろえる(コンテナはCPUが1つ少なく、PostgreSQL 2 CPU・nginx 1 CPU、VMは3と2 vCPU) 3,152 18,732 3,579 48,401 1,750 15
cchv v0.4.3(コンテナはPostgreSQL 3 CPU・nginx 2 CPU、VMは3と2 vCPU) 3,966 27,282 3,550 45,031 21,220 216
  • PostgreSQL: ブロックデバイスにすると、Kataはvirtio-fsより書き込みが約11%速くなります(CPUをそろえて4,588と4,127、VMの大きさをそろえて3,152と2,825)。CPUをそろえた行では、Kataがcchvより書き込みで16%上で、読み取りとコミットは同等です。VMの大きさをそろえた行では、cchvが書き込みで26%、読み取りで46%上で、コミットは同等です。Kataの既定に対するcchvの約1.4倍のうち、ブロックデバイスで説明できるのは一部で、残りは、VMの大きさをそろえた行でKataのCPUが1つ減る分です。Kataの本当の値は2つの行の間で、cchvに近いです。
  • nginxの小さいファイル: ブロックデバイスのKataは、1 KBでcchvより7〜14%速いです。どちらもrunc(31,920)より上ですが、runcはCPUのquotaに縛られ、microVMのvCPUはコンテナの制限の外にあるので、VMのランタイムは制限より多くのホストCPUを使えます。今回、ホストのCPU時間は測っていません。cchvの小さいファイルの速さはブロックデバイスのおかげで、ブロックデバイスを持つランタイムなら同じになります。
  • 100 KBと10 MB: Kataは1,742と14、cchvは21,220と216です。ディスクの経路では説明できません。virtio-fsのKataも同じ水準(1,640〜1,670と15)だからです。VMに入るネットワークの経路に見えますが、原因は見つかっていません。
  • メモリは、ディスクの経路では変わりません。差が出るのは、VM 1台の固定費です。

メモリの費用

アイドルのPostgreSQL 1個がホストに使わせるメモリと、アイドルのnginxを多数並べたときの1個あたりのメモリです。

PostgreSQL、アイドル nginx 1個あたり(16個並べる)、アイドル → 負荷中
runc 60 MiB 12 → 29 MiB
gVisor 146 MiB 39 → 62 MiB
Kata 336 MiB 154 → 172 MiB
cchv 356 MiB 72 → 88 MiB

コンテナごとのmicroVMは、無料ではありません。データベースでは、cchvはruncより約300 MiB多く、Kataよりも少し多いです。nginxでは、cchvはKataの半分以下です。

nginx

wrk、2 CPU、60秒、1秒あたりのリクエスト数です。

1 KB、50接続 100 KB、50接続 10 MB、50接続
runc 31,920 19,908 405
Kata(どちらの大きさでも) 6,678 / 7,131 1,640 / 1,670 15
cchv 45,031 21,220 216

cchvは、小さなファイルではruncより上で、10 MBのファイルでは下です(VMを通るコピーのコスト)。この表のKataはvirtio-fsで、ブロックデバイスを渡すと、1 KBではKataの方がcchvより速くなります(上の節)。gVisorの1 KBの数字は、この表から外しました。どの実行でも、ちょうど毎秒831リクエストで、接続を4倍にすると4倍になります。スループットの上限ではなく、小さな応答に対するTCPの経路の固定の遅延のように見えます。原因は見つかっていません。

cchvが負けるところ

  • たくさん同時に起動する。 PostgreSQLを16個、全部が準備できるまで、cchvで65秒、Kataで26秒、gVisorで13秒、runcで8秒かかりました。PostgreSQL 1個の起動は、cchvで約3秒です。
  • データベース1個あたりのメモリ。 上の表のとおりです。
  • nginxで大きなファイルを返すとき。
  • ブロックデバイスを渡したKataに対する、小さなファイル(1 KBでKataが7〜14%上。PostgreSQLの書き込みも、CPUをそろえるとKataが16%上)。

この数字が言っていないこと

マシンは1台で、CPUは古い世代です。PostgreSQLのバージョンは1つ、nginxのイメージも1つです。Kataは既定の設定のままで、チューニングしていません。チューニングしたKataは、もっと速いかもしれません。cchvは自分たちで作ったので、他のランタイムより設定をよく知っています。fsync なしで書いたファイルは、4つのランタイムのどれでも、コンテナの終了後に残りました。fsync 自体の費用も、どこでも同じ(約200 µs)でした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?