Skip to content

RBSU Monitor — 24ノードの手作業をWorkflowにした

発端

Securebootの証明書切れの対応で、ASHノードのRBSUに入ってKeyをリセットする必要がでた
2つのリージョン、合計24台のノードで実施・・??
だるすぎる。Excelの手順書作りたくない
💡よし、ワークフローにしよう

公式手順よりやることは以下で確定
HPE Azure Stack Hub Solutions – Secure Boot Certificate Expiration and Update

フェーズ手作業
切り離しASH Admin Portalから対象ノードをDrainし、Maintenanceに遷移確認
停止ASH Admin Portalから対象ノードをShutdownし、Power Offに遷移確認
Key更新RBSUでReset All Keys to Platform Defaultsを実行する
再設定再起動後、Secure Bootを再度有効化し、再起動
確認Secure Boot有効を確認し、Shutdown、Power Offを確認
起動ASH Admin PortalからNodeをStartし、Power Onに遷移確認
組み込みASH Admin Portalから対象ノードをResumeし、Runningに遷移確認
確認クラスタとVolumeの正常性を確認する

何を作ったのか

Windowsならデフォルトで入っているPowershell 5.1を使ったWorkflowエンジン

項目内容
UIPowerShell TUI
接続先ASH Admin API / PowerShell、HPE iLO Redfish API
Workflow18 STEP、状態保存、Retry、再開対応
承認3か所のApproval GateでNodeNameを入力

Workflowの全体像

こんな感じ。青色はWorkflowが決定論的に自動実行するところ、赤色は人間が承認するところ

同じ番号のコネクタへ続く。

全体のアーキテクチャ

Powershellのモジュール構造は以下。状態管理にDBは使わずstate.jsonファイルをSoTとする

モジュール役割
Launcher各モジュールを読み込み、State、接続、Inventory、TUIを初期化する
ConfigRegion選択、認証情報、ASH Admin接続を扱う
InventoryNode、BMC Address、Volumeの状態を取得する
TUI状態表示、Node Lock、DryRun / Exec切替、キー入力を扱う
Workflow18 STEP、次の処理、Approval Gate、進捗保存を制御する
AdaptersASH Admin APIとiLO Redfish APIの操作と状態確認を行う
StatephasecurrentStep、エラー、Inventory、ログを永続化する

TUIはこんな感じ

RBSU MonitorのPowerShell TUI。Node一覧と18 STEPの進捗を表示

18 STEPの決定論的Workflow

選択したノードに対して以下のフローを順次実行。2、3、15はApproval Gateによる人間の承認が発生

#STEP実行内容完了条件
1ResetAllKeysToDefaultiLO RedfishでPlatform DefaultへリセットHTTP 200
2ASH Node drainDisable-AzsScaleUnitNodeを実行ASHがMaintenance
3ASH ShutdownAdmin REST APIでShutdownHTTP 200 / 202を受理
4Power Off confirmediLOをポーリングPowerState=Off
5RBSU Once設定Boot OverrideをBiosSetup / Onceへ変更HTTP 200
6iLO Power OnRedfishで電源ONPower On要求正常終了
7Secure Boot Disabled確認RBSU到達状態をポーリング2回連続RBSU到達を確認
8Power Off before staging安全条件を再確認してForceOffPowerState=Off
9SecureBootEnable=true電源OFF状態でSecure Bootを有効化SecureBootEnable=true
102回目のRBSU Once設定Boot Overrideを再設定PATCH正常終了
11iLO Power OnRedfishで電源ONHTTP 200
12Secure Boot Enabled確認RBSU到達状態をポーリング2回連続RBSU到達を確認
13Power Off after RBSU安全条件を再確認してForceOffPowerState=Off
14Normal boot確認Onceを確認し、必要な場合だけPATCHBootSourceOverrideEnabled=Disabled
15ASH Start通常起動を開始HTTP 200
16ASH Start confirmedASH状態をポーリングMaintenance / Running
17ASH ResumeEnable-AzsScaleUnitNodeを実行HTTP 200
18最終正常性確認Nodeと全VolumeをポーリングNodeがRunning / Running、全VolumeがHealthy / OK

各STEPの動き

各STEPはRetry耐性強化を目的に、基本的に3つのGateを状態遷移の単位とする

Gate内容
Pre-Check Gateどの状態ならSTEPを開始してもよいかのGate
Execute Gate設定変更等の処理を行うGate
Post-Check Gate処理が完了し、後続STEPに引き渡せる状態か確認するGate

以下イメージ

操作Pre-check GateExecute GatePost-check Gate
DrainMaintenanceになっていないDisableMaintenanceになっている
ForceOffRBSUに到達しているForceOffPowerState=Offになっている

Approval Gate

サービス影響が出る可能性のある作業(ASHのNode Drain、Shutdown、Start等)については、人間の承認をもって実行することにする

Approval Gate人間が判断する理由
Drain対象NodeやRegionを誤ると、予期しないサービス影響が起きる
ShutdownDrain済みで、安全に停止できる対象かを確定する
Start対象Nodeを本当に起動してよいかを確定する

実際のApproval Gateでは、対象Nodeと実行コマンドを表示し、NodeNameの完全一致入力を求める。

text
Target: NODE-01
Action: ASH Node drain
Command to execute:
Disable-AzsScaleUnitNode -Location region_a -Name NODE-01 -Force -Confirm:$false

If this is correct, type the exact NodeName to continue:
> NODE-01

NodeNameとRegionはサンプル値。

NodeName入力を承認にした理由

対象のノードであること、対象のリージョンであることの最終確認ポイントとするために、NodeNameを入力させるようにしました。

実際に使ってみてどうだったか

1ノードあたり15分程度の時短を得ることができた。時間ベースでみると些細なものだが・・
人間が手を動かす点を最小限とし、Nodenameを確認して入力するというところに集中させることができた。
夜間実施ということもあり、手作業と比較しても安全に実施できたのではないかと思っている

観点手作業RBSU Monitor
RBSU操作Remote Consoleで操作Redfish APIで実行
状態確認画面を監視して判断APIをポーリングして期待値を検証
中断手順書と記憶から現在地を復元Stateと実機状態から再開
人間の入力各工程の操作と監視3つのApproval Gate
1 Nodeの経過時間約60分約45分
実績-8時間で12 Node、全24 Nodeに使用

あとがき

Codex+GPT5.6 Solを使ってこのWorkflowを作成しました。散歩している時に思いついてから1日でプロトタイプが完成、翌日には検証環境で回してみて動作を検証できた。
今まではツール化よりも手順書書く方が時短だったかもしれないが、やはり速い。 決定論的な実装ができるならコーディングエージェントを使ったツール化は有効かも。

このツールで得たものは作業時間の圧縮じゃなくて、Approval Gateの承認に人間の作業を集中させることで自動処理中に監視をする必要がなくなったこと。

実際にWorkflowが進んでいる間は上長、作業者を含めて雑談しながら待つということができたことから考えると、単に作業時間が短くなったことが効能ではなく、
普段仕事中に時間をとってまでできないような話ができる時間を生み出したという点について価値のあるものになったのではないかなと思いました。

AI活用が賑わっていますが、LLM活用ではなくコーディングエージェントとして使ってみた話でした
実装は結構頑張って考えたのですが・・誰も興味がないようで・・全然コメントないので・・
悲しくなってここに供養することにしました。

Appendix: State.jsonについて

STEPが正常終了した時
json
{
  "schemaVersion": 1,
  "region": "region_a",
  "updatedAt": "2026-08-20T18:10:42+09:00",
  "nodes": [
    {
      "id": 1,
      "name": "NODE-01",
      "status": "completed",
      "phase": "resume_confirmed",
      "currentStep": "",
      "iloIp": "192.0.2.10",
      "ashStatus": "Running",
      "powerState": "Running",
      "iloStatus": "OK",
      "lastError": "",
      "updatedAt": "2026-08-20T18:10:42+09:00"
    }
  ],
  "volumes": [
    {
      "label": "InfrastructureVolume-01",
      "healthStatus": "Healthy",
      "operationalStatus": "OK",
      "repairStatus": ""
    }
  ],
  "logs": [
    {
      "timestamp": "2026-08-20T18:10:42+09:00",
      "level": "INFO",
      "nodeName": "NODE-01",
      "message": "Workflow completed."
    }
  ]
}
STEPが異常終了した時
json
{
  "schemaVersion": 1,
  "region": "region_a",
  "updatedAt": "2026-08-20T15:42:18+09:00",
  "nodes": [
    {
      "id": 1,
      "name": "NODE-01",
      "status": "failed",
      "phase": "shutdown",
      "currentStep": "power_off_confirmed",
      "iloIp": "192.0.2.10",
      "ashStatus": "Maintenance",
      "powerState": "Stopping",
      "iloStatus": "OK",
      "lastError": "Timed out waiting for iLO PowerState=Off.",
      "updatedAt": "2026-08-20T15:42:18+09:00"
    }
  ],
  "volumes": [],
  "logs": [
    {
      "timestamp": "2026-08-20T15:42:18+09:00",
      "level": "ERROR",
      "nodeName": "NODE-01",
      "message": "Step failed: Timed out waiting for iLO PowerState=Off."
    }
  ]
}