すべてを一つに:VMとコンテナが「同じ屋根の下」に住むとき
DevOpsエンジニアなら、片手で kubectl を操りコンテナを制御し、もう片方の手でProxmoxやVMwareを操作してレガシーなデータベースを動かす仮想マシン(VM)を管理する、という光景に慣れっこでしょう。このように2つの異なるインフラを維持することは、リソースと人件費を大幅に消費します。私のホームラボでも、コンテナ化できないレガシーアプリのために12台のVMを維持していましたが、ダッシュボードを行ったり来たりするのは本当に苦痛でした。
そこで救世主として登場するのが KubeVirt です。これにより、KubernetesのPod内でKVM仮想マシンを直接実行できるようになります。今や、シンプルなNginxコンテナを定義するのと同じように、YAMLファイルを使ってWindows Serverを定義できるのです。
実例比較:従来の仮想化 vs クラウドネイティブ仮想化
コマンドを打ち始める前に、自分たちがどこに立っているのかを知るために、核心的な違いを振り返ってみましょう。
- 従来の仮想化(Proxmox, ESXi): 仮想マシンは「第一級市民」です。ネットワークとストレージはVM専用に設計されています。K8sを実行したい場合は、これらのVMの上にインストールする必要があります。
- クラウドネイティブ仮想化(KubeVirt): Kubernetesが下地(Underlay)の役割を果たします。VMはK8s内の一つのリソース(CRD)となります。SchedulerからRBAC、Monitoring(Prometheus)、Logging(Loki)まで、エコシステム全体を継承します。
個別のVLAN設定に頭を悩ませる代わりに、VMはCalicoやCiliumを介してクラスターのネットワーク帯域を共有します。これがネットワーク構成を大幅にシンプルにする鍵となります。
KubeVirtは本当に万能か? メリットとデメリットを整理
KubeVirtのメリット
最大の利点は一貫性です。PodとVMの両方に対して、全く同じCI/CDパイプパイプラインとアラートシステムを使用できます。次に、リソースの有効活用です。K8sはRAM/CPUに余裕があるノードに自動的にVMを配置するため、手動で細かく計算する必要がありません。
注意すべきデメリット
最大の問題はパフォーマンスです。VMがPodの中でネストして実行されるため、抽象化レイヤーが一つ増えます。KVMのサポートがあっても、CPUのオーバーヘッドはベアメタル実行に比べて通常5〜10%程度発生します。また、K8s上でのVM用ストレージ管理(PVCからのディスクイメージ作成など)は、Proxmoxで数回クリックするのに比べれば、まだ少し手間がかかります。
いつKubeVirtを「導入」すべきか?
既存のVMwareシステムをすぐに捨てる必要はありません。私の経験上、以下の3つのケースでKubeVirtを検討してみてください。
- インフラを近代化したいが、Windows Serverや特定のカーネルでしか動作しない古いモジュールが残っている場合。
- 開発チーム向けに、1セットのYAMLだけでDB(VM)とアプリ(コンテナ)の両方を迅速に作成できるセルフサービス基盤を構築したい場合。
- すべてをGitOpsとKubernetesカスタムリソースで管理し、システム全体の構成を同期させたい場合。
KubeVirtを導入するための実践的ステップ
ステップ1:サーバーの「内功(スペック)」を確認する
KubeVirtをスムーズに動かすには、ノードがハードウェア仮想化をサポートしている必要があります。以下のコマンドで素早く確認しましょう。
virt-host-validate qemu
すべての項目が PASS と表示されれば問題ありません。もし FAIL が出る場合は、エミュレーション(ソフトウェア)モードを使用せざるを得ませんが、速度は亀のように遅くなるため、あくまで検証用として考えてください。
ステップ2:KubeVirt Operatorのインストール
KubeVirtのライフサイクルを最もプロフェッショナルに管理するために、Operatorを使用します。
# GitHubから最新バージョンを取得
export VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases/latest | grep tag_name | cut -d '"' -f 4)
# Operatorとカスタムリソースをインストール
kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml
kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-cr.yaml
コーヒーを一杯飲んで、kubevirt ネームスペース内のPodが準備完了になるまで数分待ちましょう。
ステップ3:操作ツール virtctl の準備
コンソールへのアクセスや起動・停止など、VMと深くやり取りするには kubectl だけでは不十分です。virtctl が必要になります。
curl -L -o virtctl https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/virtctl-${VERSION}-linux-amd64
chmod +x virtctl
sudo mv virtctl /usr/local/bin/
ステップ4:最初の仮想マシンを起動する
これは「超軽量」なFedoraを動かすためのYAMLサンプルです。コンテナイメージから起動するため、約30秒でブートが完了します。
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: itfromzero-vm
spec:
running: false
template:
spec:
domain:
devices:
disks:
- name: containerdisk
disk: {}
interfaces:
- name: default
masquerade: {}
resources:
requests:
memory: 1024Mi
networks:
- name: default
pod: {}
volumes:
- name: containerdisk
containerDisk:
image: kubevirt/fedora-cloud-container-disk-demo
ファイルを適用した後、以下のコマンドで仮想マシンを目覚めさせます。
virtctl start itfromzero-vm
実践で「ハマらない」ためのヒント
最もよく遭遇するエラーは、Storage ClassがReadWriteMany (RWX)をサポートしていないことです。ライブマイグレーション(ダウンタイムなしでノード間をVM移動)を行いたい場合、ストレージは複数の場所から同時にアクセスできる必要があります。単一ノードでのテストでない限り、ローカルパスは使用しないでください。
また、CDI (Containerized Data Importer) についても調べてみてください。これにより、.qcow2 や .iso ファイルをURLから直接PVCに取り込むことができ、手動でDockerイメージをビルドするよりも遥かに便利です。
KubeVirtは、あらゆるシナリオでVMwareやProxmoxを完全に置き換えるものではないかもしれませんが、「Single Pane of Glass(単一の管理画面)」という集中管理モデルを実現するための鍵となります。ラボの構築が成功することを願っています。困ったことがあれば、下のコメント欄に気軽に残してくださいね!

