本記事は連載「ServiceNow標準機能だけで作るPull型自動化連携」の第2回です。
第1回では、この仕組みの必要性とビジネス価値、連載の目次を紹介しました。
今回は、実装に入る前に全体アーキテクチャと設計方針を整理します。
この回で分かること
- ServiceNowと自動化エンジンの責任分界
- 「自動化2.0」のどの部分を、ServiceNowのどの機能で実現するのか
- SCTASKの State × Assigned to だけで自動化の状態を表す方法
- 正常時・失敗時の状態遷移
- Flow Designer、カスタムテーブル、カスタムフィールドをあえて使わない理由
1. 全体アーキテクチャ
ServiceNowから自動化エンジンへの通信は一切ありません。すべて自動化エンジンから見た外向きのHTTPS通信です。そのため、ServiceNowから社内の自動化基盤へ到達する経路を用意する必要がありません。
2. 責任分界
| ServiceNowの責務 | 自動化エンジンの責務 |
|---|---|
| 依頼の受付と入力値の保持 | 実行待ちSCTASKの定期取得 |
| Execution PlanによるSCTASK生成と順序制御 | 対象タスクの確保 |
| SCTASKの標準的な状態管理 | 実行開始状態への更新 |
| 実行結果JSONの保持、Work Notesへの記録 | 作業の実行 |
| 成功時は次のステップへ進める | 実行結果JSONの生成 |
| 失敗時は運用担当グループへ引き継ぐ | 成功・失敗の結果をServiceNowへ返す |
ServiceNowは「何を、どの順番で、誰がやるか」を管理し、自動化エンジンは「自分宛ての仕事を取って、やって、報告する」ことだけに専念します。
自動化エンジンは、業務フローの順序も、失敗時の引継ぎ先も知りません。それらはすべてServiceNow側の定義で決まります。
3. 自動化2.0との対応
第1回で紹介した「自動化2.0」12の考え方を、この仕組みでは次のように実現しています。
| 自動化2.0の要素 | この仕組みでの実現手段 |
|---|---|
| 自動化1.0(手順の置き換え) | 自動化エンジン上のPlaybook・スクリプト |
| サービス化(作業チーム外の人が使える形にする) | Catalog Item + Variable Set |
| サービスの連結 | Execution Plan(作業ごとのSCTASKを順番に生成) |
| API化 | Table API + Scripted REST API |
| 人の作業との組み合わせ | 担当が人のSCTASKを、同じExecution Planの中に配置 |
ポイントは、連結の仕組みを自動化エンジン側に作らないことです。
連結をAAPのWorkflowなどで組むと、途中に人の作業を挟みにくくなり、作業の順序がServiceNowから見えにくくなります。順序制御をExecution Planに任せることで、自動化の作業と人の作業を同じSCTASKとして並べられます。
4. 状態管理の設計 ― State × Assigned to
4.1 基本の考え方
自動化の状態を管理するためのフィールドやテーブルは追加しません。SCTASKがもともと持っている次の2つの組み合わせで、状態を表します。
- State(標準の状態フィールド)
- Assigned to(担当者)
自動化エンジンの状態は、「状態を表す名前を持つ自動化ユーザー」への割当てで表現します。
| ユーザー | 意味 |
|---|---|
autoengine1 |
取得待ち、または確保済みで実行待ち |
autoengine1running |
自動化エンジンで実行中 |
これらのユーザーは、Assignment group autoengine1group に所属させます。
4.2 状態の一覧
| 処理状態 | State | Assigned to / Assignment group |
|---|---|---|
| 実行待ち | Open(1) | autoengine1 |
| 確保済み・実行待ち | In Progress(2) | autoengine1 |
| 実行中 | In Progress(2) | autoengine1running |
| 成功 | Closed Complete(3) | 変更しない |
| 技術的失敗 | In Progress(2) | Assignment groupをfailure_assignment_groupへ変更、Assigned toは空欄 |
Stateの内部値(1/2/3)はインスタンスによって異なる場合があります。また、Execution Planが次のステップへ進む条件と、Closed Completeの扱いが整合しているかは、必ず実機で確認してください。
4.3 状態遷移図
4.4 なぜ「確保」と「実行開始」を分けるのか
「確保(State変更)」と「実行開始(Assigned to変更)」は、別々のステップにしています。
- 確保: ディスパッチャーが「このタスクは取った」と宣言します。次回のPullで同じタスクを再取得しないようにするためのものです。Table APIでStateを2にするだけの、単純な更新です。
-
実行開始: ワーカーが実際に作業を始める直前に、
autoengine1→autoengine1runningへ変更します。このとき、現在の担当がautoengine1である場合だけ更新する条件付き更新(Compare-and-set)を行います。期待値と一致しない場合は、HTTP 409が返ります。
この分割により、「確保はしたが、まだ実行していない」状態と「実行中」の状態を、ServiceNowの画面上で区別できます。自動化エンジンが途中で停止した場合に、どこで止まったのかを判断しやすくなります。
4.5 失敗時の扱い
自動化が技術的に失敗した場合、SCTASKは次のように更新されます。
- StateはIn Progressのまま
- Assignment groupを、依頼ごとに指定した
failure_assignment_groupへ変更 - Assigned toは空欄
「失敗」という専用の状態を作るのではなく、通常の人手対応キューにそのまま載せるのが狙いです。運用担当者は、いつもの自分のグループのキューで作業を受け取り、手動で作業を完了させるか、依頼者へ差し戻すかを判断します。
自動リトライは、原則として行いません。インフラ作業は「同じことを2回やってよいか」が作業ごとに異なるため、再実行の判断は人に委ねています。
5. 処理の振り分け ― Short descriptionを処理キーにする
自動化エンジンが「このSCTASKで何をすべきか」を判断するキーには、SCTASKのShort descriptionを使います。
Execution PlanのTask TemplateのShort descriptionに、機械が判読できる値を設定しておきます。
<REQUEST_TYPE>_<ACTION_NUMBER>
REQTYPE_LINUXLOG_ACTION1 → linux_log_retrieve.yml
REQTYPE_LINUXLOG_ACTION2 → linux_log_archive.yml
REQTYPE_LSOF_ACTION1 → linux_lsof.yml
処理種別のための専用変数(例: automation_type)は作りません。Task Templateは作業単位で定義するものなので、そこに処理キーを持たせるのが最も素直です。
1つのCatalog Itemの中に複数の自動化作業があっても、作業ごとにキーを分けられます。
6. 入力と結果のデータ設計
6.1 入力 ― Variable Set
| 種類 | 変数の例 | 用途 |
|---|---|---|
| 共通Variable Set | target_host |
作業対象 |
| 共通Variable Set |
execution_result_json(非表示) |
実行結果の履歴(JSON配列) |
| 共通Variable Set | execution_result_display |
依頼者向けの結果表示 |
| 個別Variable Set | failure_assignment_group |
失敗時の引継ぎ先(全個別セットに必ず用意) |
| 個別Variable Set |
log_path, destination など |
依頼種別に固有の入力値 |
自動化エンジンには、RITMの変数を原則すべて渡します。依頼種別ごとに必要な変数は異なるため、API側では渡す変数を限定せず、人向けの表示用変数やルーティング用の変数だけを除外します。
6.2 結果 ― RITMにJSON履歴として蓄積
自動化エンジンは、結果を次の形式で返します。
{
"sctask": "SCTASK0010006",
"result": {
"status": "SUCCESS",
"jobid": 1234,
"message": "Linux log collected.",
"data": { "target_host": "server01" }
}
}
ServiceNow側では、結果を次の3か所に記録します。
| 記録先 | 内容 | 主な読み手 |
|---|---|---|
RITMのexecution_result_json
|
SCTASKごとの結果をJSON配列に追記 | 後続の自動化作業 |
| SCTASKのWork Notes | Status / Job ID / Message / 整形済みResult Data | 運用者 |
RITMのexecution_result_display
|
結果サマリー | 依頼者 |
結果をRITM単位の履歴として持つことで、作業3が作業1の結果を参照する、といった連結が可能になります。
結果の項目ごとにServiceNowのフィールドを追加することはしません。ServiceNow側は、結果JSONを保存するだけです。
7. あえて使わないもの
| 使わないもの | 理由 |
|---|---|
| ServiceNowからのPush連携 | ServiceNowから社内の自動化基盤への通信経路が不要になり、自動化エンジンの停止がServiceNow側の処理を止めない |
| Flow Designer / IntegrationHub | 依頼種別ごとにフローが増えるのを避け、順序制御はExecution Planに一本化する |
| 状態管理用のカスタムテーブル | SCTASKそのものが状態を持っており、二重管理になる |
| 状態管理用のカスタムフィールド | 標準のState × Assigned toで表現でき、バージョンアップや運用の負担を増やさない |
| 外部インターフェースでのsys_id | インスタンス固有の内部IDに依存せず、SCTASK番号・user_name・グループ名でやり取りする |
ServiceNow側で個別に開発するのは、次の3つだけです。
- SCTASKの詳細取得と、条件付きでAssigned toを更新するScripted REST API
- 結果登録のScripted REST API
- 進捗をRITMへ転記するBusiness Rule
8. 想定する制約
- 本連載のサンプルは、学習・検証用の最小構成です。
- ポーラー(ディスパッチャー)は1つだけであることを前提にしています。Table APIでの確保は条件付き更新ではないため、複数のポーラーを動かす場合は排他制御の追加設計が必要です。
- 取得後、確保前に自動化エンジンが停止すると、同じSCTASKが再取得される可能性があります。必要に応じて、自動化処理側に冪等性を持たせてください。
- 長時間更新されないSCTASKの検知は、ServiceNowの標準機能(SLAやエスカレーション)で行う想定です。
次回予告
次回は、実際にServiceNow上でCatalog Item、Variable Set、Execution Plan、自動化ユーザーとグループを作成します。人の作業と複数の自動化エンジンを組み合わせたExecution Planの設定例も紹介します。
連載記事
- 第1回 なぜ今Pull型連携なのか
- 第2回 全体アーキテクチャと設計方針(本記事)
参考文献
※ 本記事の内容は個人の見解であり、所属する組織の公式な見解ではありません。
-
Qiita Zine「ITインフラ自動化の未来、「自動化2.0」とは何か – Ansible Automates 2021 Japanレポート」(2021年11月17日) https://qiita.com/official-columns/event/202111-red-hat/ ↩
-
日立ソリューションズ「第11回 Automation 2.0 with Ansible Automation Platform」(2024年3月28日) https://www.hitachi-solutions.co.jp/redhat/column/vol11/ ↩