Skip to content
cccskills
FreePublished on GitHub

linstor-bench

LINSTOR/DRBD ストレージベンチマーク。VM上でfioを実行し、thin/thick-stripe構成の性能を計測する。

The English summary is being prepared. Showing the original description.

See how to install

Files included (1)

  • SKILL.md30.3 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

LINSTOR ベンチマークスキル

LINSTOR/DRBD ストレージ上に VM を作成し、fio でベンチマークを実行する。 引数 storage_type で thin (LVM thin pool) または thick-stripe (LVM 4本ストライプ) を選択する。 オプションで region を指定して特定リージョンでベンチマークを実行する。

マルチリージョン構成

リージョンノードDRBD通信特徴
region-a4号機 + 5号機 + 6号機IPoIB 192.168.100.xInfiniBand 高速通信
region-b7号機 + 8号機 + 9号機IPoIB 192.168.100.xInfiniBand 高速通信

region 指定時は、そのリージョンの最初のノードに VM を配置し、同リージョン内の2ノードで DRBD レプリケーションを行う。 config/linstor.yml の regions セクションからノード構成を読み取る。

事前準備

  1. LINSTOR/DRBD が全ノードにインストール済み (linstor-controller, linstor-satellite, drbd-dkms, drbd-utils, linstor-proxmox)
  2. PVE クラスタが構築済み (pvecm status で Quorate)
  3. LINSTOR ノードが登録済み (linstor node list で全ノード Online)
  4. 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 参照)
  5. Debian cloud image が PVE ホスト上にダウンロード済み (パスは config/linstor.yml の benchmark.cloud_image)
  6. vendor snippet (ssh-pwauth.yml) が PVE ホスト上に作成済み (後述)
  7. 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 0SMART Current_Pending_Sector > 0ゼロ書きで強制再割り当て
F2LINSTOR リソース名が vm-100-disk-0 ではなく pm-XXXXPhase 3qm importdisk 出力に pm-XXXX と表示importdisk 出力をパースしてリソース名を取得
F3cloud-init SSH パスワード認証無効Phase 3Permission denied (publickey)vendor snippet ssh_pwauth: true + --cicustom
F4VM MAC アドレス不一致で IP 検出失敗Phase 4IP 検出タイムアウト管理用 IP (10.x) が config で設定済みのため不要。DHCP のみの場合は qm config から MAC を動的取得
F5Thick LVM で DRBD 全領域同期Phase 4peer-disk:Inconsistent が長時間ポーリングで待機 (thin は ~30秒)
F6linstor --output-format json 不存在Phase 4unrecognized arguments エラーlinstor -m resource list を使う
F7citype デフォルト (configdrive2) が Debian に非対応Phase 3cloud-init 設定が VM に反映されない--citype nocloud を初回起動前に設定
F8LINSTOR Auto-eviction がノードオフライン時にリソースを自動退去Phase 4-5linstor node list で "Auto-eviction at ..." 表示テスト前に無効化
F9fio JSON 出力ディレクトリが未作成Phase 5No such file or directoryローカルの mkdir -p を先頭に追加
F10--boot order=scsi0 をディスクインポート前に設定Phase 3device 'scsi0' does not existimportdisk → scsi0 接続の後に boot order を設定
F11DRBD 9 の同期確認に /proc/drbd (DRBD 8形式) を使用Phase 4タイムアウトまたは空出力drbdsetup status <res> --verbose を使用
F12sshpass が非コントローラ PVE ホストに未インストールPhase 4sshpass: command not found公開鍵認証 + 10.x 直接 SSH を使用するため sshpass 不要
F13VM 再作成後に SSH known_hosts のホスト鍵が不一致Phase 4REMOTE HOST IDENTIFICATION HAS CHANGEDssh-keygen -R <vm_ip> -f ssh/known_hosts で事前クリア
F14Satellite ノードで linstor コマンドが localhost controller に接続不可Phase 4Connection refused全 linstor コマンドは Controller ノード (4号機) で実行
F15cloud-init DHCP でアドレス取得失敗 → SSH 不能Phase 3IP 検出タイムアウトDHCP 取得を最大5分待機。管理用 SSH は ipconfig1 の static 10.x で行うため DHCP 完了前でもアクセス可能
F16vendor snippet ssh_pwauth=true でもパスワード認証不可Phase 3-4Permission denied (publickey)SSH 公開鍵認証を優先: qm set --sshkeys <pubkey_file>
F17Debian 13 (OpenSSH 10.0) で RSA 鍵が無効化Phase 3-4Permission denied (publickey)Ed25519 鍵 (id_ed25519.pub) を使用すること
F18DRBD non-UpToDate 中に qm resize が失敗Phase 3LINSTOR API 500 エラーDRBD 同期完了後に resize する。resize 後に VM 内で growpart + resize2fs も必要
F19PrefNic 変更後に既存 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) を使うこと。

  1. ローカルマシン (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 に接続)
  2. ssh -o StrictHostKeyChecking=no debian@$VM_MGMT_IP でローカルから直接接続 (10.x 経由、sshpass 不要)
  3. DHCP は最大5分かかることがあるが、SSH は static 10.x なので DHCP 完了を待つ必要はない
  4. 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秒) で実行。

#テスト名rwbsiodepthsize
1randread-4k-qd1randread4k1$FIO_SIZE
2randread-4k-qd32randread4k32$FIO_SIZE
3randwrite-4k-qd1randwrite4k1$FIO_SIZE
4randwrite-4k-qd32randwrite4k32$FIO_SIZE
5seqread-1m-qd32read1m32$FIO_SEQ_SIZE
6seqwrite-1m-qd32write1m32$FIO_SEQ_SIZE
7mixed-rw-4k-qd32randrw (70/30)4k32$FIO_SIZE

共通オプション: --ioengine=libaio --direct=1 --numjobs=1 --time_based --group_reporting --output-format=json

フェーズ実行


Phase 0: Pre-flight — ディスクヘルスチェック

pve-lock: 不要

各ノードの各ストレージディスクの SMART をチェックし、不良セクタを検出する。

  1. 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/
    
  2. 各ノードで実行:

    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'
    
  3. 不良セクタ検出時 (exit 1):

    • 対策 F1 のゼロ書き手順でセクタを強制再割り当て
    • 再割り当て後に再実行して Current_Pending_Sector = 0 を確認

Phase 1: クリーンアップ

pve-lock: 必須

既存の VM、LINSTOR リソース、ストレージプール、LVM を解体する。 存在しないリソースの削除はエラーになるので、各ステップで存在確認してからスキップまたは削除する。

削除順序: VM → LINSTOR リソース → リソースグループ → ストレージプール → PVE ストレージ → LVM

  1. 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"
    
  2. LINSTOR リソース削除 (存在する場合):

    # リソース定義一覧を確認
    ssh root@$NODE1_IP "linstor resource-definition list"
    # 各リソース定義を削除 (--async でタイムアウト回避)
    ssh root@$NODE1_IP "linstor resource-definition delete <resource-name>"
    
  3. PVE ストレージ削除:

    ssh root@$NODE1_IP "pvesm status" | grep linstor-storage && \
      ssh root@$NODE1_IP "pvesm remove linstor-storage"
    
  4. リソースグループ削除:

    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
    
  5. ストレージプール削除:

    ssh root@$NODE1_IP "linstor storage-pool delete $NODE1 <pool-name>"
    ssh root@$NODE1_IP "linstor storage-pool delete $NODE2 <pool-name>"
    
  6. 各ノードで 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"
    
  7. 検証:

    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 前に完了すること。

  1. ブリッジ検証 (★ 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 を入れ替える
    
  2. 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"
    
  3. ディスクインポート (★ 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> の両方にマッチするため、正しい行から抽出しないと誤ったリソース名になる
  4. ディスク接続 (パースしたリソース名を使用):

    ssh root@$NODE1_IP "qm set $VM_ID --scsi0 linstor-storage:${RESOURCE_NAME},discard=on,iothread=1"
    
  5. ブート順序 + 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"
    
  6. 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'"
    
  7. citype 設定 (★ F7 対策):

    ssh root@$NODE1_IP "qm set $VM_ID --citype nocloud"
    
  8. 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 経由で直接接続するため
  9. 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 管理用, ゲートウェイ不要)
  10. 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 テスト定義セクション参照):

  1. randread-4k-qd1: --rw=randread --bs=4k --iodepth=1 --size=$FIO_SIZE
  2. randread-4k-qd32: --rw=randread --bs=4k --iodepth=32 --size=$FIO_SIZE
  3. randwrite-4k-qd1: --rw=randwrite --bs=4k --iodepth=1 --size=$FIO_SIZE
  4. randwrite-4k-qd32: --rw=randwrite --bs=4k --iodepth=32 --size=$FIO_SIZE
  5. seqread-1m-qd32: --rw=read --bs=1m --iodepth=32 --size=$FIO_SEQ_SIZE
  6. seqwrite-1m-qd32: --rw=write --bs=1m --iodepth=32 --size=$FIO_SEQ_SIZE
  7. mixed-rw-4k-qd32: --rw=randrw --rwmixread=70 --bs=4k --iodepth=32 --size=$FIO_SIZE

Phase 6: 結果抽出 + レポート

pve-lock: 不要

  1. fio JSON から主要メトリクスを抽出:

    • IOPS (read/write)
    • BW (KiB/s or MiB/s)
    • Avg Latency (ms)
    • p99 Latency (ms)
  2. 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)
    
  3. 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...>    # ロック待ち→実行

ロック中の場合は別の課題に着手し、ロック解放後に再開する。

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Supermicro X11DPU/X10DRT-P BIOS Setup 操作。KVM スクリーンショット + キーストロークで BIOS メニューを操作する。BIOS 設定変更、確認、保存を行う。4-6号機 + 10号機対応。

The English summary is being prepared. Showing the original description.

miminashi/pvese19Updated Jul 6, 2026

Dell ファームウェアダウンロード。Playwright で dl.dell.com から BIN を取得し firmimg.d7 を抽出する。

The English summary is being prepared. Showing the original description.

miminashi/pvese19Updated Jul 6, 2026

Mellanox SX6036 InfiniBand スイッチのシリアルコンソール操作。ステータス確認、show コマンド、IB 設定、FW 管理を行う。

The English summary is being prepared. Showing the original description.

miminashi/pvese19Updated Jul 6, 2026

idrac7

Free

iDRAC7 基本操作。SSH 経由で racadm コマンドを実行し、サーバ管理を行う。

The English summary is being prepared. Showing the original description.

miminashi/pvese19Updated Jul 6, 2026

iDRAC7 ファームウェアアップデート。段階的アップグレードパスに従い TFTP 経由で適用する。

The English summary is being prepared. Showing the original description.

miminashi/pvese19Updated Jul 6, 2026

Fujitsu iRMC S4 (TX1320 M3 等) の電源・BIOS・RAID 操作 + BIOS 設定リファレンス。Redfish (HTTPS + SECLEVEL=0) 経由の電源/ブート操作 + iRMC Web UI/KVM 経由の手動 BIOS/RAID 操作手順 + 全 BIOS 設定項目の網羅リファレンス (bios/)。training-tx1320 対応。

The English summary is being prepared. Showing the original description.

miminashi/pvese19Updated Jul 6, 2026

See all skills by miminashi

Report a problem with this skill