Supermicro X11DPU/X10DRT-P BIOS Setup 操作。KVM スクリーンショット + キーストロークで BIOS メニューを操作する。BIOS 設定変更、確認、保存を行う。4-6号機 + 10号機対応。
linstor-bench
LINSTOR/DRBD ストレージベンチマーク。VM上でfioを実行し、thin/thick-stripe構成の性能を計測する。
含まれるファイル(1)
- SKILL.md30.3 KB
SKILL.md(原文)
インストールする前に、エージェントに与えられる指示の中身を確認できます。
LINSTOR ベンチマークスキル
LINSTOR/DRBD ストレージ上に VM を作成し、fio でベンチマークを実行する。
引数 storage_type で thin (LVM thin pool) または thick-stripe (LVM 4本ストライプ) を選択する。
オプションで region を指定して特定リージョンでベンチマークを実行する。
マルチリージョン構成
| リージョン | ノード | DRBD通信 | 特徴 |
|---|---|---|---|
| region-a | 4号機 + 5号機 + 6号機 | IPoIB 192.168.100.x | InfiniBand 高速通信 |
| region-b | 7号機 + 8号機 + 9号機 | IPoIB 192.168.100.x | InfiniBand 高速通信 |
region 指定時は、そのリージョンの最初のノードに VM を配置し、同リージョン内の2ノードで DRBD レプリケーションを行う。
config/linstor.yml の regions セクションからノード構成を読み取る。
事前準備
- LINSTOR/DRBD が全ノードにインストール済み (linstor-controller, linstor-satellite, drbd-dkms, drbd-utils, linstor-proxmox)
- PVE クラスタが構築済み (
pvecm statusで Quorate) - LINSTOR ノードが登録済み (
linstor node listで全ノード Online) - IB インターフェース (ibp*) が登録済み + PrefNic 設定済み (両リージョン)
- 確認:
ssh -F ssh/config pve$N "ip link show type ipoib"で ibp* が UP であること - 未設定の場合:
scp + ssh ib-setup-remote.sh --persistで設定 (詳細は linstor-node-ops スキル N7 参照)
- 確認:
- Debian cloud image が PVE ホスト上にダウンロード済み (パスは
config/linstor.ymlのbenchmark.cloud_image) - vendor snippet (
ssh-pwauth.yml) が PVE ホスト上に作成済み (後述) config/linstor.ymlのbenchmark:セクションが設定済み
スクリプト一覧
| スクリプト | 用途 |
|---|---|
./scripts/linstor-bench-preflight.sh | ディスク SMART ヘルスチェック (SCP で PVE ノードに転送して実行) |
設定値の読み取り
YQ="${PROJECT_DIR}/bin/yq"
CONFIG="config/linstor.yml"
# リージョン指定時のノード選択
# region-a: nodes[0]=4号機, nodes[1]=5号機
# region-b: nodes[2]=6号機, nodes[3]=7号機
# リージョン未指定時はデフォルトで region-a (nodes[0], nodes[1])
REGION="${2:-region-a}" # 第2引数
if [ "$REGION" = "region-b" ]; then
NODE1=$("$YQ" '.regions.region-b[0]' "$CONFIG")
NODE2=$("$YQ" '.regions.region-b[1]' "$CONFIG")
else
NODE1=$("$YQ" '.regions.region-a[0]' "$CONFIG")
NODE2=$("$YQ" '.regions.region-a[1]' "$CONFIG")
fi
# ノード名からIPを取得
NODE1_IP=$("$YQ" ".nodes[] | select(.name == \"$NODE1\") | .ip" "$CONFIG")
NODE2_IP=$("$YQ" ".nodes[] | select(.name == \"$NODE2\") | .ip" "$CONFIG")
DISKS=$("$YQ" ".nodes[] | select(.name == \"$NODE1\") | .storage_disks[]" "$CONFIG")
# ストレージ
VG_NAME=$("$YQ" '.vg_name' "$CONFIG")
RG_NAME=$("$YQ" '.resource_group' "$CONFIG")
PLACE_COUNT=$("$YQ" '.place_count' "$CONFIG")
# ベンチマーク
VM_ID=$("$YQ" '.benchmark.vm_id' "$CONFIG")
VM_NAME=$("$YQ" '.benchmark.vm_name' "$CONFIG")
VM_CORES=$("$YQ" '.benchmark.vm_cores' "$CONFIG")
VM_MEMORY=$("$YQ" '.benchmark.vm_memory' "$CONFIG")
VM_DISK_SIZE=$("$YQ" '.benchmark.vm_disk_size' "$CONFIG")
VM_BRIDGE=$("$YQ" '.benchmark.vm_bridge' "$CONFIG")
VM_MGMT_BRIDGE=$("$YQ" '.benchmark.vm_mgmt_bridge' "$CONFIG")
VM_MGMT_IP=$("$YQ" '.benchmark.vm_mgmt_ip' "$CONFIG")
VM_MGMT_PREFIX=$("$YQ" '.benchmark.vm_mgmt_prefix' "$CONFIG")
VM_USER=$("$YQ" '.benchmark.vm_user' "$CONFIG")
VM_PASS=$("$YQ" '.benchmark.vm_password' "$CONFIG")
CLOUD_IMAGE=$("$YQ" '.benchmark.cloud_image' "$CONFIG")
FIO_RUNTIME=$("$YQ" '.benchmark.fio_runtime' "$CONFIG")
FIO_SIZE=$("$YQ" '.benchmark.fio_size' "$CONFIG")
FIO_SEQ_SIZE=$("$YQ" '.benchmark.fio_seq_size' "$CONFIG")
既知の失敗と対策
前回のベンチマーク実行で発生した失敗パターン。各フェーズでこの対策を適用する。
| ID | 失敗 | フェーズ | 検出方法 | 対策 |
|---|---|---|---|---|
| F1 | ディスク不良セクタ | Phase 0 | SMART Current_Pending_Sector > 0 | ゼロ書きで強制再割り当て |
| F2 | LINSTOR リソース名が vm-100-disk-0 ではなく pm-XXXX | Phase 3 | qm importdisk 出力に pm-XXXX と表示 | importdisk 出力をパースしてリソース名を取得 |
| F3 | cloud-init SSH パスワード認証無効 | Phase 3 | Permission denied (publickey) | vendor snippet ssh_pwauth: true + --cicustom |
| F4 | VM MAC アドレス不一致で IP 検出失敗 | Phase 4 | IP 検出タイムアウト | 管理用 IP (10.x) が config で設定済みのため不要。DHCP のみの場合は qm config から MAC を動的取得 |
| F5 | Thick LVM で DRBD 全領域同期 | Phase 4 | peer-disk:Inconsistent が長時間 | ポーリングで待機 (thin は ~30秒) |
| F6 | linstor --output-format json 不存在 | Phase 4 | unrecognized arguments エラー | linstor -m resource list を使う |
| F7 | citype デフォルト (configdrive2) が Debian に非対応 | Phase 3 | cloud-init 設定が VM に反映されない | --citype nocloud を初回起動前に設定 |
| F8 | LINSTOR Auto-eviction がノードオフライン時にリソースを自動退去 | Phase 4-5 | linstor node list で "Auto-eviction at ..." 表示 | テスト前に無効化 |
| F9 | fio JSON 出力ディレクトリが未作成 | Phase 5 | No such file or directory | ローカルの mkdir -p を先頭に追加 |
| F10 | --boot order=scsi0 をディスクインポート前に設定 | Phase 3 | device 'scsi0' does not exist | importdisk → scsi0 接続の後に boot order を設定 |
| F11 | DRBD 9 の同期確認に /proc/drbd (DRBD 8形式) を使用 | Phase 4 | タイムアウトまたは空出力 | drbdsetup status <res> --verbose を使用 |
| F12 | sshpass が非コントローラ PVE ホストに未インストール | Phase 4 | sshpass: command not found | 公開鍵認証 + 10.x 直接 SSH を使用するため sshpass 不要 |
| F13 | VM 再作成後に SSH known_hosts のホスト鍵が不一致 | Phase 4 | REMOTE HOST IDENTIFICATION HAS CHANGED | ssh-keygen -R <vm_ip> -f ssh/known_hosts で事前クリア |
| F14 | Satellite ノードで linstor コマンドが localhost controller に接続不可 | Phase 4 | Connection refused | 全 linstor コマンドは Controller ノード (4号機) で実行 |
| F15 | cloud-init DHCP でアドレス取得失敗 → SSH 不能 | Phase 3 | IP 検出タイムアウト | DHCP 取得を最大5分待機。管理用 SSH は ipconfig1 の static 10.x で行うため DHCP 完了前でもアクセス可能 |
| F16 | vendor snippet ssh_pwauth=true でもパスワード認証不可 | Phase 3-4 | Permission denied (publickey) | SSH 公開鍵認証を優先: qm set --sshkeys <pubkey_file> |
| F17 | Debian 13 (OpenSSH 10.0) で RSA 鍵が無効化 | Phase 3-4 | Permission denied (publickey) | Ed25519 鍵 (id_ed25519.pub) を使用すること |
| F18 | DRBD non-UpToDate 中に qm resize が失敗 | Phase 3 | LINSTOR API 500 エラー | DRBD 同期完了後に resize する。resize 後に VM 内で growpart + resize2fs も必要 |
| F19 | PrefNic 変更後に既存 DRBD リソースが自動再接続されることを知らない | Phase 2-4 | 手動 drbdadm adjust を実行してしまう | PrefNic 変更すると LINSTOR が自動的に drbdadm adjust 相当を実行し、既存リソースが IB 経由に切り替わる。手動 drbdadm adjust は不要 |
F1: ディスク不良セクタ
SMART の Current_Pending_Sector が 0 より大きいディスクには不良セクタがあり、I/O エラーの原因になる。
ゼロ書きで該当セクタに書き込むと、ディスクが代替セクタに再割り当てを行う。
# 不良セクタの強制再割り当て (対象ディスクに対して実行)
ssh root@<node_ip> 'dd if=/dev/zero of=/dev/sdX bs=1M count=100 oflag=direct'
ssh root@<node_ip> 'dd if=/dev/zero of=/dev/sdX bs=1M count=100 oflag=direct seek=$(($(blockdev --getsize64 /dev/sdX)/1048576 - 100))'
# 再チェック
ssh root@<node_ip> 'smartctl -A /dev/sdX | grep -E "Current_Pending|Reallocated|Offline_Uncorrectable"'
F2: LINSTOR リソース名
qm importdisk が LINSTOR ストレージにディスクをインポートすると、リソース名が pm-XXXX (ランダム) になる。
vm-100-disk-0 のような標準名にはならないため、importdisk の出力からリソース名をパースする必要がある。
# importdisk 実行結果の例:
# unused0: successfully imported disk 'linstor-storage:pm-bfea68ea_100'
# → パースして 'pm-bfea68ea_100' を取得し、qm set --scsi0 に使用
# 注意: リソース名は pm-<hex>_<vmid> 形式。[0-9]* ではなく [a-z0-9_]+ でマッチすること
IMPORT_OUTPUT=$(ssh root@$NODE1_IP "qm importdisk $VM_ID $CLOUD_IMAGE linstor-storage" 2>&1)
RESOURCE_NAME=$(echo "$IMPORT_OUTPUT" | grep -o "linstor-storage:pm-[a-z0-9_]*" | sed 's/linstor-storage://')
ssh root@$NODE1_IP "qm set $VM_ID --scsi0 linstor-storage:$RESOURCE_NAME,discard=on,iothread=1"
F3: cloud-init SSH パスワード認証
Debian cloud image はデフォルトで SSH パスワード認証が無効。--cipassword を設定しても SSH できない。
vendor snippet で ssh_pwauth: true を設定する必要がある。
# vendor snippet を PVE ホストに作成 (snippets ディレクトリが必要)
ssh root@$NODE1_IP 'mkdir -p /var/lib/vz/snippets'
ssh root@$NODE1_IP 'printf "#cloud-config\nssh_pwauth: true\n" > /var/lib/vz/snippets/ssh-pwauth.yml'
# VM に適用
ssh root@$NODE1_IP "qm set $VM_ID --cicustom 'vendor=local:snippets/ssh-pwauth.yml'"
F4: VM MAC アドレスの動的取得
注: 管理用 IP (10.x) が config で設定済み (
vm_mgmt_ip) の場合、MAC アドレス検出・nmap スキャン・ARP 参照は不要。VM_IP=$VM_MGMT_IPで直接 SSH 接続できる。
以下は DHCP のみの構成で IP 検出が必要な場合の参考手順:
MAC=$(ssh root@$NODE1_IP "qm config $VM_ID" | grep '^net0' | grep -o 'virtio=[0-9A-Fa-f:]*' | cut -d= -f2)
ssh root@$NODE1_IP "ip neigh | grep -i '$MAC' | awk '{print \$1}'"
F7: citype nocloud
Debian の cloud-init は nocloud データソースを使う。PVE のデフォルト configdrive2 では設定が反映されない。
ssh root@$NODE1_IP "qm set $VM_ID --citype nocloud"
F8: LINSTOR Auto-eviction
ノードがオフラインになると LINSTOR は約60分後に Auto-eviction を発動し、リソースを自動退去させる。 ベンチマーク中にノード障害やリブートが発生すると、意図しないリソース再配置が起きる。
検出:
ssh root@$NODE1_IP "linstor node list"
# "Auto-eviction at 2026-XX-XX XX:XX:XX" が表示される
対策 (テスト前に各ノードで無効化):
ssh root@$NODE1_IP "linstor node set-property $NODE1 DrbdOptions/AutoEvictAllowEviction false"
ssh root@$NODE1_IP "linstor node set-property $NODE2 DrbdOptions/AutoEvictAllowEviction false"
テスト終了後に再有効化:
ssh root@$NODE1_IP "linstor node set-property $NODE1 DrbdOptions/AutoEvictAllowEviction"
ssh root@$NODE1_IP "linstor node set-property $NODE2 DrbdOptions/AutoEvictAllowEviction"
F9: fio 出力ディレクトリ未作成
fio の JSON 出力を SSH 経由で stdout リダイレクトする場合、出力先ディレクトリはローカルホスト側 (Claude Code 実行マシン) に必要。
# Phase 5 の先頭で実行
mkdir -p tmp/<session-id>/fio-results/
F10: boot order 設定の順序
qm importdisk → qm set --scsi0 → qm set --boot order=scsi0 の順で実行すること。
importdisk 前や scsi0 接続前に boot order を設定すると、scsi0 デバイスが存在しないためエラーになる。
F11: DRBD 9 の同期確認
DRBD 9 では /proc/drbd は空または DRBD 8 と形式が異なる。同期状態の確認には以下を使用:
# 推奨: 全リソースのステータス
ssh root@$CONTROLLER_IP "drbdsetup status --verbose"
# 特定リソース
ssh root@$CONTROLLER_IP "drbdsetup status <resource> --verbose"
# peer-disk で UpToDate を確認
# drbdadm status も使用可能 (ANSI カラーコード付き)
F12: sshpass 未インストール
公開鍵認証 + 10.x 管理用 IP への直接 SSH を使用するため、sshpass は不要。
VM への SSH は ssh ${VM_USER}@${VM_MGMT_IP} で直接接続する。
F13: SSH known_hosts ホスト鍵不一致
VM を再作成すると SSH ホスト鍵が変わるため、known_hosts に古い鍵が残っているとエラーになる。
# VM の IP に対してホスト鍵をクリア
ssh-keygen -R <vm_ip> -f ssh/known_hosts
# PVE ホスト側でも同様
ssh root@$NODE1_IP "ssh-keygen -R <vm_ip> -f ssh/known_hosts"
F14: Satellite ノードでの linstor コマンド
Satellite ノードには linstor-controller が動いていないため、linstor コマンドがデフォルトの localhost:3370 に接続しようとして失敗する。全 linstor コマンドは Controller ノード (4号機) 経由で実行すること。
F15-F16: SSH 接続の推奨方法
VM にはデュアル NIC を構成し、SSH は 10.x 管理用 IP に直接接続する:
net0: vmbr1 (192.168.39.0/24, DHCP, インターネット用)net1: vmbr0 (10.0.0.0/8, static, SSH 管理用)
注意 (F17): Debian 13 cloud image (OpenSSH 10.0) は RSA 鍵が無効化されている。
/root/.ssh/id_rsa.pubではなく Ed25519 鍵 (/root/.ssh/id_ed25519.pub) を使うこと。
- ローカルマシン (Claude Code ホスト) の Ed25519 公開鍵を
qm set --sshkeysで設定:scp -F ssh/config ~/.ssh/id_ed25519.pub root@$NODE1_IP:/tmp/local_ed25519.pub ssh root@$NODE1_IP "qm set $VM_ID --sshkeys /tmp/local_ed25519.pub"- 注意: PVE ホストの鍵ではなくローカルの鍵を使うこと (SSH はローカルから直接 10.x に接続)
ssh -o StrictHostKeyChecking=no debian@$VM_MGMT_IPでローカルから直接接続 (10.x 経由、sshpass 不要)- DHCP は最大5分かかることがあるが、SSH は static 10.x なので DHCP 完了を待つ必要はない
- fio インストール (apt) にはインターネットが必要なので、cloud-init 完了を待つ:
ssh ${VM_USER}@${VM_MGMT_IP} 'cloud-init status --wait'
注意: 192.168.39.0/24 に静的 IP を割り当てないこと (DHCP 衝突の危険)。
fio テスト定義
全7テスト。各テストは --runtime=$FIO_RUNTIME (デフォルト 60秒) で実行。
| # | テスト名 | rw | bs | iodepth | size |
|---|---|---|---|---|---|
| 1 | randread-4k-qd1 | randread | 4k | 1 | $FIO_SIZE |
| 2 | randread-4k-qd32 | randread | 4k | 32 | $FIO_SIZE |
| 3 | randwrite-4k-qd1 | randwrite | 4k | 1 | $FIO_SIZE |
| 4 | randwrite-4k-qd32 | randwrite | 4k | 32 | $FIO_SIZE |
| 5 | seqread-1m-qd32 | read | 1m | 32 | $FIO_SEQ_SIZE |
| 6 | seqwrite-1m-qd32 | write | 1m | 32 | $FIO_SEQ_SIZE |
| 7 | mixed-rw-4k-qd32 | randrw (70/30) | 4k | 32 | $FIO_SIZE |
共通オプション: --ioengine=libaio --direct=1 --numjobs=1 --time_based --group_reporting --output-format=json
フェーズ実行
Phase 0: Pre-flight — ディスクヘルスチェック
pve-lock: 不要
各ノードの各ストレージディスクの SMART をチェックし、不良セクタを検出する。
-
preflight スクリプトを各ノードに転送:
scp -F ssh/config ./scripts/linstor-bench-preflight.sh root@$NODE1_IP:/tmp/ scp -F ssh/config ./scripts/linstor-bench-preflight.sh root@$NODE2_IP:/tmp/ -
各ノードで実行:
ssh root@$NODE1_IP 'sh /tmp/linstor-bench-preflight.sh /dev/sda /dev/sdb /dev/sdc /dev/sdd' ssh root@$NODE2_IP 'sh /tmp/linstor-bench-preflight.sh /dev/sda /dev/sdb /dev/sdc /dev/sdd' -
不良セクタ検出時 (exit 1):
- 対策 F1 のゼロ書き手順でセクタを強制再割り当て
- 再割り当て後に再実行して
Current_Pending_Sector = 0を確認
Phase 1: クリーンアップ
pve-lock: 必須
既存の VM、LINSTOR リソース、ストレージプール、LVM を解体する。 存在しないリソースの削除はエラーになるので、各ステップで存在確認してからスキップまたは削除する。
削除順序: VM → LINSTOR リソース → リソースグループ → ストレージプール → PVE ストレージ → LVM
-
VM 停止・削除 (存在する場合):
ssh root@$NODE1_IP "qm status $VM_ID" 2>/dev/null && \ ssh root@$NODE1_IP "qm stop $VM_ID" && \ ssh root@$NODE1_IP "qm destroy $VM_ID --purge" -
LINSTOR リソース削除 (存在する場合):
# リソース定義一覧を確認 ssh root@$NODE1_IP "linstor resource-definition list" # 各リソース定義を削除 (--async でタイムアウト回避) ssh root@$NODE1_IP "linstor resource-definition delete <resource-name>" -
PVE ストレージ削除:
ssh root@$NODE1_IP "pvesm status" | grep linstor-storage && \ ssh root@$NODE1_IP "pvesm remove linstor-storage" -
リソースグループ削除:
ssh root@$NODE1_IP "linstor volume-group delete $RG_NAME 0" 2>/dev/null ssh root@$NODE1_IP "linstor resource-group delete $RG_NAME" 2>/dev/null -
ストレージプール削除:
ssh root@$NODE1_IP "linstor storage-pool delete $NODE1 <pool-name>" ssh root@$NODE1_IP "linstor storage-pool delete $NODE2 <pool-name>" -
各ノードで LVM 解体:
ssh root@$NODE1_IP "vgs $VG_NAME" 2>/dev/null && \ ssh root@$NODE1_IP "lvremove -f $VG_NAME 2>/dev/null; vgremove -f $VG_NAME; pvremove /dev/sda /dev/sdb /dev/sdc /dev/sdd" ssh root@$NODE2_IP "vgs $VG_NAME" 2>/dev/null && \ ssh root@$NODE2_IP "lvremove -f $VG_NAME 2>/dev/null; vgremove -f $VG_NAME; pvremove /dev/sda /dev/sdb /dev/sdc /dev/sdd" -
検証:
ssh root@$NODE1_IP "linstor storage-pool list" ssh root@$NODE1_IP "linstor resource-definition list" ssh root@$NODE1_IP "pvesm status"
Phase 2: ストレージ構成
pve-lock: 必須
引数 storage_type に応じてストレージを構成する。
共通: VG 作成
各ノードで VG を作成する:
ssh root@$NODE1_IP "wipefs -af /dev/sda /dev/sdb /dev/sdc /dev/sdd && pvcreate /dev/sda /dev/sdb /dev/sdc /dev/sdd && vgcreate $VG_NAME /dev/sda /dev/sdb /dev/sdc /dev/sdd"
ssh root@$NODE2_IP "wipefs -af /dev/sda /dev/sdb /dev/sdc /dev/sdd && pvcreate /dev/sda /dev/sdb /dev/sdc /dev/sdd && vgcreate $VG_NAME /dev/sda /dev/sdb /dev/sdc /dev/sdd"
storage_type=thin の場合
# Thin pool 作成 (各ノード)
ssh root@$NODE1_IP "lvcreate -l 95%FREE -T ${VG_NAME}/thinpool"
ssh root@$NODE2_IP "lvcreate -l 95%FREE -T ${VG_NAME}/thinpool"
# LINSTOR ストレージプール (lvmthin)
POOL_NAME="thinpool"
ssh root@$NODE1_IP "linstor storage-pool create lvmthin $NODE1 $POOL_NAME ${VG_NAME}/thinpool"
ssh root@$NODE1_IP "linstor storage-pool create lvmthin $NODE2 $POOL_NAME ${VG_NAME}/thinpool"
storage_type=thick-stripe の場合
# LINSTOR ストレージプール (lvm)
POOL_NAME="striped-pool"
ssh root@$NODE1_IP "linstor storage-pool create lvm $NODE1 $POOL_NAME $VG_NAME"
ssh root@$NODE1_IP "linstor storage-pool create lvm $NODE2 $POOL_NAME $VG_NAME"
# ストライピングオプション設定 (-i4: 4本, -I64: 64KiB)
# ダッシュ引数が承認プロンプトに引っかかるため scp + ssh パターンで実行
# tmp/<session-id>/lvcreate-opts.sh に以下を Write (ノード名を変数で展開):
# linstor storage-pool set-property <NODE> <POOL_NAME> StorDriver/LvcreateOptions -- '-i4 -I64'
scp -F ssh/config tmp/<session-id>/lvcreate-opts-node1.sh root@$NODE1_IP:/tmp/lvcreate-opts.sh
ssh root@$NODE1_IP sh /tmp/lvcreate-opts.sh
scp -F ssh/config tmp/<session-id>/lvcreate-opts-node2.sh root@$NODE1_IP:/tmp/lvcreate-opts.sh
ssh root@$NODE1_IP sh /tmp/lvcreate-opts.sh
共通: リソースグループ + DRBD オプション + PVE ストレージ
# リソースグループ
ssh root@$NODE1_IP "linstor resource-group create $RG_NAME --place-count $PLACE_COUNT --storage-pool $POOL_NAME"
ssh root@$NODE1_IP "linstor volume-group create $RG_NAME"
# DRBD オプション
ssh root@$NODE1_IP "linstor resource-group drbd-options --protocol C $RG_NAME"
ssh root@$NODE1_IP "linstor resource-group drbd-options --quorum off $RG_NAME"
ssh root@$NODE1_IP "linstor resource-group drbd-options --auto-promote yes $RG_NAME"
# PVE ストレージ
ssh root@$NODE1_IP "pvesm add drbd linstor-storage --resourcegroup $RG_NAME --content images,rootdir --controller $NODE1_IP"
検証
ssh root@$NODE1_IP "linstor storage-pool list"
ssh root@$NODE1_IP "pvesm status"
Phase 3: VM 作成
pve-lock: 必須
注意: cloud-init は初回起動時のみ実行される。すべての設定 (cicustom, citype, ciuser, cipassword, ipconfig0, ipconfig1) を
qm start前に完了すること。
-
ブリッジ検証 (★ 7号機 NIC 逆順対策):
# vmbr0 が 10.x (管理)、vmbr1 が 192.168.39.x (DHCP) であることを確認 ssh root@$NODE1_IP "ip -4 addr show vmbr0" # → 10.10.10.x が表示されるべき ssh root@$NODE1_IP "ip -4 addr show vmbr1" # → 192.168.39.x が表示されるべき # 逆の場合は VM_BRIDGE と VM_MGMT_BRIDGE を入れ替える -
VM 作成 (★ デュアル NIC: net0=インターネット用, net1=管理用):
ssh root@$NODE1_IP "qm create $VM_ID --name $VM_NAME --memory $VM_MEMORY --cores $VM_CORES --cpu host --net0 virtio,bridge=$VM_BRIDGE --net1 virtio,bridge=$VM_MGMT_BRIDGE --ostype l26 --scsihw virtio-scsi-single" -
ディスクインポート (★ F2 対策: リソース名をパース):
IMPORT_OUTPUT=$(ssh root@$NODE1_IP "qm importdisk $VM_ID $CLOUD_IMAGE linstor-storage" 2>&1) RESOURCE_NAME=$(echo "$IMPORT_OUTPUT" | grep "successfully imported" | grep -o 'pm-[a-z0-9_]*')RESOURCE_NAMEが空の場合は出力全体を確認しエラー対処- 注意: grep は
successfully imported行のみ対象にすること。pm-<hex>とpm-<hex>_<vmid>の両方にマッチするため、正しい行から抽出しないと誤ったリソース名になる
-
ディスク接続 (パースしたリソース名を使用):
ssh root@$NODE1_IP "qm set $VM_ID --scsi0 linstor-storage:${RESOURCE_NAME},discard=on,iothread=1" -
ブート順序 + cloudinit ドライブ (★ F10: scsi0 接続後に設定すること):
ssh root@$NODE1_IP "qm set $VM_ID --boot order=scsi0" ssh root@$NODE1_IP "qm set $VM_ID --ide2 linstor-storage:cloudinit" -
vendor snippet 作成・適用 (★ F3 対策):
ssh root@$NODE1_IP 'mkdir -p /var/lib/vz/snippets' ssh root@$NODE1_IP 'printf "#cloud-config\nssh_pwauth: true\n" > /var/lib/vz/snippets/ssh-pwauth.yml' ssh root@$NODE1_IP "qm set $VM_ID --cicustom 'vendor=local:snippets/ssh-pwauth.yml'" -
citype 設定 (★ F7 対策):
ssh root@$NODE1_IP "qm set $VM_ID --citype nocloud" -
SSH 公開鍵設定 (★ F16/F17 対策: Ed25519 公開鍵認証を使用):
# ローカルマシン (Claude Code ホスト) の Ed25519 公開鍵を PVE ホストにコピー scp -F ssh/config ~/.ssh/id_ed25519.pub root@$NODE1_IP:/tmp/local_ed25519.pub ssh root@$NODE1_IP "qm set $VM_ID --sshkeys /tmp/local_ed25519.pub"- 注意: PVE ホストの鍵ではなく、ローカルマシンの公開鍵を設定すること。SSH はローカルから 10.x 経由で直接接続するため
-
cloud-init ユーザ・ネットワーク設定 (★ デュアル NIC: DHCP + 管理用 static):
ssh root@$NODE1_IP "qm set $VM_ID --ciuser $VM_USER --cipassword $VM_PASS --ipconfig0 ip=dhcp --ipconfig1 ip=$VM_MGMT_IP/$VM_MGMT_PREFIX"ipconfig0: vmbr1 (DHCP, インターネット用)ipconfig1: vmbr0 (static 10.x, SSH 管理用, ゲートウェイ不要)
-
VM 起動 (★ resize は DRBD 同期完了後に行うため先に起動):
ssh root@$NODE1_IP "qm start $VM_ID"
Phase 4: 同期待ち + SSH 接続
pve-lock: 不要
DRBD 同期待ち (★ F5)
thick-stripe の場合、全領域の DRBD 初期同期が発生する。thin の場合は使用済み領域のみで ~30秒。
実測同期レート (SATA HDD over IPoIB):
| ディスクサイズ | 所要時間 | レート |
|---|---|---|
| 32G | ~9分 | — |
| 518 GiB | ~92分 | ~96 MiB/s |
ポーリング間隔: 30秒 (drbdsetup status)
# 同期状態のポーリング (30秒間隔) (★ F11: drbdsetup を使用、/proc/drbd は DRBD 9 で空)
ssh root@$CONTROLLER_IP "drbdsetup status --verbose"
# 出力例 (同期中): peer-disk:Inconsistent
# 出力例 (完了): peer-disk:UpToDate
# ★ F14: linstor/DRBD コマンドは Controller ノード (4号機) で実行すること
# ★ 接続先アドレスの確認には `drbdsetup show <resource>` を使う (IP 表示あり)。
# `drbdsetup status --verbose` では接続先 IP が表示されない
UpToDate/UpToDate になるまでポーリングで待機する。
ディスクリサイズ (★ F18: DRBD 同期完了後に実行)
ssh root@$NODE1_IP "qm resize $VM_ID scsi0 $VM_DISK_SIZE"
# VM 内でパーティション + ファイルシステム拡張
ssh ${VM_USER}@${VM_MGMT_IP} "sudo growpart /dev/sda 1"
ssh ${VM_USER}@${VM_MGMT_IP} "sudo resize2fs /dev/sda1"
VM 管理 IP
VM の管理用 IP は config から既知 (10.x static)。MAC アドレス検出・nmap スキャン・ARP テーブル参照は不要。
VM_IP=$VM_MGMT_IP
注: F4 (MAC アドレス不一致) は管理用 IP が config で設定済みのため不要。 DHCP の 192.168.39.x IP はインターネット通信専用で、SSH 接続には使用しない。
SSH 接続テスト (★ F13)
# ★ F13: VM 再作成時はホスト鍵をクリア
ssh-keygen -R $VM_IP -f ssh/known_hosts
# 10.x 管理用 IP に直接 SSH (公開鍵認証、Phase 3 で --sshkeys 設定済み)
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 ${VM_USER}@${VM_IP} 'uname -a'
cloud-init 完了待ち + fio インストール
DHCP (vmbr1) は最大5分かかる場合がある。SSH は 10.x (static) 経由なので DHCP 完了前でもアクセス可能。 ただし fio インストール (apt) にはインターネットが必要なので、cloud-init 完了を待つ。
ssh ${VM_USER}@${VM_IP} 'cloud-init status --wait'
ssh ${VM_USER}@${VM_IP} 'sudo apt-get update && sudo apt-get install -y fio'
注意 (F6): LINSTOR の JSON 出力は
linstor --output-format jsonではなくlinstor -m(machine-readable) を使う。--output-formatオプションは存在しない。
Phase 5: ベンチマーク実行
pve-lock: 不要
7テストを順番に実行する。各テスト結果は JSON で tmp/<session-id>/fio-results/ に保存する。
# ★ F9: 出力ディレクトリをローカル側に事前作成
mkdir -p tmp/<session-id>/fio-results
各テストの実行 (10.x 管理 IP に公開鍵認証で SSH 接続):
ssh ${VM_USER}@${VM_IP} "sudo fio \
--name=<test-name> \
--ioengine=libaio --direct=1 \
--rw=<rw-pattern> --bs=<block-size> \
--iodepth=<queue-depth> --numjobs=1 \
--size=<size> \
--runtime=$FIO_RUNTIME --time_based \
--group_reporting --output-format=json" \
> tmp/<session-id>/fio-results/<test-name>.json
テスト一覧 (fio テスト定義セクション参照):
randread-4k-qd1:--rw=randread --bs=4k --iodepth=1 --size=$FIO_SIZErandread-4k-qd32:--rw=randread --bs=4k --iodepth=32 --size=$FIO_SIZErandwrite-4k-qd1:--rw=randwrite --bs=4k --iodepth=1 --size=$FIO_SIZErandwrite-4k-qd32:--rw=randwrite --bs=4k --iodepth=32 --size=$FIO_SIZEseqread-1m-qd32:--rw=read --bs=1m --iodepth=32 --size=$FIO_SEQ_SIZEseqwrite-1m-qd32:--rw=write --bs=1m --iodepth=32 --size=$FIO_SEQ_SIZEmixed-rw-4k-qd32:--rw=randrw --rwmixread=70 --bs=4k --iodepth=32 --size=$FIO_SIZE
Phase 6: 結果抽出 + レポート
pve-lock: 不要
-
fio JSON から主要メトリクスを抽出:
- IOPS (read/write)
- BW (KiB/s or MiB/s)
- Avg Latency (ms)
- p99 Latency (ms)
-
Python スクリプトで JSON をパース:
# tmp/<session-id>/extract-fio.py を作成して実行 python3 tmp/<session-id>/extract-fio.py tmp/<session-id>/fio-results/fio JSON の構造:
jobs[0].read.iops, jobs[0].read.bw (KiB/s), jobs[0].read.clat_ns.mean (ns), jobs[0].read.clat_ns.percentile["99.000000"] (ns) jobs[0].write.iops, jobs[0].write.bw (KiB/s), jobs[0].write.clat_ns.mean (ns), jobs[0].write.clat_ns.percentile["99.000000"] (ns) -
report/にレポート生成 (REPORT.md フォーマット準拠):- 環境情報 (ハードウェア、ソフトウェア、DRBD 構成)
- ストレージ構成 (thin or thick-stripe)
- ベンチマーク結果テーブル (IOPS, スループット, レイテンシ)
- 分析 (ボトルネック、前回結果との比較 (あれば))
- 再現方法
oplog
状態変更操作は ./oplog.sh で記録する:
- Phase 1 (クリーンアップ): VM 削除、LINSTOR リソース削除、LVM 解体
- Phase 2 (ストレージ構成): VG 作成、ストレージプール作成
- Phase 3 (VM 作成): qm create, qm importdisk, qm start
読み取り専用操作 (linstor storage-pool list, drbdadm status, fio 実行) は oplog 不要。
pve-lock の使い方
Phase 1〜3 では状態変更操作に ./pve-lock.sh を使用する:
./pve-lock.sh run <command...> # 即座に実行(ロック中ならエラー)
./pve-lock.sh wait <command...> # ロック待ち→実行
ロック中の場合は別の課題に着手し、ロック解放後に再開する。
レビュー
まだレビューはありません。使ってみた感想をお寄せください。
同じリポジトリのスキル
概要と使いどころ
Dell ファームウェアダウンロード。Playwright で dl.dell.com から BIN を取得し firmimg.d7 を抽出する。
Mellanox SX6036 InfiniBand スイッチのシリアルコンソール操作。ステータス確認、show コマンド、IB 設定、FW 管理を行う。
iDRAC7 基本操作。SSH 経由で racadm コマンドを実行し、サーバ管理を行う。
iDRAC7 ファームウェアアップデート。段階的アップグレードパスに従い TFTP 経由で適用する。
Fujitsu iRMC S4 (TX1320 M3 等) の電源・BIOS・RAID 操作 + BIOS 設定リファレンス。Redfish (HTTPS + SECLEVEL=0) 経由の電源/ブート操作 + iRMC Web UI/KVM 経由の手動 BIOS/RAID 操作手順 + 全 BIOS 設定項目の網羅リファレンス (bios/)。training-tx1320 対応。