ハードウェア基礎 #7 仮想化とコンテナ — 物理サーバー 1 台が複数台になる仕組み
#6 まで、1 台のサーバーを構成する 4 つのリソースをすべて見ました。ところがクラウドは物理サーバー 1 台を数十台のように分けて売ります。EC2 インスタンス 1 つがまるごと物理サーバーであるはずはありません。この分割を可能にするのが仮想化で、その上でさらに軽く分ける方式がコンテナです。今回はその仕組みを整理します。
ハードウェア基礎 シリーズでの今回の位置です。
- #1 コンピュータを動かす 4 つのリソース — CPU / メモリ / ストレージ / ネットワーク
- #2 CPU — コア / スレッド / クロック / キャッシュ、そして vCPU の正体
- #3 メモリ — RAM と階層構造、スワップが始まると起きること
- #4 ストレージ ① デバイス — HDD / SSD / NVMe と IOPS / スループット / レイテンシ
- #5 ストレージ ② 構成と接続 — RAID と DAS / NAS / SAN
- #6 ネットワーク — 帯域幅とレイテンシ、NIC からデータセンターまで
- #7 仮想化とコンテナ — 物理サーバー 1 台が複数台になる仕組み ← 今回
- #8 クラウド — 所有から賃借へ、オンプレミスから IaaS / PaaS / SaaS まで
- #9 クラウドインスタンスのスペックの読み方 — ワークロードに合わせて選ぶ
なぜ 1 台を分けるのか #
1 台の物理サーバーは、たいてい普段はリソースが余っています。1 つのサービスが CPU とメモリを常に使い切ることはまれです。サービスごとにサーバーを 1 台ずつ買えば、余るリソースの分だけお金が遊びます。
仮想化はこの余るリソースを集めて、1 台を複数の独立した環境に分けます。各環境は自分だけのサーバーのように見え、互いに隔離されます。稼働率が上がり、環境を分単位で作って消せるようになります。クラウドの「必要なだけ借りて使う」を可能にした土台がまさにこれです。
仮想化 — ハイパーバイザーがハードウェアを分ける #
物理サーバーの上に ハイパーバイザー (Hypervisor) という層を置き、その上に複数の 仮想マシン (VM) を乗せます。ハイパーバイザーは物理リソースを切って各 VM に分け与え、VM 同士が互いに侵せないように隔離します。
各 VM は 自分だけのオペレーティングシステムをまるごと持ちます。 VM から見れば本物のハードウェアの上で動いているように見え、その中に Linux なり Windows なりを別途インストールします。EC2 インスタンス 1 つがまさにこの VM 1 つに相当します。
┌──────────┐ ┌──────────┐ ┌──────────┐
│ アプリ A │ │ アプリ B │ │ アプリ C │
│ OS │ │ OS │ │ OS │ ← VM ごとに OS 1 つ
└──────────┘ └──────────┘ └──────────┘
ハイパーバイザー
物理サーバー (CPU・メモリ・ストレージ・ネットワーク)VM は隔離が強いです。1 つの VM の中で何が起きても、他の VM と物理サーバーへの影響はほぼありません。代わりに OS をまるごと乗せるのでメモリとディスクを多く使い、起動に時間がかかります。
コンテナ — OS カーネルを共有する #
コンテナは別の道を選びます。OS を VM ごとに別々に持たず、ホストの OS カーネルを複数のコンテナが共有 します。コンテナはその上でプロセス単位に隔離されるだけで、自分の OS をまるごと持ちません。
┌──────┐ ┌──────┐ ┌──────┐
│アプリA│ │アプリB│ │アプリC│ ← OS なしでアプリと依存だけ
└──────┘ └──────┘ └──────┘
コンテナランタイム
共有 OS カーネル
物理サーバーまたは VMOS 1 つを共有するのでコンテナは軽いです。メモリを少なく使い、起動が数十秒ではなく一瞬です。同じサーバーに VM よりはるかに多く乗せられます。この軽さが Docker と Kubernetes が定着した理由です。代わりにカーネルを共有するので隔離は VM より弱いです。
| 項目 | 仮想マシン (VM) | コンテナ |
|---|---|---|
| OS | VM ごとに 1 つ | ホストカーネルを共有 |
| 重さ | 重い (GB 単位) | 軽い (MB 単位) |
| 起動時間 | 数十秒 | 数秒以内 |
| 隔離 | 強い | 相対的に弱い |
| 1 サーバーに乗せる数 | 数個~数十個 | 数十~数百個 |
実務では 2 つを重ねて使います。クラウドが物理サーバーを VM (インスタンス) に分けて貸し、ユーザーはそのインスタンスの中でさらにコンテナを複数動かします。
リソースはどう分けられ上限が掛かるか #
分けた環境がリソースを取り合わないためには、各自の取り分に上限が必要です。Linux は cgroups という機能でプロセスグループごとに CPU・メモリ・入出力の上限を掛けます。コンテナのリソース制限がこの上で動作します。
- CPU — #2 の vCPU がここで分かれます。インスタンスに割り当てられた vCPU を、その中のコンテナたちが上限の範囲で分けて使います。
- メモリ — #3 で押さえたとおり、コンテナにメモリ上限を掛けなければ 1 つがホストのメモリを飲み込んで他のコンテナまで脅かします。上限を超えるとそのコンテナのプロセスが終了します。
オーバーコミットとノイジーネイバー #
仮想化の稼働率には影があります。クラウド事業者は物理リソースより多い量を各 VM に約束することもあります。すべての VM が同時にリソースを使い切ることはないという前提の上でです。これを オーバーコミット (overcommit) と言います。
普段は問題ありませんが、同じ物理サーバーに乗った別の VM が急にリソースを使い込むと、自分の VM の性能が揺れます。この現象を ノイジーネイバー (noisy neighbor) と言います。「昨日は問題なかったインスタンスが今日は遅い」の 1 つの原因です。
性能が揺れてはいけないワークロードは、リソースを独占するインスタンスの種類を選ぶか、1 つの物理サーバーをまるごと借りる専用オプションを使います。こうした選択は #9 のインスタンス種類の決定とつながります。
よく出会う落とし穴 #
「コンテナは軽い VM だ」 #
似て見えますが違います。VM は OS をまるごと持って隔離が強く、コンテナはカーネルを共有して軽いものの隔離が弱いです。隔離の水準が重要なワークロードはこの違いを見極める必要があります。
「コンテナに上限を掛けなかった」 #
上限がなければ 1 つのコンテナがホストのリソースを独占して他のコンテナを飢えさせます。運用では CPU とメモリの上限を明示するのが安全です。
「インスタンスの性能がばらつくが原因がわからない」 #
オーバーコミット環境のノイジーネイバーかもしれません。一貫した性能が必要なら、リソースを独占する種類や専用インスタンスを検討します。
「VM の上にコンテナは無駄だ」 #
むしろ標準です。クラウドインスタンス (VM) の強い隔離の上に、その中でコンテナの軽いデプロイを一緒に得る構成です。
まとめ #
今回つかんだ絵です。
- 仮想化は余るリソースを集めて、1 台の物理サーバーを複数の独立した環境に分けます。
- ハイパーバイザー がハードウェアを分け、各 VM は自分の OS をまるごと持ちます。EC2 インスタンスがその VM です。
- コンテナ はホストカーネルを共有して軽いものの、隔離は VM より弱いです。Docker と Kubernetes の土台です。
- リソースは cgroups で上限が掛かります。コンテナのメモリ上限は明示するのが安全です。
- オーバーコミット と ノイジーネイバー はクラウドの性能が揺れる 1 つの原因です。
次回 — クラウド #
仮想化はクラウドがリソースを分けて売る土台でした。これからその上の絵、クラウド自体を整理します。#8 クラウド — 所有から賃借へ、オンプレミスから IaaS / PaaS / SaaS まで では、ハードウェアを所有から賃借へ変えた変化、オンプレミスとコロケーションとクラウドの違い、そして IaaS・PaaS・SaaS がハードウェアをどこまで見えなくするかを整理します。