千手エージェントはプロセスツリーの処理が全て終わらないと応答を返さない

開発

久しぶりに技術系のネタです。
昨年から参画している案件でSenjuDCを使っているのですが、
これまで触ってきた経験も無い&お試しする環境も無いので悪戦苦闘しています。。。

今回のオチはもうタイトルに書いてある通りです。
どういうプロセスでこの結論に辿り着いたか、どうやって解決したかを書きます。

Senju DC とは

SenjuDCはシステム運用管理ツールを提供してくれます。
ジョブの管理やモニタリング等、できることは多岐にわたります。

詳しくは公式ページを参照してください。
機能が多すぎ&説明できるほどノウハウも無いので・・・

どうでもいいことですが、製品名はSenjuなのに、マニュアル等には千手と書かれているんですよね。
ここでは日本語表記で進めます。

運用で良く使うコマンドを千手に登録できる

今回私が関与する機能は「コマンド」になります。
システム運用で多用されるコマンドを千手マネージャーに登録でき、タイプミスを防ぎつつワンクリックで実行できるというメリットがあります。
コマンドには2種類あります。
1.千手コマンド
2.ユーザーコマンド

千手コマンドは千手にプリセットされているコマンドとなっており、追加・変更・削除ができません。
一方、ユーザーコマンドは利用者が自由に設定できるコマンドとなっています。

コマンドを使って何をするのか

今回のミッションはコマンドを使って、千手エージェントの再起動を行うというものです。

WindowsOSで稼働しているサーバにおいて、予期せぬシャットダウンがあった場合、千手エージェントの起動が不完全となる事象がありました。

この不完全な状態を解消する為に、千手エージェントの再起動が必要なのです。

重要な問題がある

通信が途絶える

運用管理ツールは、運用を管理するサーバと運用される側のサーバにそれぞれマネージャーとエージェントをインストールして使います。マネージャーからエージェントへ指示を送って様々なオペレーションを実行するわけです。

flowchart LR
  manager[マネージャー]
  agent[エージェント]
  manager --指示--> agent
  agent --応答--> manager

エージェントを再起動するという事は、マネージャーとエージェント間のやり取りができなくなる瞬間が出てきます。

flowchart LR
  manager[マネージャー]
  agent[エージェント:停止中]
  manager -.指示が届かない.-> X:::invisible
  classDef invisible fill:none,stroke:none,stroke-width:0px,color:none,width:10;
  X ~~~ agent

運管からの再起動は公式非推奨

エージェントの停止・起動は対象サーバのターミナルから実行するように。と公式ページにも記載がありました。非推奨というより、【警告】として書かれているので、禁止に近いですね。

Windowsエージェントに対して、運用管理サーバーからリモートでsj_haltコマンドを実行すると、sj_haltコマンドが正常に終了することができません。本コマンドは、必ず監視対象ノードのコマンドプロンプトにて実行して下さい。

8. 千手コマンド一覧 — Senju DevOperation Conductor 2024.0.0 Developers Guide

さぁ困りました。

問題のまとめ

  1. エージェント・マネージャー間の通信が行えない為、マネージャー側でエラーが発生する。
  2. 運管からエージェントの再起動コマンドを投入するのは禁止されている。

この2つをクリアしないとダメそうです。

通信遮断問題・コマンド制約への対策

マネージャーはエージェントに対して指示を出します。
エージェントは指示通り動作して結果をマネージャーに返します。

再起動を行うコマンドを実行すると、即座にエージェントが停止処理を始める為
sj_mremsh(.com) 'user' 'node' 'sj_halt'を実行してしまうとマネージャーとの通信が途絶えます。

また、問題点の2つ目にある運管からエージェントの再起動を行ってはいけないという制約もあるので、再起動コマンドはエージェント側でバッチ実行させることにしました。

しかし、エージェントがバッチを即実行してしまうと、通信が切れてしまうのでtimeoutを挟んで時間差でバッチを実行させてみました。

flowchart LR
  manager[マネージャー]
  agent[エージェント]
  batch[バッチ
  sj_halt
  sj_boot]
  manager --指示--> agent
  agent --timeout--> batch

マネージャーに応答が返ってこない

エージェントがバッチを時間差で呼び出すので、マネージャーへの応答は返ってくるものだと想定していました。が、エージェントはtimeoutで非同期実行したバッチの終了も待っていました。更に、Batchの中で実行されるsj_haltによってAgentそのものが停止する為、呼び出されたBatchの処理も終了するというカオスに。。。結局sj_bootが動かないのでAgentが停止したままとなりました。

sequenceDiagram
  activate Manager
  Manager->>Agent:指示
  activate Agent
  Agent->>Batch:timeoutで非同期実行
  activate Batch
  note over Manager,Agent:ここで応答して欲しかった
  Batch->>Agent:sj_halt実行
  deactivate Agent
  deactivate Batch
  note over Agent,Batch:Agentが停止する為<br>呼び出した<br>Batchも止まる
  Agent--xManager:Agent停止により<br>応答不可
  deactivate Manager

これでは何の意味もありません…

別プロセスで実行させる

エージェントがコールしたバッチの処理が完了するまでエージェントが待機するというのであれば、別プロセスで起動させればエージェントの監視から外れるのでは?と考えました。

コマンドプロンプトのstartを使えば、本体のプロセスと切り離して処理を実行できるはず。と…

運管から実行するリモートコマンドにstartを含めることも試しましたが、
sj_mremshではstartを直接実行することは許可されていませんでした。

次に考えたのが、中間バッチを挟む対応です。
千手エージェントから中間バッチを呼び出し、中間バッチの中で本命のバッチをstartで別プロセスとして実行するようにしました。

flowchart LR
  manager[マネージャー]
  agent[エージェント]
  midBatch[中間バッチ]
  batch[本命バッチ]
  manager--指示-->agent
  agent-->midBatch
  midBatch--timeout, start-->batch

この構成であれば、エージェントは中間バッチの処理終了で応答を返すと考えました。
ところが、タイトルの問題がここで発生します。
そう!本命バッチの処理を待ってしまうのです!!

sequenceDiagram
  participant Manager as マネージャー
  participant Agent as エージェント
  participant MidBatch as 中間バッチ
  participant Batch as 本命バッチ
  activate Manager
  Manager->>Agent:
  activate Agent
  Agent->>MidBatch:
  activate MidBatch
  MidBatch->>Batch:非同期実行
  activate Batch
  MidBatch->>Agent:
  deactivate MidBatch
  note over Manager,Agent:ここで応答して欲しかった
  Batch->>Agent:sj_halt
  deactivate Agent
  note over Manager,Agent:sj_haltにより通信切断
  Batch->>Agent:sj_boot
  activate Agent
  deactivate Batch
  deactivate Agent
  deactivate Manager

この手法で目的の動作は達成できなかったものの、sj_bootまでは実行させることができました。
これまでの対応から以下の事がわかりました。

  • 千手エージェントから直接startコマンドは実行できない
  • 千手エージェントから呼び出されたバッチの中でsj_haltを実行するとAgent諸共停止する
  • 千手エージェントから別プロセス起動したバッチであれば最後まで処理を続行できる

いろいろとググったりAIに質問してみたりと試行錯誤していく中で、
プロセスの親子関係に問題があるのではないか?と閃く

完全に独立したプロセス Start-Process

千手エージェントから中間バッチを介して本命バッチを起動しても
プロセスツリーでは千手エージェントとの関連を断ち切れていないとのこと。

関連性を断ち切る為の手段としてpowrshellStart-Processを使用しました。
これによって千手エージェントの呪縛から本命バッチを解き放つことができました。

最終的に以下の動作になりました。

sequenceDiagram
  participant mng as マネージャー
  participant agt as エージェント
  participant mid as 中間バッチ
  participant psh as Powershell
  participant btc as 本命バッチ
  activate mng
  activate agt
  mng->>agt:
  activate mid
  agt->>mid:
  activate psh
  mid->>psh:Start-Process
  psh->>psh:timeout
  mid->>agt:
  deactivate mid
  agt->>mng:
  deactivate mng
  note over mng:正常終了の表示
  psh->>btc:実行
  deactivate psh
  activate btc
  btc->>agt:sj_halt
  deactivate agt
  btc->>agt:sj_boot
  activate agt
  deactivate btc
  deactivate agt

まとめ

今回の調査はなかなか骨が折れました。
不慣れなツールであり、検証を行う環境も時間制限があったり等。。。

ただ、こういった調査ではわからないなりに仮説を立てて、その仮説を基に実験してみる
というのが確実に前進していくものだなと改めて感じました。
何となく情報収集をしていても、ポイントを理解しないと時間だけが過ぎていきます。

今回の調査でいうと「プロセスの親子関係に何かあるのでは?」というところがポイントでした。

ググってもこの情報は出てこなかったので、
同じように苦戦している方のお役に立てれば幸いです。

コメント

バイクアイコン
バイクアイコン
clubman