Skip to content

필사 모드: KubeVirtはどのようにPod上でVMを実行するのか

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

はじめに

KubeVirtを初めて見た時に最も違和感があるのはこの点だ。「Kubernetesは元々コンテナオーケストレーターなのに、どうやってVMをPod上で起動できるのか?」この質問に答えるには、まず一つの誤解を解く必要がある。KubeVirtはkubeletの中にVM機能を組み込まない。代わりに**Kubernetesが既に得意なことと、仮想化スタックが得意なことを分離**する。

- Kubernetesが担うもの:APIストレージ、スケジューリング、Podネットワーク、ボリュームマウント、ノード配置、リトライ

- KubeVirtが担うもの:VM関連CRD、VM専用controller、ノードエージェント、libvirtとQEMUオーケストレーション

- Linuxとハイパーバイザーが担うもの:`cgroup`、`namespace`、`tap`、`netlink`、`/dev/kvm`、QEMU仮想化実行

つまりKubeVirtの本質は「コンテナランタイム上でVMをエミュレーションする」ではない。正確には**Podを VM実行のためのサンドボックスと制御単位として使用し、その中でQEMUとlibvirtを動作させる構造**だ。

最初に掴むべきメンタルモデル

KubeVirtの構造を一行でまとめると次の通りだ。

1. ユーザーが`VirtualMachine`または`VirtualMachineInstance`を作成する。

2. `virt-controller`がこれを見て`virt-launcher` Podを作成する。

3. Kubernetesがそのpodを通常のPodと同様にスケジューリングする。

4. 該当ノードの`virt-handler`がPodとVMIを見て実際のVMラウンチを指揮する。

5. `virt-launcher` Pod内部のlibvirtとQEMUがVMプロセスを実行する。

ここで重要なのは**VMがPodの中に「パッケージ」されている**ということであり、ゲストOSがコンテナになるという意味ではないという点だ。ゲストOSは依然としてQEMUが提供する仮想ハードウェア上で動作する。ただし、そのQEMUプロセスがPodのリソース境界内で実行される。

KubeVirt公式アーキテクチャドキュメントの`docs/architecture.md`と`docs/components.md`もこの構造を明確に示している。そこではKubeVirtはKubernetes上に載る追加的なコントロールプレーンとノードエージェントの集合として説明されている。

なぜわざわざPodをVM実行単位として使うのか

この設計は非常に実用的だ。KubeVirtが独自にスケジューラ、ボリュームアタッチロジック、ネットワークアロケーターを作り直す必要がないからだ。

1. スケジューリングを作り直す必要がない

VMも結局どのノードに配置されなければならない。Kubernetesはリソース要求、affinity、taint、topology spread、priorityに基づいてPodを適切に配置する。KubeVirtはこの機能を再利用する。

2. ネットワークを新しく作る必要がない

デフォルトモデルでは、まず`virt-launcher` PodがCNIを通じてネットワークを受け取る。その後KubeVirtがそのPodのネットワークnamespace内部でbridge、masquerade、TAPなどの追加ワイヤリングを行い、ゲストNICを接続する。

3. ストレージを新しく作る必要がない

PVC、DataVolume、container disk、secret、config mapなどのリソースはすべてPodボリュームモデルを通じて`virt-launcher`に渡される。KubeVirtはその上でこれらをディスクイメージやブロックデバイスとしてゲストに接続する。

Pod内部で実際に何が動いているのか

コアPodは`virt-launcher` Podだ。このPodは「VM一台につき一つ」という感覚で理解すればよい。このPod内で重要なプロセスは以下の通り。

- `virt-launcher`

- libvirtdまたはvirtqemud系の制御コンポーネント

- QEMU

- 場合によってはsidecarやhookコンテナ

ユーザーは通常「VMが実行されている」と言うが、ノードの観点では実際には**QEMUプロセスがPodのcgroupとnamespace内で実行**されている。これがKubeVirtがVMをPod上で実行できる最も実質的な理由だ。

`docs/components.md`は`virt-launcher` Podの目的を「VMIプロセスのためのcgroupとnamespaceを提供すること」と説明している。この表現は非常に重要だ。ここでのPodは単なるデプロイ単位ではなく**VM実行境界**だ。

KubernetesとKubeVirtの境界

KubeVirtを理解する際に最も混乱しやすい部分は「誰が何を担当するのか」だ。

Kubernetesが引き続き担当する部分

- Podスケジューリング

- ボリュームマウント準備

- Podネットワークアタッチ

- コンテナライフサイクル

- ノード状態反映

KubeVirtが追加で担当する部分

- VM関連API種類の提供

- VM specをlauncher Pod specに変換

- ノードでのVMプロセスライフサイクル調整

- ゲスト用ネットワークバインディングとDHCP補助

- ライブマイグレーションオーケストレーション

libvirtとQEMUが担当する部分

- ドメインXML解釈

- 仮想ハードウェアモデル構成

- CPU、メモリ、ディスク、NIC仮想化

- ライブマイグレーションデータ転送

この分離がうまくできているため、KubeVirtはKubernetesをフォークしたりkubeletを大規模に修正したりせずにVMワークロードを追加できる。

ソースコードでこの構造が現れる場所

このシリーズ全般で繰り返し見ることになる核心パッケージは以下の通りだ。

staging/src/kubevirt.io/api/core/v1

pkg/virt-controller/watch

pkg/virt-handler

pkg/virt-launcher/virtwrap

pkg/network

各レイヤーを一行でまとめると:

- `staging/src/kubevirt.io/api/core/v1`:VM関連CRDスキーマ

- `pkg/virt-controller/watch`:クラスタワイドのreconcileロジック

- `pkg/virt-handler`:ノード別VMエージェント

- `pkg/virt-launcher/virtwrap`:libvirt、QEMU制御

- `pkg/network`:PodネットワークをゲストNICに接続するコード

「Pod上でVM」が成立する核心メカニズム

さて質問に戻ろう。一体どうやってVM機能をPodで実現できたのか?

核心は3つだ。

第一に、Podは元々プロセス分離境界である

Podはネットワークnamespace、マウントnamespace、PID namespace、cgroupなどの境界を提供する。QEMUは結局Linuxプロセスなので、この境界内で実行できる。

第二に、`/dev/kvm`のようなホスト機能をPodに公開できる

ハードウェア仮想化の高速化にはKVMデバイスアクセスが必要だ。KubeVirtは適切なデバイスと権限を`virt-launcher`側に接続してゲスト実行パフォーマンスを確保する。

第三に、Kubernetesリソースモデルと仮想化モデルの間にtranslation layerを作る

ユーザーはVMI specにCPU、メモリ、ディスク、NICを宣言する。KubeVirtはこれをPod spec、libvirtドメインspec、ゲスト可視デバイス構成へと順次変換する。つまりKubeVirtの本質は**translation engine**だ。

よくある誤解

誤解1:VMがコンテナ内で動くのだからコンテナと同じだ

違う。実行境界はPodを再利用するが、ゲストOSはQEMUが提供する仮想ハードウェア上で動作する。プロセスモデルとゲストOSモデルは異なる。

誤解2:KubeVirtがネットワークとストレージをすべて自前で実装している

違う。設計哲学上、KubernetesとCNI、ボリュームシステムを最大限再利用する。KubeVirtはその上にVM向けのワイヤリングを追加する。

誤解3:kubeletがVMライフサイクルを理解している

直接理解していない。kubeletは`virt-launcher` Podを管理する。VMライフサイクルの詳細な状態は`virt-handler`と`virt-launcher`が追加で調整する。

運用者がすぐに使えるデバッグチェックポイント

- VMIが作成されたのにPodがなければ、`virt-controller`側のreconcileを確認する。

- Podは起動しているがVMがブートしなければ、`virt-handler`と`virt-launcher`の通信を確認する。

- ゲストネットワークがおかしければ、Pod NIC、bridge、TAP、DHCPの順に確認する。

- マイグレーション問題が発生したら、controllerステージとlibvirtマイグレーションステージが分離されていることを覚えておく。

まとめ

KubeVirtが「Pod上でVM」を実現できた理由は、Kubernetesを変更したからではなく、Kubernetesの強みをそのまま活用し、VMに必要なtranslation layerを追加したからだ。Podは実行サンドボックスとなり、`virt-controller`はオーケストレーションを担い、`virt-handler`はノード別の実行を調整し、`virt-launcher`内のlibvirtとQEMUが実際のVMを作成する。

次の記事では、この構造を構成するオブジェクトモデル、すなわち`VirtualMachine`、`VirtualMachineInstance`、`VirtualMachineInstanceMigration`がそれぞれ何を表現するのか、ソーススキーマ基準で整理する。

현재 단락 (1/66)

KubeVirtを初めて見た時に最も違和感があるのはこの点だ。「Kubernetesは元々コンテナオーケストレーターなのに、どうやってVMをPod上で起動できるのか?」この質問に答えるには、まず一つの...

작성 글자: 0원문 글자: 4,362작성 단락: 0/66