なにかの技術メモ置き場

なにかの技術メモ置き場

@インフラエンジニア

KVMゲストのストレージをイメージファイルからiSCSIディスクに移行する

f:id:none06:20211007000548p:plain

目次

概要

QEMU+KVM環境のゲストマシンのストレージを、イメージファイル(.img)からiSCSIディスクに移行する。移行といってもddで複製するだけだが、その前後の作業が煩雑だったため記録した。
移行なので既存のゲストマシンが作業対象となる。新規ゲストマシンをiSCSIディスクにインストールする方法は前回記事を参照。 none06.hatenadiary.org

経緯

  • KVMホストのローカルディスクの容量が逼迫してきた。恒久対処としてゲストマシンのイメージファイルをKVMホストの外で管理することにした。
  • データの管理場所はNASとした。
  • 接続インターフェース(プロトコル)はiSCSIとした。

環境

概念図

f:id:none06:20211007000548p:plain

構成

ホスト名 管理NWのIP ストレージNWのIP OS H/W 備考
file01 172.16.0.5 172.16.1.5 RAIDiator 4.2.31 NETGEAR ReadyNAS Pro 2 iSCSIターゲット
kvm01 172.16.0.205 172.16.1.205 CentOS 8.4.2105 HP DL360 G7 KVMホスト
guest01 172.16.0.253 - CentOS 8.4.2105 - KVMゲスト
NWアドレス NW名 用途
172.16.0.0/24 管理NW ssh接続、Web管理画面接続
172.16.1.0/24 ストレージNW ストレージ接続(iSCSI)

前提

  • iSCSIターゲットの作成手順は各自確認のこと。
  • ゲストマシンを作成済みとする。ディスクイメージはファイル(.img)とする。

手順

1.iSCSIターゲット/LUNの作成

1-1.移行元ディスク容量の確認

手順の汎用化のため、ゲストマシンのホスト名を変数_NODEに格納しておく。

[root@kvm01 ~]# _NODE=guest01
[root@kvm01 ~]# echo $_NODE
guest01

移行元ディスクの容量を確認する。

[root@kvm01 ~]# qemu-img info /var/lib/libvirt/images/${_NODE}.img
image: /var/tmp/images/guest01.img
file format: qcow2
virtual size: 20 GiB (21474836480 bytes)
disk size: 2.15 GiB
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
1-2.iSCSIターゲット/LUNの作成

iSCSIターゲット/LUNを作成する。手順は各自の環境に依存。 |ターゲット名|LUN番号|ディスク容量| |:--|:--|:--| |iqn.2020-09.file01:guest01|0|20GB|

ディスク容量について。移行元ディスクと比較して

  • 同一:無駄もなく作業もわかりやすい
  • 大きい:ディスク複製は可能だが作業後に必要に応じて拡張が必要(当記事のスコープ外)
  • 小さい:当記事の手順では移行不可(※)

パーティション作成、バックアップ(xfsdump)、リストア(xfsrestore)、grub更新、fstab更新、などを行なえば可能。

2.事前作業

2-1.ゲストマシンの定義ファイルのバックアップ

ゲストマシンの定義ファイルをバックアップする。

[root@kvm01 ~]# ls -l /etc/libvirt/qemu/${_NODE}.xml*
-rw------- 1 root root 4316 10月  8 20:25 /etc/libvirt/qemu/guest01.xml
[root@kvm01 ~]# cp -p /etc/libvirt/qemu/${_NODE}.xml{,_$(date +%Y%m%d)}
[root@kvm01 ~]# ls -l /etc/libvirt/qemu/${_NODE}.xml*
-rw------- 1 root root 4316 10月  8 20:25 /etc/libvirt/qemu/guest01.xml
-rw------- 1 root root 4316 10月  8 20:25 /etc/libvirt/qemu/guest01.xml_20211009

3.移行元ディスクの接続

3-1.nbdモジュールの読み込み

nbdモジュールを読み込む。

[root@kvm01 ~]# modprobe nbd
[root@kvm01 ~]# lsmod | grep nbd
nbd                    49152  0

nbdデバイスが作成されていることを確認する。

[root@kvm01 ~]# ls -l /dev/nbd*
brw-rw---- 1 root disk 43,   0 10月  9 13:26 /dev/nbd0
brw-rw---- 1 root disk 43,  32 10月  9 13:18 /dev/nbd1
brw-rw---- 1 root disk 43, 320 10月  9 13:18 /dev/nbd10
brw-rw---- 1 root disk 43, 352 10月  9 13:18 /dev/nbd11
brw-rw---- 1 root disk 43, 384 10月  9 13:18 /dev/nbd12
brw-rw---- 1 root disk 43, 416 10月  9 13:18 /dev/nbd13
brw-rw---- 1 root disk 43, 448 10月  9 13:18 /dev/nbd14
brw-rw---- 1 root disk 43, 480 10月  9 13:18 /dev/nbd15
brw-rw---- 1 root disk 43,  64 10月  9 13:18 /dev/nbd2
brw-rw---- 1 root disk 43,  96 10月  9 13:18 /dev/nbd3
brw-rw---- 1 root disk 43, 128 10月  9 13:18 /dev/nbd4
brw-rw---- 1 root disk 43, 160 10月  9 13:18 /dev/nbd5
brw-rw---- 1 root disk 43, 192 10月  9 13:18 /dev/nbd6
brw-rw---- 1 root disk 43, 224 10月  9 13:18 /dev/nbd7
brw-rw---- 1 root disk 43, 256 10月  9 13:18 /dev/nbd8
brw-rw---- 1 root disk 43, 288 10月  9 13:18 /dev/nbd9
3-2.nbdデバイスへの接続

ディスクイメージをnbdデバイスに接続する。

[root@kvm01 ~]# blkid | grep nbd0
[root@kvm01 ~]# qemu-nbd --connect=/dev/nbd0 /var/lib/libvirt/images/${_NODE}.img
[root@kvm01 ~]# blkid | grep nbd0
/dev/nbd0: PTUUID="417f0ae5" PTTYPE="dos"
/dev/nbd0p1: UUID="41619de3-6f19-40cf-b088-27e34d842a53" BLOCK_SIZE="1024" TYPE="ext4" PARTUUID="417f0ae5-01"
/dev/nbd0p2: UUID="64849620-bd0d-48ad-93e3-a2861530fc2e" TYPE="swap" PARTUUID="417f0ae5-02"
/dev/nbd0p3: UUID="2a90a8c7-1221-435d-8a8b-b9e660a70c67" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="417f0ae5-03"

パーティションが見えた。すごい。

4.移行先ディスクの接続

4-1.iSCSIプールの定義

iSCSIプールを定義する。

[root@kvm01 ~]# virsh pool-list --all
 名前       状態       自動起動
-----------------------------------
[root@kvm01 ~]# virsh pool-define-as --name ${_NODE} --type iscsi --source-host 172.16.1.5 --source-dev iqn.2020-09.file01:${_NODE} --target /dev/disk/by-path/
プール guest01 が定義されました
[root@kvm01 ~]# virsh pool-list --all
 名前       状態       自動起動
------------------------------------
 guest01    停止状態   いいえ (no)
4-2.iSCSIプールの起動

iSCSIプールを起動する。裏でiSCSIターゲットへのログインが行われるので前後で状態を確認しておく。

[root@kvm01 ~]# iscsiadm --mode node
iscsiadm: No records found
[root@kvm01 ~]# iscsiadm --mode session
iscsiadm: No active sessions.
[root@kvm01 ~]# virsh pool-start ${_NODE}
プール guest01 が起動されました
[root@kvm01 ~]# virsh pool-autostart ${_NODE}
プール guest01 が自動起動としてマークされました
[root@kvm01 ~]# virsh pool-list --all
 名前       状態       自動起動
-----------------------------------
 guest01    動作中     はい (yes)
[root@kvm01 ~]# iscsiadm --mode node
172.16.1.5:3260,1 iqn.2020-09.file01:guest01
[root@kvm01 ~]# iscsiadm --mode session
tcp: [78] 172.16.1.5:3260,1 iqn.2020-09.file01:guest01 (non-flash)
4-3.ディスクの認識確認

ディスクを認識できていることを確認する。

[root@kvm01 ~]# ls -l /dev/disk/by-path | grep ${_NODE}
lrwxrwxrwx 1 root root  9 10月  9 17:22 ip-172.16.1.5:3260-iscsi-iqn.2020-09.file01:guest01-lun-0 -> ../../sdb
lrwxrwxrwx 1 root root 10 10月  9 17:22 ip-172.16.1.5:3260-iscsi-iqn.2020-09.file01:guest01-lun-0-part1 -> ../../sdb1
lrwxrwxrwx 1 root root 10 10月  9 17:22 ip-172.16.1.5:3260-iscsi-iqn.2020-09.file01:guest01-lun-0-part2 -> ../../sdb2
lrwxrwxrwx 1 root root 10 10月  9 17:22 ip-172.16.1.5:3260-iscsi-iqn.2020-09.file01:guest01-lun-0-part3 -> ../../sdb3

上記よりデバイス名は/dev/sdbだと特定できる。手順の汎用化のため変数_TARGET_DEVに格納しておく。

[root@kvm01 ~]# _TARGET_DEV=$(ls -l /dev/disk/by-path/ip-172.16.1.5\:3260-iscsi-iqn.2020-09.file01\:${_NODE}-lun-0 | sed 's#.*../../#/dev/#')
[root@kvm01 ~]# echo $_TARGET_DEV
/dev/sdb
[root@kvm01 ~]# fdisk -l ${_TARGET_DEV}
ディスク /dev/sdb: 20 GiB, 21474837504 バイト, 41943042 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 524288 バイト
[root@kvm01 ~]# blkid | grep ${_TARGET_DEV}

※blkidではまだ見えない。

5.ディスクの移行

5-1.ディスクの複製

ディスクを複製する。原始的なddを使う。

[root@kvm01 ~]# dd if=/dev/nbd0 of=${_TARGET_DEV} bs=1024 status=progress
2429779968 bytes (2.4 GB, 2.3 GiB) copied, 6 s, 405 MB/s
--- snip ---
21439167488 bytes (21 GB, 20 GiB) copied, 242 s, 88.6 MB/s
20971520+0 レコード入力
20971520+0 レコード出力
21474836480 bytes (21 GB, 20 GiB) copied, 297.242 s, 72.2 MB/s
[root@kvm01 ~]# blkid | grep ${_TARGET_DEV}
/dev/sdb1: UUID="81e8e85e-f169-443b-a525-2294f0c3e1ed" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="000a8874-01"
/dev/sdb2: UUID="ee5a595f-3bf7-48bd-9ba4-b02468b60eab" TYPE="swap" PARTUUID="000a8874-02"
/dev/sdb3: UUID="828fc91e-fa92-4dfc-944c-c4c70ec43cb7" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="000a8874-03"
5-2.nbdデバイスからの切断

移行元ディスクをnbdデバイスから切断する。

[root@kvm01 ~]# qemu-nbd --disconnect /dev/nbd0
/dev/nbd0 disconnected
[root@kvm01 ~]# blkid | grep nbd0

6.ゲストマシンの定義変更

6-1.ゲストマシンからの移行元ディスクの切断

ゲストマシンから移行元ディスクを切断する。

[root@kvm01 ~]# virsh dumpxml guest01
--- snip ---
  <devices>
    <emulator>/usr/libexec/qemu-kvm</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/var/tmp/images/guest01.img'/>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </disk>
--- snip ---

バイス名は上記よりvdaだと特定できる。手順の汎用化のために変数_GUEST_DEVに格納する。

[root@kvm01 ~]# _GUEST_DEV=$(virsh dumpxml ${_NODE} | grep .img -2 | grep "target dev" | sed "s/.*dev='\(.*\)' bus.*/\1/g")
[root@kvm01 ~]# echo $_GUEST_DEV
vda
[root@kvm01 ~]# virsh detach-disk ${_NODE} --target ${_GUEST_DEV} --config
ディスクが正常に切断されました
6-2.ゲストマシンへの移行先ディスクの接続

ゲストマシンへ移行先ディスクを接続する。

[root@kvm01 ~]# virsh attach-disk --domain ${_NODE} --source /dev/disk/by-path/ip-172.16.1.5\:3260-iscsi-iqn.2020-09.file01\:${_NODE}-lun-0 --target vda --io native --cache none --config
ディスクが正常に接続されました
6-3.定義ファイルの差分確認

定義ファイルの差分箇所がディスク関連のみであることを確認する。

[root@kvm01 ~]# diff /etc/libvirt/qemu/${_NODE}.xml{,_$(date +%Y%m%d)}
27c27,29
<   <cpu mode='host-model' check='partial'/>
---
>   <cpu mode='host-model' check='partial'>
>     <model fallback='allow'/>
>   </cpu>
42,44c44,46
<     <disk type='block' device='disk'>
<       <driver name='qemu' type='raw' cache='none' io='native'/>
<       <source dev='/dev/disk/by-path/ip-172.16.1.5:3260-iscsi-iqn.2020-09.file01:guest01-lun-0'/>
---
>     <disk type='file' device='disk'>
>       <driver name='qemu' type='qcow2'/>
>       <source file='/var/lib/libvirt/images/guest01.img'/>

※cpuのmodelの差分は不明だが無影響。

6-4.ゲストマシンの起動

ゲストマシンを起動する。

[root@kvm01 ~]# virsh list
 Id   名前   状態
-------------------
[root@kvm01 ~]# virsh start ${_NODE}
ドメイン guest01 が起動されました
[root@kvm01 ~]# virsh list
 Id   名前      状態
------------------------
 1    guest01   実行中
6-5.ゲストマシンの正常性確認

ログインするなどしてOSが正常に起動していることを確認する。

おまけ

当記事の手順をスクリプト化したものを貼っておく。

#!/bin/sh
#
# img2iscsi.sh
#
#   Usage: img2iscsi.sh <_NODE>
#

# 引数チェック
if [ "$1" = "" ]; then
        echo "Usage: $0 <_NODE>"
        exit 1
fi
_NODE=$1

# 1.iSCSIターゲット/LUNの作成
# 完了している前提とする

# 2.事前作業
ls -l /etc/libvirt/qemu/${_NODE}.xml*
if [ ! -f /etc/libvirt/qemu/${_NODE}.xml_$(date +%Y%m%d) ]; then
        cp -p /etc/libvirt/qemu/${_NODE}.xml{,_$(date +%Y%m%d)}
        ls -l /etc/libvirt/qemu/${_NODE}.xml*
fi

# 3.移行元ディスクの接続
lsmod | grep nbd; if [ $? -ne 0 ]; then modprobe nbd; lsmod | grep nbd; fi
ls -l /dev/nbd0
blkid
qemu-nbd --connect=/dev/nbd0 /var/tmp/images/${_NODE}.img
blkid

# 4.移行先ディスクの接続
virsh pool-list --all
virsh pool-define-as --name ${_NODE} --type iscsi --source-host 172.16.1.5 --source-dev iqn.2020-09.file01:${_NODE} --target /dev/disk/by-path/
virsh pool-start ${_NODE}
virsh pool-autostart ${_NODE}
virsh pool-list --all

_TARGET_DEV=$(ls -l /dev/disk/by-path/ip-172.16.1.5\:3260-iscsi-iqn.2020-09.file01\:${_NODE}-lun-0 | sed 's#.*../../#/dev/#')
echo "_TARGET_DEV: $_TARGET_DEV"

# 5.ディスクの移行
tune2fs -l /dev/nbd0p1 | grep "Block size"
xfs_info /dev/nbd0p3
dd if=/dev/nbd0 of=${_TARGET_DEV} bs=1024 status=progress
blkid
tune2fs -l ${_TARGET_DEV}1 | grep "Block size"
xfs_info ${_TARGET_DEV}3

qemu-nbd --disconnect /dev/nbd0
blkid

# 6.ゲストマシンの定義変更
_GUEST_DEV=$(virsh dumpxml ${_NODE} | grep .img -2 | grep "target dev" | sed "s/.*dev='\(.*\)' bus.*/\1/g")
virsh detach-disk ${_NODE} --target ${_GUEST_DEV} --config

virsh attach-disk --domain ${_NODE} --source /dev/disk/by-path/ip-172.16.1.5\:3260-iscsi-iqn.2020-09.file01\:${_NODE}-lun-0 --target vda --io native --cache none --config

diff /etc/libvirt/qemu/${_NODE}.xml{,_$(date +%Y%m%d)}

virsh list
virsh start ${_NODE}
virsh list

#EOF

参考サイト

oplern.hatenablog.com