なにかの技術メモ置き場

なにかの技術メモ置き場

@インフラエンジニア

QEMU+KVM+iSCSI環境でゲストマシンの多重起動を防止する

f:id:none06:20211013220931p:plain

目次

概要

QEMU+KVM環境でゲストマシンの多重起動を防止する。virtlockdの排他ロック機能を導入する。

経緯

前回の記事でライブマイグレーションの環境を構築したが、共有ディスクがiSCSIのため排他ロックの概念がなく、複数のホストマシンから同一ゲストマシンの多重起動ができてしまうリスクがあった。今回の記事ではそのリスクに対処する。

環境

概要図

f:id:none06:20211013220931p:plain

構成

ホスト名 管理NWのIP ストレージNWのIP OS H/W 備考
kvm02 172.16.0.206 172.16.1.206 CentOS 8.4.2105 Fujitsu TX1320 M1 KVMホスト(移行元)
kvm03 172.16.0.207 172.16.1.207 CentOS 8.4.2105 Fujitsu TX120 S3 KVMホスト(移行先)
guest01 172.16.0.253 - CentOS 8.4.2105 - KVMゲスト
linux01 任意 - CentOS 7.9.2009 - KVMゲストへの疎通確認用Linux
file01 172.16.0.5 172.16.1.5 RAIDiator 4.2.31 NETGEAR ReadyNAS Pro 2 iSCSIターゲット、NFSサーバ
NWアドレス NW名 用途
172.16.0.0/24 管理NW ssh接続、Web管理画面接続
172.16.1.0/24 ストレージNW ストレージ接続(iSCSI/NFS)

前提

  • NFSサーバを構築済みとする。

手順

1.NFSサーバの設定

1-1.NFS領域の公開

以下のディレクトリを作成し公開する。設定方法は環境に依る。

/nfs/virt-lockd

2.ホストマシンの設定

注意

両方のホストマシンに対して実施すること。

2-1.fstabの編集

fstabにNFS領域のマウント定義を追記する。

[root@kvm02 ~]# ls -l /etc/fstab*
-rw-r--r--. 1 root root 734 10月  6 20:24 /etc/fstab
[root@kvm02 ~]# cp -p /etc/fstab{,_$(date +%Y%m%d)}
[root@kvm02 ~]# ls -l /etc/fstab*
-rw-r--r--. 1 root root 734 10月  6 20:24 /etc/fstab
-rw-r--r--  1 root root 734 10月  6 20:24 /etc/fstab_20211012
[root@kvm02 ~]# cat << EOF >> /etc/fstab
>
> # virtlockd
> file012:/nfs/virt-lockd /var/lib/libvirt/lockd nfs vers=3,defaults 0 0
> EOF
[root@kvm02 ~]# diff /etc/fstab{,_$(date +%Y%m%d)}
19,21d18
<
< # virtlockd
< file012:/nfs/virt-lockd /var/lib/libvirt/lockd nfs vers=3,defaults 0 0

※当環境のNFSサーバはNFSv3のためvers=3オプションを付与している。

2-2.マウントポイントの作成

マウントポイントを作成する。

[root@kvm02 ~]# mkdir /var/lib/libvirt/lockd
[root@kvm02 ~]# ls -l /var/lib/libvirt/lockd
合計 0
2-3.マウントの実行

マウントする。マウントポイント名だけを指定することで、マウント元はfstabから読み取らせてfstabの動作確認を兼ねる。

[root@kvm02 ~]# df -hT | grep /var/lib/libvirt/lockd
[root@kvm02 ~]# mount /var/lib/libvirt/lockd
[root@kvm02 ~]# df -hT | grep /var/lib/libvirt/lockd
file012:/nfs/virt-lockd nfs        7.3T  5.0T  2.3T   69% /var/lib/libvirt/lockd
2-4.ロック機能の有効化

qemu.confを編集し、ロック機能を有効化する。

[root@kvm02 ~]# ls -l /etc/libvirt/qemu.conf*
-rw-r--r-- 1 root root 31778  8月 11 05:57 /etc/libvirt/qemu.conf
[root@kvm02 ~]# cp -p /etc/libvirt/qemu.conf{,_$(date +%Y%m%d)}
[root@kvm02 ~]# ls -l /etc/libvirt/qemu.conf*
-rw-r--r-- 1 root root 31778  8月 11 05:57 /etc/libvirt/qemu.conf
-rw-r--r-- 1 root root 31778  8月 11 05:57 /etc/libvirt/qemu.conf_20211012
[root@kvm02 ~]# sed -i -e '/^#lock_manager/s/#//g' /etc/libvirt/qemu.conf
[root@kvm02 ~]# diff /etc/libvirt/qemu.conf{,_$(date +%Y%m%d)}
668c668
< lock_manager = "lockd"
---
> #lock_manager = "lockd"

qemu-lockd.confを編集し、ロックファイルの作成先を定義する。

[root@kvm02 ~]# ls -l /etc/libvirt/qemu-lockd.conf*
-rw-r--r-- 1 root root 2169  8月 11 05:59 /etc/libvirt/qemu-lockd.conf
[root@kvm02 ~]# cp -p /etc/libvirt/qemu-lockd.conf{,_$(date +%Y%m%d)}
[root@kvm02 ~]# ls -l /etc/libvirt/qemu-lockd.conf*
-rw-r--r-- 1 root root 2169  8月 11 05:59 /etc/libvirt/qemu-lockd.conf
-rw-r--r-- 1 root root 2169  8月 11 05:59 /etc/libvirt/qemu-lockd.conf_20211012
[root@kvm02 ~]# sed -i \
> -e '/^#require_lease_for_disks/s/#//g' \
> -e '/^#file_lockspace_dir/s/#//g' \
> -e '/^#lvm_lockspace_dir/s/#//g' \
> -e '/^#scsi_lockspace_dir/s/#//g' \
> /etc/libvirt/qemu-lockd.conf
[root@kvm02 ~]# diff /etc/libvirt/qemu-lockd.conf{,_$(date +%Y%m%d)}
17c17
< require_lease_for_disks = 1
---
> #require_lease_for_disks = 1
39c39
< file_lockspace_dir = "/var/lib/libvirt/lockd/files"
---
> #file_lockspace_dir = "/var/lib/libvirt/lockd/files"
53c53
< lvm_lockspace_dir = "/var/lib/libvirt/lockd/lvmvolumes"
---
> #lvm_lockspace_dir = "/var/lib/libvirt/lockd/lvmvolumes"
67c67
< scsi_lockspace_dir = "/var/lib/libvirt/lockd/scsivolumes"
---
> #scsi_lockspace_dir = "/var/lib/libvirt/lockd/scsivolumes"

virtlockdサービスが停止していることを確認する。

[root@kvm02 ~]# systemctl is-active virtlockd.service
inactive

ロックファイル格納ディレクトリが存在しないことを確認する。

[root@kvm02 ~]# ls -l /var/lib/libvirt/lockd
合計 0

libvirtdサービスを再起動する。

[root@kvm02 ~]# systemctl is-active libvirtd.service
active
[root@kvm02 ~]# systemctl restart libvirtd.service
[root@kvm02 ~]# systemctl is-active libvirtd.service
active

連動してvirtlockdサービスも起動される。

[root@kvm02 ~]# systemctl is-active virtlockd.service
active

ロックファイル格納ディレクトリが作成されていることを確認する。数秒かかる可能性がある。

[root@kvm02 ~]# ls -l /var/lib/libvirt/lockd
合計 12
drwx------ 2 nobody nobody 4096 10月 13 19:50 files
drwx------ 2 nobody nobody 4096 10月 13 19:50 lvmvolumes
drwx------ 2 nobody nobody 4096 10月 13 19:50 scsivolumes
[root@kvm02 ~]# ls -lR /var/lib/libvirt/lockd
/var/lib/libvirt/lockd:
合計 12
drwx------ 2 nobody nobody 4096 10月 13 19:50 files
drwx------ 2 nobody nobody 4096 10月 13 19:50 lvmvolumes
drwx------ 2 nobody nobody 4096 10月 13 19:50 scsivolumes

/var/lib/libvirt/lockd/files:
合計 0

/var/lib/libvirt/lockd/lvmvolumes:
合計 0

/var/lib/libvirt/lockd/scsivolumes:
合計 0

※所有者・所有グループがnobody nobodyなのはNASの設定。

3.動作確認

3-1.ゲストマシンの起動

1台目のホストマシンでゲストマシンを起動する。

[root@kvm02 ~]# virsh start guest01
ドメイン guest01 が起動されました

ロックファイルが作成されていることを確認する。なお、今回はiSCSIディスクなのでscsivolumesにしか作成されない。

[root@kvm02 ~]# ls -l /var/lib/libvirt/lockd/scsivolumes/
合計 0
-rw------- 1 nobody nobody 0 10月 13 19:51 360014052e1170401087d041000000000
3-2.排他ロックの動作確認

2台目のホストマシンからロックファイルが見えていることを確認する。

[root@kvm03 ~]# ls -l /var/lib/libvirt/lockd/scsivolumes/
合計 0
-rw------- 1 nobody nobody 0 10月 13 19:51 360014052e1170401087d041000000000

2台目のホストマシンからゲストマシンを多重起動する。

[root@kvm03 ~]# virsh list
 Id   名前   状態
-------------------
[root@kvm03 ~]# virsh start guest01
エラー: ドメイン guest01 の起動に失敗しました
エラー: resource busy: ロック空間のリソース '360014052e1170401087d041000000000' がロックされています
[root@kvm03 ~]# virsh list
 Id   名前   状態
-------------------

排他ロックが機能し、ゲストマシンの多重起動を防止することができた。

補足1

ゲストマシンを停止するとロックファイルが削除される。

[root@kvm02 ~]# ls -l /var/lib/libvirt/lockd/scsivolumes/
合計 0
-rw------- 1 nobody nobody 0 10月 13 20:05 360014052e1170401087d041000000000
[root@kvm02 ~]# virsh shutdown guest01
ドメイン guest01 はシャットダウン中です
[root@kvm02 ~]# virsh list
 Id   名前   状態
-------------------
[root@kvm02 ~]# ls -l /var/lib/libvirt/lockd/scsivolumes/
合計 0
補足2

ロックファイルのファイル名はディスクのデバイスIDに由来している。ディスク側で値を持っているため、ホストマシンが異なってもファイル名が変わることはない。

[root@kvm02 ~]# ls -l /dev/disk/by-id/ | grep 360014052e1170401087d041000000000
lrwxrwxrwx 1 root root   9 10月 13 20:08 scsi-360014052e1170401087d041000000000 -> ../../sdl
lrwxrwxrwx 1 root root  10 10月 13 20:08 scsi-360014052e1170401087d041000000000-part1 -> ../../sdl1
lrwxrwxrwx 1 root root  10 10月 13 20:08 scsi-360014052e1170401087d041000000000-part2 -> ../../sdl2
lrwxrwxrwx 1 root root  10 10月 13 20:08 scsi-360014052e1170401087d041000000000-part3 -> ../../sdl3
[root@kvm02 ~]# ls -l /dev/disk/by-path/ | grep sdl
lrwxrwxrwx 1 root root  9 10月 13 20:08 ip-172.16.1.5:3260-iscsi-iqn.2020-09.file01:guest01-lun-0 -> ../../sdl
lrwxrwxrwx 1 root root 10 10月 13 20:08 ip-172.16.1.5:3260-iscsi-iqn.2020-09.file01:guest01-lun-0-part1 -> ../../sdl1
lrwxrwxrwx 1 root root 10 10月 13 20:08 ip-172.16.1.5:3260-iscsi-iqn.2020-09.file01:guest01-lun-0-part2 -> ../../sdl2
lrwxrwxrwx 1 root root 10 10月 13 20:08 ip-172.16.1.5:3260-iscsi-iqn.2020-09.file01:guest01-lun-0-part3 -> ../../sdl3

/etc/libvirt/qemu-lockd.confにちゃんと書いてあった。

#
# When using SCSI volumes that can be visible across
# multiple, it is desirable to do locking based on
# the unique UUID associated with each volume, instead
# of their paths. Setting this path causes libvirt to
# do UUID based locking for SCSI.
#
# Typically this directory would be located on a shared
# filesystem visible to all hosts accessing the same
# storage.
#
scsi_lockspace_dir = "/var/lib/libvirt/lockd/scsivolumes"

参考記事

https://soar.keizof.com/wp/?p=157
今回の設定方法はググっても上記記事しか見つからなかった。RHELの公式ドキュメントもgoogleの検索対象なのでそこにもないと思われる。貴重な情報に感謝する。
併せて、公式ドキュメントを読む姿勢と、ドキュメントがない場合はmanや定義ファイルのコメントを読む姿勢、いずれも不足していたと痛感した。