なにかの技術メモ置き場

なにかの技術メモ置き場

@インフラエンジニア

QEMU+KVM+iSCSIでライブマイグレーションをする

f:id:none06:20211010153636p:plain

目次

概要

QEMU+KVM+iSCSIな環境でライブマイグレーションを実行する。

経緯

OpenStackのライブマイグレーション機能を試す前に、OpenStack内部で使われているQEMU+KVMで設定と検証をしてみたかった。

環境

概要図

f:id:none06:20211010153636p: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ターゲット
NWアドレス NW名 用途
172.16.0.0/24 管理NW ssh接続、Web管理画面接続
172.16.1.0/24 ストレージNW ストレージ接続(iSCSI)

前提

  • ホストマシンは構築済みとする。
  • ゲストマシンは共有ディスク上にインストールする必要がある。当記事ではiSCSIディスク上を用いる。
  • 共有ディスクの排他ロック機能は使用しない。
    • ゲストOSの多重起動ができてしまう。ファイルシステム破損などが起こりうる。
    • オペミスさえしなければ問題ないが、あまりよろしくないため実装後に追記予定。→こちらで実施済み。

手順

1.ホストマシンの設定

注意

移行元と移行先の双方のホストマシンに対して実施すること。

1-1.ファイアウォールの設定

ライブマイグレーションで使用するポート番号に対して通信を許可する。

[root@kvm02 ~]# firewall-cmd --list-ports
[root@kvm02 ~]# firewall-cmd --add-port=49152-49215/tcp --permanent
success
[root@kvm02 ~]# firewall-cmd --reload
success
[root@kvm02 ~]# firewall-cmd --list-ports
49152-49215/tcp
[root@kvm02 ~]#
補足.ポート番号

ポート番号は以下で定義されている。コメントアウトされているがデフォルト設定だとこの値で動作しているっぽい。

[root@kvm02 ~]# grep migration_port /etc/libvirt/qemu.conf
#migration_port_min = 49152
#migration_port_max = 49215
補足.ゲストマシンへの接続にssh以外を使用している場合

環境に依るが、サービスlibvirtlibvirt-tlsの許可が必要。当環境は該当しないため割愛する。

[root@kvm02 ~]# cat /usr/lib/firewalld/services/libvirt.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>Virtual Machine Management</short>
  <description>Enable this option if you want to allow remote virtual machine management with SASL authentication and encryption (digest-md5 passwords or GSSAPI/Kerberos). The libvirtd service is needed for this option to be useful.</description>
  <port protocol="tcp" port="16509"/>
</service>
[root@kvm02 ~]# grep -R 16509 /etc/
/etc/libvirt/libvirtd.conf:#tcp_port = "16509"
/etc/libvirt/virtproxyd.conf:#tcp_port = "16509"
[root@kvm02 ~]# lsof -i:16509
[root@kvm02 ~]# cat /usr/lib/firewalld/services/libvirt-tls.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>Virtual Machine Management (TLS)</short>
  <description>Enable this option if you want to allow remote virtual machine management with TLS encryption, x509 certificates and optional SASL authentication. The libvirtd service is needed for this option to be useful.</description>
  <port protocol="tcp" port="16514"/>
</service>
[root@kvm02 ~]# grep -R 16514 /etc/
/etc/libvirt/libvirtd.conf:#tls_port = "16514"
/etc/libvirt/virtproxyd.conf:#tls_port = "16514"
[root@kvm02 ~]# lsof -i:16514

2.ゲストマシンの準備

2-1.ゲストマシンの準備

ゲストマシンを準備する。

  • すでにiSCSIディスク上にゲストマシンが存在する場合は不要。
  • ローカルディスク上に存在するゲストマシンをiSCSIディスク上に移行する場合はこちらを参照。
  • ゲストマシンをiSCSIディスク上に新規作成する場合はこちらを参照。
2-2.iSCSIディスクへの接続(ホストマシン)

ゲストマシンの準備の副産物として、ホストマシンからiSCSIディスクへの接続設定がホストマシン上に残る。この設定はライブマイグレーションされないものの必要なため、もう1台のホストマシンでも同様に設定(iSCSIプールの作成と起動)をする。

3.ライブマイグレーション

3-1.ライブマイグレーションの実行

ライブマイグレーションを実行する。オプションの意味は以下。*3

・ --persistent - ドメインを移動先ホスト物理マシンでもそのまま永続的な状態に維持します。
・ --undefinesource - ソースのホスト物理マシンのゲスト仮想マシンを削除します。
・ --verbose - 移行実施中の進捗状況を表示します。

移行元画面:

ライブマイグレーションを実行する。

[root@kvm02 ~]# virsh migrate --domain guest01 --live --persistent --undefinesource qemu+ssh://kvm03/system --verbose
マイグレーション: [100 %]

ゲストマシンが消える。

[root@kvm02 ~]# virsh list --all
 Id   名前           状態
-----------------------------------

定義ファイルも消える。

[root@kvm02 ~]# ls -l /etc/libvirt/qemu/guest01.xml
ls: '/etc/libvirt/qemu/guest01.xml' にアクセスできません: そのようなファイルやディレクトリはありません
移行先画面:

ライブマイグレーション実行後、ゲストマシンが起動する。

[root@kvm03 ~]# virsh list
 Id   名前      状態
------------------------
 1    guest01   実行中

定義ファイルも生成される。

[root@kvm03 ~]# ls -l /etc/libvirt/qemu/guest01.xml
-rw------- 1 root root 5617 10月 10 11:30 /etc/libvirt/qemu/guest01.xml
疎通確認用サーバ画面:

事前にpingを実行しておく。ライブマイグレーション中は応答がなくなる。

[root@linux01 ~]# ping 172.16.0.253
PING 172.16.0.253 (172.16.0.253) 56(84) bytes of data.
--- snip ---
64 bytes from 172.16.0.253: icmp_seq=12 ttl=64 time=2.52 ms
64 bytes from 172.16.0.253: icmp_seq=13 ttl=64 time=2.30 ms
64 bytes from 172.16.0.253: icmp_seq=14 ttl=64 time=2.57 ms # ここでしばらく止まる
64 bytes from 172.16.0.253: icmp_seq=39 ttl=64 time=1.23 ms # ここから再開する
64 bytes from 172.16.0.253: icmp_seq=40 ttl=64 time=0.729 ms
64 bytes from 172.16.0.253: icmp_seq=41 ttl=64 time=0.710 ms
3-2.ライブマイグレーションの実行(逆方向)
移行先画面:
[root@kvm03 ~]# virsh migrate --domain guest01 --live --persistent --undefinesource qemu+ssh://kvm02/system --verbose

マイグレーション: [100 %]
[root@kvm03 ~]# virsh list --all
 Id   名前   状態
-------------------
[root@kvm03 ~]# ls -l /etc/libvirt/qemu/guest01.xml
ls: '/etc/libvirt/qemu/guest01.xml' にアクセスできません: そのようなファイルやディレクトリはありません
移行先画面:
[root@kvm02 ~]# virsh list
 Id   名前      状態
------------------------
 10   guest01   実行中
[root@kvm02 ~]# ls -l /etc/libvirt/qemu/guest01.xml
-rw------- 1 root root 5617 10月 10 11:30 /etc/libvirt/qemu/guest01.xml
疎通確認用サーバ画面:
[root@linux01 ~]# ping 172.16.0.253
PING 172.16.0.253 (172.16.0.253) 56(84) bytes of data.
--- snip ---
64 bytes from 172.16.0.253: icmp_seq=47 ttl=64 time=2.42 ms
64 bytes from 172.16.0.253: icmp_seq=48 ttl=64 time=2.64 ms
64 bytes from 172.16.0.253: icmp_seq=49 ttl=64 time=2.91 ms # ここでしばらく止まる
64 bytes from 172.16.0.253: icmp_seq=72 ttl=64 time=1041 ms # ここから再開する
64 bytes from 172.16.0.253: icmp_seq=73 ttl=64 time=1.19 ms
64 bytes from 172.16.0.253: icmp_seq=74 ttl=64 time=0.872 ms
補足.移行元と移行先のホストマシンのCPUが異なる場合

当環境では以下のエラーが出た。

[root@kvm02 ~]# virsh migrate --domain guest01 --live qemu+ssh://kvm03/system --verbose
エラー: 操作は失敗しました: guest CPU doesn't match specification: missing features: vmx,fma,movbe,bmi1,avx2,bmi2,invpcid,pdpe1gb,abm

ひとまず以下の対処によりエラーを回避できた。

[root@kvm02 ~]# virsh shutdown guest01
ドメイン guest01 はシャットダウン中です
[root@kvm02 ~]# virsh list
 Id   名前   状態
-------------------
[root@kvm02 ~]# virsh edit guest01
ドメイン guest01 XML の設定は編集されました
  • 変更前
  <cpu mode='host-model' check='partial'/>
  • 変更後
  <cpu mode='host-model' check='partial'>
    <feature policy='disable' name='vmx'/>
    <feature policy='disable' name='fma'/>
    <feature policy='disable' name='movbe'/>
    <feature policy='disable' name='bmi1'/>
    <feature policy='disable' name='avx2'/>
    <feature policy='disable' name='bmi2'/>
    <feature policy='disable' name='invpcid'/>
    <feature policy='disable' name='pdpe1gb'/>
    <feature policy='disable' name='abm'/>
  </cpu>
[root@kvm02 ~]# virsh start guest01
ドメイン guest01 が起動されました
[root@kvm02 ~]# virsh list
 Id   名前      状態
------------------------
 9    guest01   実行中

不足しているfeaturesをfeature policy='disable'としてひたすら登録しただけなので暫定対処としか思えない。恒久対処は、/usr/share/libvirt/cpu_map/にCPUのモデルの定義が格納されているため、双方のホストマシンが対応するモデルを特定してゲストマシンに設定するべきだと思う。

補足

ゲストマシンへのping結果を見ると30secほどのダウンタイムが発生しているように見える。これを"ライブ"マイグレーションと呼べるのかと疑念を抱かれかねないため、追加で検証した。

結論

  • OSはダウンタイムなしに稼働している(すごい)。
  • TCPセッションは維持されている。一時的にレスポンスがなくなるが、TCP再送により復帰する(すごい)。
  • UDPやICMPはロストする。ICMPの結果はpingにて確認済み。

検証1.TCP

ゲストマシンにssh接続した状態でライブマイグレーションを実行した。レスポンスの可視化のためにゲストマシン上で1sec間隔でuptimeコマンドを実行した。

[root@guest01 ~]# while :; do uptime; sleep 1; done
 10:07:53 up 9 min,  1 user,  load average: 0.00, 0.00, 0.00
 10:07:54 up 9 min,  1 user,  load average: 0.00, 0.00, 0.00
 10:07:55 up 9 min,  1 user,  load average: 0.00, 0.00, 0.00
 10:07:56 up 9 min,  1 user,  load average: 0.00, 0.00, 0.00
 10:07:57 up 9 min,  1 user,  load average: 0.00, 0.00, 0.00
 10:07:58 up 9 min,  1 user,  load average: 0.00, 0.00, 0.00
 10:07:59 up 9 min,  1 user,  load average: 0.00, 0.00, 0.00 # ここでしばらく表示が止まる
 10:08:00 up 9 min,  1 user,  load average: 0.00, 0.00, 0.00 # sshセッション復帰後一気に表示される
 10:08:01 up 9 min,  1 user,  load average: 0.00, 0.00, 0.00
 10:08:02 up 9 min,  1 user,  load average: 0.00, 0.00, 0.00

マイグレーション中はsshクライアントへの出力が止まったが、sshセッション復帰後に止まっていた部分も含めて一気に出力が再開した。

検証2.UDP

ゲストマシンに1sec間隔でsnmpwalkを実行しながらライブマイグレーションを実行した。

[root@linux01 ~]# while :; do snmpwalk -cpublic -v2c 172.16.0.253 uptime; sleep 1; done
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (44539) 0:07:25.39
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (44687) 0:07:26.87
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (44834) 0:07:28.34
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (44982) 0:07:29.82
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (45130) 0:07:31.30
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (45279) 0:07:32.79
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (45427) 0:07:34.27
Timeout: No Response from 172.16.0.253
Timeout: No Response from 172.16.0.253
Timeout: No Response from 172.16.0.253
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (48018) 0:08:00.18
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (48165) 0:08:01.65
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (48313) 0:08:03.13

参考サイト

https://soar.keizof.com/wp/?p=169 www.server-world.info blogger.fastriver.net access.redhat.com access.redhat.com access.redhat.com access.redhat.com