| name | linstor-migration |
| description | LINSTOR/DRBD マルチリージョン VM マイグレーション。ライブマイグレーション、コールドマイグレーション、リージョン廃止・追加を行う。 |
| argument-hint | <subcommand: live-migrate|cold-migrate|decommission-region|add-region|setup-dr> |
LINSTOR マイグレーションスキル
LINSTOR/DRBD マルチリージョン環境での VM マイグレーション操作を行う。
| サブコマンド | 用途 |
|---|
live-migrate <vmid> <target_node> | リージョン内ライブマイグレーション (Protocol C, ゼロダウンタイム) |
cold-migrate <vmid> <source_region> <target_region> | リージョン間コールドマイグレーション (VM 停止必要) |
decommission-region <region> | リージョン廃止 (全 VM 移行 + ノード削除) |
add-region <region> | リージョン追加 + DR レプリカ設定 |
setup-dr <vmid> <dr_node> | DR レプリカの追加 (2+1 構成) |
前提条件
- LINSTOR マルチリージョン構成済み (
scripts/linstor-multiregion-setup.sh 実行済み)
- 各ノードに
Aux/site プロパティが設定済み
- リージョン内: Protocol C + allow-two-primaries=yes
- リージョン間: Protocol A + allow-two-primaries=no
設定値の読み取り
YQ="${PROJECT_DIR}/bin/yq"
CONFIG="config/linstor.yml"
CONTROLLER_IP=$("$YQ" '.controller_ip' "$CONFIG")
トポロジー: 2+1 構成
Region A (Protocol C) Region B (Protocol C)
[Node 4] ←→ [Node 5] ←→ [Node 6] [Node 7] ←→ [Node 8] ←→ [Node 9]
←──── Protocol A (DR) ────→
- リージョン内: 2レプリカ (Protocol C, allow-two-primaries=yes) → ライブマイグレーション可能
- リージョン間: 1レプリカ (Protocol A, allow-two-primaries=no) → DR 用、非同期レプリケーション
サブコマンド: live-migrate
リージョン内のノード間で VM をゼロダウンタイムで移行する。
pve-lock: 必須
前提条件
- 移行元・移行先が同一リージョン内 (Protocol C + allow-two-primaries=yes)
- 両ノードに DRBD リソースが UpToDate で存在
- CPU タイプが
kvm64 (異種ハードウェア間の場合)
手順
-
事前状態記録:
ssh root@$SOURCE_IP "qm status $VMID"
ssh root@$CONTROLLER_IP "drbdsetup status --verbose"
ssh $VM_USER@$VM_MGMT_IP "uptime"
-
ライブマイグレーション実行:
./pve-lock.sh run ./oplog.sh ssh root@$SOURCE_IP "qm migrate $VMID $TARGET_NODE --online"
-
事後検証:
ssh root@$SOURCE_IP "qm status $VMID"
ssh $VM_USER@$VM_MGMT_IP "uptime"
ssh $VM_USER@$VM_MGMT_IP "md5sum -c checksums.txt"
ssh root@$CONTROLLER_IP "drbdsetup status --verbose"
実測値
| 方向 | ダウンタイム (1回目) | ダウンタイム (2回目) | 備考 |
|---|
| 6号機 → 7号機 | 73ms / 911 MiB / 18秒 | 37ms / 834 MiB / 17秒 | 平均 55ms |
| 7号機 → 6号機 | 33ms / 349 MiB / 11秒 | 74ms / 844 MiB / 15秒 | 平均 53.5ms |
注記: 旧リージョン構成 (Region B: 6+7号機) 時の実測値。
サブコマンド: cold-migrate
リージョン間で VM を移行する (VM 停止が必要)。
pve-lock: 必須
手順
-
移行先リージョンに2レプリカを確保:
ssh root@$CONTROLLER_IP "linstor resource create $TARGET_NODE2 $RESOURCE_NAME"
ssh root@$CONTROLLER_IP "linstor node-connection path create $SOURCE_NODE $TARGET_NODE cross-region default default"
./scripts/linstor-multiregion-setup.sh setup config/linstor.yml
-
VM 停止:
./pve-lock.sh run ./oplog.sh ssh root@$SOURCE_NODE_IP "qm stop $VMID"
-
移行元リージョンのレプリカ削除:
ssh root@$CONTROLLER_IP "linstor resource delete $SOURCE_NODE1 $RESOURCE_NAME"
ssh root@$CONTROLLER_IP "linstor resource delete $SOURCE_NODE2 $RESOURCE_NAME"
-
VM config を移行先 PVE クラスタに再作成:
ssh root@$SOURCE_NODE_IP "rm /etc/pve/qemu-server/$VMID.conf"
ssh root@$TARGET_NODE_IP "qm create $VMID --name $VM_NAME --memory $MEM --cores $CORES --cpu kvm64 --net0 virtio=$MAC0,bridge=vmbr1 --net1 virtio=$MAC1,bridge=vmbr0 --ostype l26 --scsihw virtio-scsi-single"
ssh root@$TARGET_NODE_IP "qm set $VMID --scsi0 linstor-storage:${RESOURCE_NAME}_${VMID},discard=on,iothread=1,size=$DISK_SIZE"
ssh root@$TARGET_NODE_IP "qm set $VMID --boot order=scsi0"
ssh root@$TARGET_NODE_IP "qm set $VMID --ipconfig1 ip=$VM_MGMT_IP/$PREFIX,gw=$GW"
-
VM 起動 + 検証:
./pve-lock.sh run ./oplog.sh ssh root@$TARGET_NODE_IP "qm start $VMID"
ssh $VM_USER@$VM_MGMT_IP "md5sum -c checksums.txt"
-
DR レプリカの再設定 (移行元リージョンに):
ssh root@$CONTROLLER_IP "linstor resource create $DR_NODE $RESOURCE_NAME"
./scripts/linstor-multiregion-setup.sh setup config/linstor.yml
重要な発見事項
qm set --scsi0 linstor-storage:<resource_name> は PVE クロスクラスタで動作する
- vzdump/qmrestore は不要。既存 LINSTOR リソースを直接アタッチできる
qm destroy は LINSTOR リソースも削除するため使用禁止。rm /etc/pve/qemu-server/*.conf を使う
- MAC アドレスを保持しないと VM のネットワーク設定が変わる
サブコマンド: decommission-region
リージョンの全 VM を移行し、ノードを LINSTOR から削除する。
pve-lock: 必須
手順
- 全 VM をコールドマイグレーション (cold-migrate サブコマンド参照)
- ノードを LINSTOR から削除:
./scripts/linstor-multiregion-node.sh remove $NODE config/linstor.yml
サブコマンド: add-region
LINSTOR にリージョンを追加し、DR レプリカを設定する。
pve-lock: 必須
手順
-
ノードを LINSTOR に登録:
ssh root@$CONTROLLER_IP "linstor node create $NODE $NODE_IP --node-type Satellite"
sleep 10
-
ストレージプール作成 (ZFS):
ssh root@$CONTROLLER_IP "linstor storage-pool create zfs $NODE zfs-pool linstor_zpool"
注: satellite 再起動直後は ZFS プロバイダが検出されないことがある。数秒待ってリトライ。
-
リージョンプロパティ + auto-eviction 無効化:
ssh root@$CONTROLLER_IP "linstor node set-property $NODE Aux/site $REGION"
ssh root@$CONTROLLER_IP "linstor node set-property $NODE DrbdOptions/AutoEvictAllowEviction false"
-
cross-region パス作成:
ssh root@$CONTROLLER_IP "linstor node-connection path create $EXISTING_NODE $NEW_NODE cross-region default default"
-
DR レプリカ追加 + Protocol A 設定:
ssh root@$CONTROLLER_IP "linstor resource create $NODE $RESOURCE_NAME"
./scripts/linstor-multiregion-setup.sh setup config/linstor.yml
サブコマンド: setup-dr
既存リソースに DR レプリカを追加し、2+1 構成にする。
pve-lock: 必須
手順
-
cross-region パスの確認・作成:
ssh root@$CONTROLLER_IP "linstor node-connection path list $SOURCE_NODE $DR_NODE"
ssh root@$CONTROLLER_IP "linstor node-connection path create $SOURCE_NODE $DR_NODE cross-region default default"
-
DR レプリカ作成:
ssh root@$CONTROLLER_IP "linstor resource create $DR_NODE $RESOURCE_NAME"
-
Protocol A 設定:
./scripts/linstor-multiregion-setup.sh setup config/linstor.yml
-
DRBD 同期待ち:
ssh root@$CONTROLLER_IP "linstor resource list -r $RESOURCE_NAME"
既知の失敗と対策
| ID | 失敗 | サブコマンド | 検出方法 | 対策 |
|---|
| M1 | qm migrate --online が LINSTOR ディスクで失敗 | live-migrate | エラー出力 | 両ノードに diskful リソースが存在するか linstor resource list で確認 |
| M2 | メモリ転送タイムアウト | live-migrate | タイムアウトエラー | --migration_network で 10.x を指定 |
| M3 | CPU タイプ host で異種ハードウェア間マイグレーション失敗 | live-migrate | Failed to set special registers | CPU タイプを kvm64 に変更 |
| M4 | vendor snippet 未配置 | live-migrate | volume 'local:snippets/...' does not exist | 移行先ノードに snippet をコピー |
| M5 | DR レプリカが一時的に Outdated | live-migrate | drbdsetup status | Protocol A の非同期性により正常。自動復帰する |
| C1 | qm set --scsi0 linstor-storage:X がクロスクラスタで動作 | cold-migrate | - | 実証済み: vzdump 不要 |
| C2 | PrefNic=ib0 で DRBD がリージョン間接続を IB アドレスにバインド | cold-migrate/setup-dr | Connecting 状態が継続 | cross-region パスを default インターフェースで作成 |
| C3 | node remove/re-add 後にパスが stale | add-region | Network interface 'default' does not exist | パスを delete + recreate |
| C4 | replicas-on-same "Aux/site" が Aux/Aux/site に二重プレフィックス | - | resource-group list-properties | --replicas-on-same site (Aux/ なし) を使用 |
| C5 | cloudinit ディスクのアタッチ不要 | cold-migrate | - | 初回起動済みのため cloudinit スキップ可 |
| C6 | DRBD フルシンクがネットワーク帯域を飽和 | cold-migrate | SSH 遅延 | c-max-rate で帯域制限 |
| C7 | パス作成時の PeerClosingConnectionException | add-region | exit code 10 + エラー出力 | パスを delete + recreate (2回目の create で安定) |
| C8 | ストライプ/非ストライプ間の LV サイズ不一致 | add-region, cold-migrate | The peer's disk size is too small! + StandAlone | リソース削除 → 手動 LV 作成 (正しい PE 数) → 再作成 |
C2: PrefNic と cross-region パス
両リージョンとも PrefNic が IB インターフェースに設定済み (Region A: ibp134s0, Region B: ibp10s0)。
DRBD はデフォルトで IB アドレス (192.168.100.x) にバインドする。
cross-region 接続は IB ではなくデフォルトインターフェース (10.x Ethernet) 経由で行う。
注: LINSTOR に登録するインターフェース名は OS のデバイス名を使う (ip link show type ipoib で確認)。ib0 ではない。
解決策: node-connection path create で cross-region ペアに default インターフェースを指定:
ssh root@$CONTROLLER_IP "linstor node-connection path create nodeA nodeB cross-region default default"
default は LINSTOR のデフォルトネットワークインターフェース (10.x) を使う。IB ではなく Ethernet で接続される。
C3: node remove/re-add 後の stale パス
LINSTOR からノードを削除して再追加すると、ノードの UUID が変わる。既存のパスは古い UUID を参照しており、
Network interface 'default' of node 'X' does not exist! エラーが発生する。
解決策: パスを削除して再作成:
ssh root@$CONTROLLER_IP "linstor node-connection path delete nodeA nodeB cross-region"
ssh root@$CONTROLLER_IP "linstor node-connection path create nodeA nodeB cross-region default default"
C7: パス作成時の PeerClosingConnectionException
ノード remove/re-add 直後に node-connection path create を実行すると、PeerClosingConnectionException が発生することがある。
パス自体は作成されるが、衛星ノードへの DRBD adjust が失敗し、後続のリソース作成で C3 エラーが発生する。
発生条件: ノード再登録直後のパス作成 (衛星ノードとの通信が不安定な場合)
再現性: 2回のテストで確認。発生するパスは一定ではない (条件依存)
確定対策手順:
ssh root@$CONTROLLER_IP "linstor node-connection path create nodeA nodeB cross-region default default"
ssh root@$CONTROLLER_IP "linstor node-connection path delete nodeA nodeB cross-region"
ssh root@$CONTROLLER_IP "linstor node-connection path create nodeA nodeB cross-region default default"
C8: ストライプ/非ストライプ間の LV サイズ不一致
(注: 2026-03-30 に全ノード ZFS raidz1 に統一したため、LVM ストライプ/非ストライプ間のサイズ不一致問題は解消。ZFS 統一構成では --storage-pool zfs-pool を指定すれば正常にリソース作成可能。)
C9: ZFS zvol ライブリサイズの不安定性
qm resize で DRBD 上の ZFS zvol をリサイズすると、一部ノードで DRBD adjust が失敗し Resizing 状態でスタックすることがある。
対策: VM ディスクサイズは作成時に確定する。ライブリサイズが必要な場合は新しいディスクを追加してデータ移行する。
oplog
状態変更操作は ./oplog.sh で記録する:
- live-migrate: qm migrate
- cold-migrate: qm stop, qm start, resource create/delete
- decommission-region: node remove
- add-region: node create, resource create
pve-lock の使い方
全サブコマンドで状態変更操作に ./pve-lock.sh を使用する:
./pve-lock.sh run <command...>
./pve-lock.sh wait <command...>
関連スクリプト
| スクリプト | 用途 |
|---|
scripts/linstor-multiregion-setup.sh setup | Aux/site 設定 + リージョン間 Protocol A 設定 |
scripts/linstor-multiregion-node.sh add/remove | ノードのリージョン追加/削除 |
scripts/linstor-multiregion-status.sh | マルチリージョン状態表示 |