libvirtでKVM仮想マシンをコマンドライン管理する方法(virsh)

Virtualization tutorial - IT technology blog
Virtualization tutorial - IT technology blog

背景:深夜2時にproduction VMがハングしたとき

午前2時17分。スマートフォンが振動した――顧客からwebアプリが応答しないと連絡が来た。hypervisorホストにSSH接続したが、GUIもwebパネルもなく、あるのは真っ白なターミナルだけ。このとき気づいた:virshを知っているかどうかが、問題を解決してまた眠れるか、朝まで手探りするかの分かれ目だと。

自分はProxmox VEで12台のVMとコンテナを管理するhomelabを運用している――productionに持ち込む前にあれこれ試すplaygroundだ。ProxmoxはWeb UIが便利だが、内部ではlibvirtとQEMUを使っている。データセンターに借りているbare-metalサーバーでは、使えるのはSSHとvirshだけ。この記事は、教科書の理論ではなく、実際にproductionで役立っているものをまとめたものだ。

アーキテクチャを簡単に説明すると:libvirtKVM/QEMU上の抽象化レイヤーで、覚えにくいパラメーターを大量に並べてQEMUを直接呼び出す代わりに、libvirt APIをすっきり使える。virsh(virtualization shell)はlibvirtのCLIクライアントで、あの深夜2時にターミナルで叩いていたものだ。なぜGUIを使い続けずvirshを学ぶべきなのか?

  • リモートサーバーにdesktop environmentがない
  • スクリプト自動化:デプロイのたびにスナップショット、定期バックアップ
  • 管理ツールのWeb UIにもアクセスできないときのVM障害デバッグ
  • 10台以上のVMを同時管理:ループコマンド1つで完結、1台ずつクリックする必要がない

libvirtと関連ツールのインストール

インストール前に、CPUが仮想化をサポートしているか確認する:

grep -E '(vmx|svm)' /proc/cpuinfo | head -1
# vmx = Intel VT-x、svm = AMD-V
# 出力が空の場合 → BIOSでVTが無効 — BIOS設定でVTを有効にする

Ubuntu/Debianへのインストール:

sudo apt update
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients \
  bridge-utils virtinst virt-top cpu-checker

# KVMが正常に読み込まれているか確認
sudo kvm-ok
# 期待される出力: INFO: /dev/kvm exists — KVM acceleration can be used

CentOS/RHEL/AlmaLinuxの場合:

sudo dnf install -y qemu-kvm libvirt libvirt-client virt-install virt-top
sudo systemctl enable --now libvirtd

sudoなしでvirshを使えるようにlibvirtグループにユーザーを追加する:

sudo usermod -aG libvirt,kvm $USER
newgrp libvirt  # ログアウトせずにすぐ反映

VMの作成から日常運用まで

virt-installで最初のVMを作成する

ISOからVMを作成する最速の方法:

sudo virt-install \
  --name ubuntu-server-01 \
  --ram 2048 \
  --vcpus 2 \
  --disk path=/var/lib/libvirt/images/ubuntu-server-01.qcow2,size=20,format=qcow2 \
  --os-variant ubuntu22.04 \
  --network bridge=virbr0 \
  --graphics none \
  --console pty,target_type=serial \
  --location 'http://archive.ubuntu.com/ubuntu/dists/jammy/main/installer-amd64/' \
  --extra-args 'console=ttyS0,115200n8 serial'

# 有効なos-variantの一覧を確認する:
osinfo-query os | grep ubuntu

あるいはcloud imageがある場合 — ISOからのインストールより約15分速く、自分がよく使う方法だ:

# Ubuntu 22.04 cloud imageをダウンロード
wget -O /var/lib/libvirt/images/ubuntu-22.04-base.qcow2 \
  https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img

# base imageからVMを作成(copy-on-write、ディスク節約)
sudo qemu-img create -f qcow2 -b /var/lib/libvirt/images/ubuntu-22.04-base.qcow2 \
  -F qcow2 /var/lib/libvirt/images/vm-test.qcow2 20G

日常的に使うvirshコマンド

覚えやすいようにグループ分けする:

VM状態の確認:

virsh list --all           # 全VMを表示(running + stopped)
virsh dominfo ubuntu-server-01   # 1つのVMの詳細情報
virsh domstate ubuntu-server-01  # 状態のみを確認
virsh vcpuinfo ubuntu-server-01  # CPUアフィニティと使用状況
virsh dommemstat ubuntu-server-01  # リアルタイムメモリ統計

VMの起動/停止:

virsh start ubuntu-server-01      # VMを起動
virsh shutdown ubuntu-server-01   # グレースフルシャットダウン(ACPIシグナル送信)
virsh destroy ubuntu-server-01    # 強制終了 — VMがハングして応答しないときに使用
virsh reboot ubuntu-server-01     # グレースフルリブート
virsh reset ubuntu-server-01      # ハードリセット(リセットボタンを押すのと同等)

あの深夜2時に使ったコマンド:

# VMが全く応答しない — まずグレースフルを試す
virsh shutdown production-web-01
# 30秒待って、シャットダウンしなければ:
virsh destroy production-web-01
# 再起動
virsh start production-web-01
# コンソールでブートログを確認
virsh console production-web-01
# コンソールを終了: Ctrl+]

スナップショット — 最も助けられた機能

デプロイやシステムアップデートの前に、必ずスナップショットを取る。10秒かかるが、問題が発生したときの手動ロールバックに要する時間を大幅に節約できる:

# スナップショットを作成(VMは実行中または停止中)
virsh snapshot-create-as ubuntu-server-01 \
  --name "before-nginx-upgrade" \
  --description "nginx 1.24アップグレード前のスナップショット" \
  --atomic

# スナップショット一覧を表示
virsh snapshot-list ubuntu-server-01

# スナップショットの詳細情報を確認
virsh snapshot-info ubuntu-server-01 before-nginx-upgrade

# 古いスナップショットにロールバック(アップグレード失敗時)
virsh snapshot-revert ubuntu-server-01 before-nginx-upgrade

# 不要なスナップショットを削除
virsh snapshot-delete ubuntu-server-01 before-nginx-upgrade

VMのクローン

クローンは最初からインストールするより約20分速い――テスト用VMを素早く立ち上げたり、ステージング環境を複製するときに便利だ:

# クローン前に元のVMをシャットダウン
virsh shutdown ubuntu-server-01

# クローン実行
sudo virt-clone \
  --original ubuntu-server-01 \
  --name ubuntu-server-02 \
  --auto-clone

# ディスクパスを指定してクローン
sudo virt-clone \
  --original ubuntu-server-01 \
  --name ubuntu-server-02 \
  --file /var/lib/libvirt/images/ubuntu-server-02.qcow2

ストレージプールの管理

デフォルトでlibvirtはディスクイメージを/var/lib/libvirt/images/に保存する。専用SSDやNASをマウントしたときは、そこを指すストレージプールを作成してパフォーマンスを活用する:

# 既存のプールを表示
virsh pool-list --all

# カスタムディレクトリを指すプールを新規作成
virsh pool-define-as ssd-pool dir --target /mnt/ssd/libvirt/images
virsh pool-build ssd-pool
virsh pool-start ssd-pool
virsh pool-autostart ssd-pool

# プール内のボリュームを表示
virsh vol-list default

# ディスクイメージの実パスを取得
virsh vol-path --pool default ubuntu-server-01.qcow2

# VMのディスクをリサイズ(VMは停止中であること)
virsh vol-resize --pool default ubuntu-server-01.qcow2 30G

VM設定の変更

# XML設定を編集(デフォルトのEDITORを使用)
virsh edit ubuntu-server-01

# VMを停止せずRAMを変更(balloon driverがサポートしている場合)
virsh setmem ubuntu-server-01 4096M --live --config

# CPUを追加
virsh setvcpus ubuntu-server-01 4 --live --config

# ホスト再起動時に自動起動
virsh autostart ubuntu-server-01
virsh autostart --disable ubuntu-server-01  # 自動起動を無効化

確認とモニタリング

リアルタイムリソース使用状況の確認

virt-topは、どのVMがCPUやRAMを食いすぎていると疑ったときに最初に叩くコマンドだ:

# VM向けtopコマンド — 非常に便利
virt-top

# 実行中の全VMの統計
virsh domstats --live

# 特定VMのCPU統計
virsh cpu-stats ubuntu-server-01 --total

# ディスクI/O統計
virsh domblkstat ubuntu-server-01 vda

# ネットワーク統計
virsh domifstat ubuntu-server-01 vnet0

VM障害時のログ確認

# libvirtdデーモンのログ
sudo journalctl -u libvirtd -f

# 各VMのQEMUログ(非常に詳細、デバッグ時に使用)
sudo cat /var/log/libvirt/qemu/ubuntu-server-01.log | tail -50

# 現在のVM XML設定を確認(ランタイム情報を含む)
virsh dumpxml ubuntu-server-01

# libvirt接続が正常かチェック
virsh -c qemu:///system version

全VMの簡易バックアップスクリプト

このスクリプトには少なくとも3回助けられた――直近では、カーネルアップデートでVMが起動できなくなったときだ。新しい設定を試す前に毎晩実行している:

#!/bin/bash
# snapshot-all.sh — 実行中の全VMをスナップショット
SNAP_NAME="daily-$(date +%Y%m%d)"

for vm in $(virsh list --name --state-running); do
  echo "Snapshotting $vm..."
  virsh snapshot-create-as "$vm" \
    --name "$SNAP_NAME" \
    --description "Auto daily snapshot" \
    --atomic && echo "OK: $vm" || echo "FAILED: $vm"
done

echo "Done. Snapshots:"
virsh snapshot-list --all 2>/dev/null || true

よくあるエラー

これら3つのエラーは、初回セットアップ時に最もよく現れる――そしてシステムアップデート後にも再発しがちだ:

エラー: error: Failed to connect socket to '/var/run/libvirt/libvirt-sock'

sudo systemctl start libvirtd
# またはソケットを確認:
ls -la /var/run/libvirt/

エラー: error: Cannot access storage file — VM起動時

# ファイルのパーミッションを確認
ls -la /var/lib/libvirt/images/
# パーミッションを修正
sudo chown libvirt-qemu:kvm /var/lib/libvirt/images/*.qcow2
sudo chmod 660 /var/lib/libvirt/images/*.qcow2

VMがシャットダウンできない(シャットダウンタイムアウト):

# /etc/libvirt/qemu.confでシャットダウンタイムアウトを延長:
# shutdown_timeout = 60  (秒)
# その後libvirtdを再起動
sudo systemctl restart libvirtd

あの深夜2時の一件の後、これらのコマンドを全部virsh-cheatsheet.mdというファイルにまとめてサーバーに置いた。覚えられないからではなく――ストレス下では、cheatsheetを見る方がGoogleで検索するより断然速いからだ。

Share: