TT Lab

한국어 English 日本語

はじめる
ブログ

ブログ

[オペレーティングシステム] 18. 仮想マシン:ハイパーバイザーからコンテナまで

仮想マシン:ハイパーバイザーからコンテナまで

仮想化技術は1台の物理マシン上に複数の独立した実行環境を作成し、リソース活用度を高めて隔離を提供します。この記事では、従来のハイパーバイザーベースVMから現代的なコンテナまで解説します。


1. 仮想マシンの利点

┌──────────────────────────────────────────┐
│            VMの主要利点                   │
│                                          │
│  隔離(Isolation):                      │
│  - VM間の完全な隔離                      │
│  - 1つのVM障害が他のVMに影響しない       │
│                                          │
│  統合(Consolidation):                  │
│  - 複数サーバーを1台の物理マシンに統合   │
│  - ハードウェア活用率向上(15% → 70%+)  │
│                                          │
│  移植性(Portability):                  │
│  - VMイメージを他のホストに移動可能      │
│  - ハードウェア独立                      │
│                                          │
│  開発/テスト:                            │
│  - 多様なOS環境を同時運用               │
│  - スナップショットで高速復元            │
│                                          │
│  セキュリティ:                           │
│  - 疑わしいソフトウェアをVMで実行        │
│  - 侵害時にVMのみ廃棄                   │
└──────────────────────────────────────────┘

2. Type 1ハイパーバイザー(Bare-Metal)

物理ハードウェア上で直接実行されるハイパーバイザーです。

┌────────────┐ ┌────────────┐ ┌────────────┐
│ Guest OS 1 │ │ Guest OS 2 │ │ Guest OS 3 │
│ (Linux)    │ │ (Windows)  │ │ (FreeBSD)  │
├────────────┤ ├────────────┤ ├────────────┤
│ 仮想 HW   │ │ 仮想 HW   │ │ 仮想 HW   │
└──────┬─────┘ └──────┬─────┘ └──────┬─────┘
       │              │              │
┌──────┴──────────────┴──────────────┴──────┐
│         Type 1 ハイパーバイザー           │
│    (VMware ESXi, Xen, Hyper-V, KVM)     │
├───────────────────────────────────────────┤
│              物理ハードウェア              │
└───────────────────────────────────────────┘
名前開発元特徴
VMware ESXiVMwareエンタープライズ市場リーダー
KVMLinuxカーネルLinuxカーネルモジュール、OSS
XenLinux Foundation準仮想化の先駆者、初期AWS使用
Hyper-VMicrosoftWindows Server統合

3. Type 2ハイパーバイザー(Hosted)

既存のオペレーティングシステム上で実行されるハイパーバイザーです。

┌────────────┐ ┌────────────┐
│ Guest OS 1 │ │ Guest OS 2 │
├────────────┤ ├────────────┤
│ 仮想 HW   │ │ 仮想 HW   │
└──────┬─────┘ └──────┬─────┘
       │              │
┌──────┴──────────────┴───────────┐
│    Type 2 ハイパーバイザー       │
│  (VirtualBox, VMware Workstation)│
├─────────────────────────────────┤
│       ホストOS (macOS等)        │
├─────────────────────────────────┤
│         物理ハードウェア         │
└─────────────────────────────────┘

Type 1 vs Type 2 比較

特性Type 1Type 2
実行場所ハードウェア直接ホストOS上
性能高い(低オーバーヘッド)普通(ホストOS経由)
用途サーバー、クラウド開発/テスト、デスクトップ
隔離レベル高い普通

4. ハードウェア支援仮想化

VT-x(Intel Virtualization Technology)

ハードウェアレベルで仮想化をサポートし効率性を高めます。

ソフトウェア仮想化(バイナリ変換):
┌─────────────────────────────────┐
│ Guest OSが特権命令を実行        │
│        ↓                        │
│ ハイパーバイザーがトラップ      │
│        ↓                        │
│ バイナリ変換でエミュレーション  │
│ → オーバーヘッド大              │
└─────────────────────────────────┘

ハードウェア支援仮想化(VT-x):
┌─────────────────────────────────┐
│ VMX rootモード(ハイパーバイザー)│
│ VMX non-rootモード(Guest OS)  │
│                                 │
│ Guest OSが特権命令を実行        │
│        ↓                        │
│ VM Exit → ハイパーバイザーへ    │
│        ↓                        │
│ ハイパーバイザー処理            │
│        ↓                        │
│ VM Entry → Guest OSに復帰      │
│ → ハードウェアが切替処理、高速  │
└─────────────────────────────────┘

メモリ仮想化 - EPT(Extended Page Tables)

ソフトウェア方式(Shadow Page Table):
ゲスト仮想 → ゲスト物理(ゲストページテーブル)
ゲスト物理 → ホスト物理(ハイパーバイザー管理)
→ 2回の変換が必要

ハードウェア方式(EPT / AMD NPT):
ゲスト仮想 → ゲスト物理 → ホスト物理
                            ↑ CPUが自動変換
→ ハイパーバイザー介入なしにハードウェアが直接処理

5. 準仮想化(Paravirtualization)

Guest OSのカーネルを修正してハイパーバイザーと直接通信する方式です。

完全仮想化:                     準仮想化:
Guest OS(修正なし)            Guest OS(修正済み)
    │                               │
    ├→ 特権命令実行                 ├→ ハイパーコール(Hypercall)
    ├→ Trap(ハードウェア)         ├→ 直接ハイパーバイザー呼出
    └→ ハイパーバイザーエミュレーション └→ ハイパーバイザー処理

準仮想化の利点: より高速(Trapオーバーヘッドなし)
準仮想化の欠点: Guest OSカーネルの修正が必要
// Xen 반가상화 하이퍼콜 예시 (의사 코드)

// 반가상화: 하이퍼콜 사용
void disable_interrupts_paravirt() {
    HYPERVISOR_event_channel_op(EVTCHNOP_mask, &mask_params);
}

void update_page_table_paravirt(pte_t *pte, pte_t new_val) {
    HYPERVISOR_mmu_update(&mmu_update, 1, NULL, DOMID_SELF);
}

6. コンテナ(Containers)

コンテナはOSレベルの仮想化で、カーネルを共有しながらプロセスを隔離します。

VM vs コンテナ

VM:                              コンテナ:
┌──────┐ ┌──────┐ ┌──────┐     ┌──────┐ ┌──────┐ ┌──────┐
│App A │ │App B │ │App C │     │App A │ │App B │ │App C │
├──────┤ ├──────┤ ├──────┤     ├──────┤ ├──────┤ ├──────┤
│Bins/ │ │Bins/ │ │Bins/ │     │Bins/ │ │Bins/ │ │Bins/ │
│Libs  │ │Libs  │ │Libs  │     │Libs  │ │Libs  │ │Libs  │
├──────┤ ├──────┤ ├──────┤     └──┬───┘ └──┬───┘ └──┬───┘
│GuestOS│ │GuestOS│ │GuestOS│        │       │       │
└──┬───┘ └──┬───┘ └──┬───┘   ┌──────┴───────┴───────┴──────┐
┌──┴────────┴────────┴──┐    │     コンテナランタイム       │
│   ハイパーバイザー     │    │     (Docker Engine)         │
├───────────────────────┤    ├──────────────────────────────┤
│     ホストOS          │    │       ホストOS               │
├───────────────────────┤    │     (カーネル共有)         │
│   物理ハードウェア     │    ├──────────────────────────────┤
└───────────────────────┘    │     物理ハードウェア         │
                             └──────────────────────────────┘

VM: OS全体含む(GB単位)      コンテナ: アプリ+ライブラリのみ(MB単位)
起動: 分単位                  開始: 秒単位

Docker基本使用法

# Docker 이미지 빌드
# Dockerfile 예시
# FROM ubuntu:22.04
# RUN apt-get update && apt-get install -y nginx
# COPY index.html /var/www/html/
# EXPOSE 80
# CMD ["nginx", "-g", "daemon off;"]

docker build -t my-nginx .
docker run -d -p 8080:80 --name web my-nginx
docker ps
docker logs web
docker stop web
docker rm web

コンテナの隔離技術(Linux)

┌──────────────────────────────────────────────┐
│       Linuxコンテナ隔離技術                   │
│                                              │
│  Namespaces(隔離):                         │
│  ┌────────────┬───────────────────────────┐  │
│  │ PID        │ プロセスID隔離            │  │
│  │ NET        │ ネットワークスタック隔離   │  │
│  │ MNT        │ ファイルシステムマウント隔離│ │
│  │ UTS        │ ホスト名隔離              │  │
│  │ IPC        │ IPCリソース隔離           │  │
│  │ USER       │ ユーザー/グループID隔離   │  │
│  │ CGROUP     │ cgroupビュー隔離          │  │
│  └────────────┴───────────────────────────┘  │
│                                              │
│  Control Groups(cgroups - リソース制限):    │
│  ┌────────────┬───────────────────────────┐  │
│  │ CPU        │ CPU使用量制限             │  │
│  │ Memory     │ メモリ使用量制限          │  │
│  │ I/O        │ ディスクI/O帯域幅制限     │  │
│  │ Network    │ ネットワーク帯域幅制限    │  │
│  └────────────┴───────────────────────────┘  │
└──────────────────────────────────────────────┘
// 네임스페이스를 이용한 프로세스 격리 (의사 코드)
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define STACK_SIZE (1024 * 1024)

int child_func(void *arg) {
    printf("Child PID (in namespace): %d\n", getpid());
    sethostname("container", 9);
    execl("/bin/bash", "bash", NULL);
    return 0;
}

int main() {
    char *stack = malloc(STACK_SIZE);
    int flags = CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNS;
    pid_t pid = clone(child_func, stack + STACK_SIZE, flags, NULL);
    printf("Child PID (in parent): %d\n", pid);
    waitpid(pid, NULL, 0);
    free(stack);
    return 0;
}

Kubernetes概要

コンテナオーケストレーションプラットフォームで、大規模コンテナのデプロイと管理を自動化します。

┌──────────────────────────────────────────────────┐
│              Kubernetes クラスター                 │
│                                                  │
│  Control Plane(マスター):                       │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐         │
│  │ API      │ │ Scheduler│ │ Controller│         │
│  │ Server   │ │          │ │ Manager  │         │
│  └──────────┘ └──────────┘ └──────────┘         │
│  ┌──────────┐                                    │
│  │ etcd     │ ← クラスター状態ストア             │
│  └──────────┘                                    │
│                                                  │
│  Worker Nodes:                                   │
│  ┌─────────────────┐  ┌─────────────────┐        │
│  │ Node 1          │  │ Node 2          │        │
│  │ ┌─────┐ ┌─────┐│  │ ┌─────┐ ┌─────┐│        │
│  │ │Pod A│ │Pod B││  │ │Pod C│ │Pod D││        │
│  │ └─────┘ └─────┘│  │ └─────┘ └─────┘│        │
│  └─────────────────┘  └─────────────────┘        │
└──────────────────────────────────────────────────┘

7. アプリケーション隔離

セキュリティ強化のための多層隔離

┌─────────────────────────────────────┐
│        隔離レベルの比較              │
│                                     │
│  VM:          強い隔離              │
│  │            (ハイパーバイザー境界)│
│  gVisor:      中間隔離              │
│  │            (ユーザー空間カーネル)│
│  コンテナ:    基本隔離              │
│  │            (名前空間/cgroups)   │
│  プロセス:    最小隔離              │
│              (同一カーネル共有)    │
└─────────────────────────────────────┘

8. VMマイグレーション

実行中のVMを別の物理ホストに移動する技術です。

ライブマイグレーション過程

ソースホスト                       宛先ホスト
┌──────────────┐                ┌──────────────┐
│ VM(実行中) │                │              │
│ 1. メモリ    │                │              │
│    ページ転送│───────────────→│ 受信         │
│ 2. ダーティ  │                │              │
│    ページ    │───────────────→│ 受信         │
│    反復転送  │                │              │
│ 3. VM一時停止│                │              │
│    残り転送  │───────────────→│ 受信         │
│ 4. VM停止   │                │ 5. VM再開    │
└──────────────┘                └──────────────┘
ダウンタイム: 数十〜数百ms(ほぼ無中断)

9. ユニカーネル(Unikernels)

アプリケーションと必要なOS機能のみを1つの単一アドレス空間イメージにコンパイルする軽量VMです。

通常のVM:                   ユニカーネル:
┌───────────┐              ┌───────────┐
│ App       │              │ App       │
├───────────┤              │ + 必要な  │
│ ライブラリ│              │   OS機能  │
├───────────┤              │(単一バイ │
│ 完全OS    │              │ ナリ)    │
└─────┬─────┘              └─────┬─────┘
  ハイパーバイザー          ハイパーバイザー

サイズ: GB単位              サイズ: MB単位
起動: 秒単位                起動: ミリ秒単位
攻撃サーフェス: 広い        攻撃サーフェス: 非常に狭い

10. まとめ

クイズ:仮想マシン

Q1. Type 1とType 2ハイパーバイザーの違いは何ですか?

A1. Type 1は物理ハードウェア上で直接実行され(bare-metal)、オーバーヘッドが少なく性能に優れます。Type 2は既存のOSの上でアプリケーションとして実行されインストールが簡単ですが、ホストOSを経由するため追加のオーバーヘッドがあります。

Q2. コンテナがVMより軽い理由は何ですか?

A2. VMはそれぞれ完全なGuest OSを含みますが、コンテナはホストカーネルを共有しアプリケーションとライブラリのみパッケージングします。そのためコンテナイメージはMB単位で軽く、起動時間も秒単位で高速です。

Q3. ライブマイグレーションでダウンタイムを最小化する方法は?

A3. プレコピー(Pre-copy)方式では、VMが実行中にメモリページを転送し、変更された(dirty)ページを反復転送します。変更量が十分に減ると、VMを短時間停止して残りを転送し、宛先で再開します。これによりダウンタイムを数十ミリ秒レベルに削減できます。

ログインするといいねできます

コメント

まだコメントはありません。

ログインするとコメントできます