1.はじめに

AWS Systems Manager Patch Manager(以下、Patch Manager)とは、EC2 インスタンスやオンプレミスサーバーに対するセキュリティパッチや更新プログラムの適用を自動化・管理できるサービスです。

本記事では、AWS 上の EC2 インスタンスを Patch Manager の実行対象とします。
同一アカウント内の 2 台の Windows Server に Patch Manager でパッチを適用するにあたり、「MaxConcurrency = 1」(1 台ずつ適用)および「MaxErrors = 0」(1 台でも失敗したら後続を停止)という構成を検討していました。その際、ある疑問が生じました。
メンテナンスウィンドウのタスクに設定する実行タイムアウト(StepTimeoutSeconds)が「ターゲット(1 台ごと)に個別」に適用されるのか、それとも「対象 2 台の合算」に対して適用されるのかという点です。

この違いによって、設定すべきタイムアウト値(1 台あたりの所要時間でよいのか、台数分をかけ合わせた時間を確保すべきなのか)が変わってくるので、挙動を確認してみました。
本記事ではその検証内容と結果を紹介します。

用語の補足

  • StepTimeoutSeconds:実行タイムアウト秒数。処理がこの時間を超えるとタイムアウトと判定される。
  • MaxConcurrency:パッチ適用の同時実行最大数。1 台ずつの順次実行の場合 1 を設定する。
  • MaxErrors:後続処理を停止するまでに許容されるエラー数。1 台目の失敗時に 2 台目の実行を抑止する場合 0 を設定する。

2.検証構成と前提条件

システム構成の概要

リージョンは東京リージョン(ap-northeast-1)です。
インターネットへのアウトバウンド通信が可能なネットワーク環境にて、異なる Availability Zone(ap-northeast-1a、ap-northeast-1c)のサブネットへ Windows Server 2025 の EC2 インスタンスを 1 台ずつ、計 2 台配置しています。

パッチの適用を試すにあたり、AMI には本検証実施日の約 2 ヶ月前にリリースされた Windows_Server-2025-Japanese-Full-Base-2026.07.15(ami-0116afe3d5f60ebf0)を使用しています。

2 台の EC2 インスタンスを稼働させています。

Patch Manager の設計と疑問の背景

Patch Manager 側の設定として、パッチベースライン、パッチグループ、メンテナンスウィンドウ、ターゲット、タスクは、いずれも「1 つ」のみ作成しています。
EC2 インスタンスごとに個別の設定を用意するのではなく、共通のタグ(PatchGroup = dev)を付与した 2 台の EC2 インスタンスを 1 つのメンテナンスウィンドウのタスクでまとめて処理する構成です。

パッチベースラインは Windows Server 向けのカスタムベースラインとし、分類フィルターに「CriticalUpdates」「SecurityUpdates」、MSRC 重要度フィルターに「Critical」「Important」を指定しています。

全体の設定イメージは以下のとおりです。

AWS Systems Manager
  └ パッチベースライン (Windows Server 向けカスタムベースライン)
       ├─ 分類フィルター: CriticalUpdates, SecurityUpdates
       ├─ MSRC 重要度フィルター: Critical, Important
       └─ パッチグループ (dev)
            ├─ EC2 win-1a (タグ: PatchGroup = dev)
            └─ EC2 win-1c (タグ: PatchGroup = dev)

メンテナンスウィンドウ (1 つ)
  ├─ ターゲット (1 つ): tag:PatchGroup = dev に合致する 2 台
  └─ タスク (1 つ): AWS-RunPatchBaseline (RUN_COMMAND)
       ├─ Operation = Install
       ├─ RebootOption = RebootIfNeeded
       ├─ StepTimeoutSeconds = 実行タイムアウト(検証ごとに変更)
       ├─ MaxConcurrency = 1 (1 台ずつ実行)
       └─ MaxErrors = 0      (1 台でも失敗したら停止)

1 台ずつ実行される動作は、タスク内の「MaxConcurrency = 1」というレート制御によるものです。この設定により、指定数で順次処理されます。
設定したレート制御の画面が以下です。

1 つのタスクのスコープが複数台のインスタンスであるからこそ、タスクに指定した実行タイムアウトは 2 台全体の合算値としてカウントされるのか、それともターゲットごとに個別にカウントされるのかという疑問が生じました。

3.検証1:事前検証(1台あたりの所要時間確認)

検証の目的

本格的な検証を行う前に、まずは「対象のインスタンスに対し、今回のパッチベースラインでパッチを適用した場合、1 台あたりどのくらいの所要時間がかかるのか」という基礎データを取得します。
パッチ適用の所要時間を把握し、その時間を次の検証で活用します。

検証の設定

実行タイムアウト(StepTimeoutSeconds)は 10800 秒(3 時間)とします。

パラメータを設定した画面が以下となります。
※ 本検証、後続の検証においてもタイムアウト(配信タイムアウト:コマンドが対象インスタンスに届きパッチ適用が始まるまでの制限時間)は 300 秒(5 分)とします。

実行と結果確認

実行直後のコマンドステータスを確認したものが以下となります。

MaxConcurrency = 1 に設定しているため、1 台目のインスタンスが「進行中」となり、もう 1 台のインスタンスは「保留中」として待機している状態が確認できます。

しばらく待機し、1 台目のパッチ適用が完了した直後の状態を確認したものが以下となります。

1 台目のインスタンス(i-0d3bf…)の処理が「成功」となりました。
開始時刻が 23:27:53 GMT、終了時刻が 00:15:47 GMT であるため、所要時間は約 48 分です。
そして 1 台目の完了と同時に、保留中だった 2 台目(i-09f0…)が「進行中」へと遷移している様子が見て取れます。

続いて 2 台目の処理も完了するまで待機した結果が以下となります。

2 台目のインスタンスも問題なく「成功」となりました。
2 台目の開始時刻は 00:15:48 GMT、終了時刻は 00:59:29 GMT となっており、所要時間は約 44 分でした。
2 台合計の所要時間は約 92 分となります。

この結果から、1 台あたりのパッチ適用には 45〜50 分程度を要することが判明しました。
ただし、今回設定した 3 時間(10800 秒)は、1 台あたりの所要時間(約 45〜50 分)と 2 台合算の所要時間(約 92 分)のどちらに対しても十分な長さです。
つまり現時点では、実行タイムアウトが「1 台ごとに 3 時間」なのか「2 台合算で 3 時間」なのかは未確定の状態となります。

4.検証2:本格検証(実行タイムアウトのスコープ特定)

仮説の設定

事前検証の結果を踏まえ、実行タイムアウトの適用スコープを特定するための仮説を立ててみます。

  • 1 台あたりの所要時間:約 45 〜 50 分
  • 2 台合計の所要時間:約 92 分(約 1 時間 30 分)

ここで、実行タイムアウト(StepTimeoutSeconds)を「3600 秒(1 時間)」に設定してみます。
この数値を設定した場合、仕様の違いによって以下の分岐が起こると予測できます。

  • 仮説 A(合算カウントの場合):2 台の処理時間の合計に対して 1 時間が適用される。1 台目の処理に約 50 分かかるため、2 台目の処理中に合計時間が 1 時間(3600 秒)を超過し、2 台目はタイムアウトで失敗する。
  • 仮説 B(個別カウントの場合):各インスタンスに対して個別に 1 時間が適用される。各台とも約 45 〜 50 分で処理を完了できるため、2 台とも制限時間内に収まり、両方とも成功する。

検証の実行と結果

検証環境の前提条件(パッチ未適用)を統一するため、作成した EC2 インスタンスおよびパッチ適用関連リソースをすべて削除し、再度同じ AMI から環境を再作成しました。
この再作成にあたり、実行タイムアウト(StepTimeoutSeconds) には「3600」を設定し、パッチ適用を実行します。

タスクのパラメータ設定を変更した画面が以下となります。

タスクを実行した直後の状態を確認したものが以下となります。

事前検証と同様に、1 台目(i-02fe…)が「進行中」、2 台目(i-0282…)が「保留中」の状態でスタートしました。

1 台目のパッチ適用が完了したタイミングの画面が以下となります。

1 台目のインスタンスが「成功」となりました。
開始時刻は 01:20:26 GMT、終了時刻は 02:16:16 GMT であり、所要時間は約 56 分でした。
1 台目だけで約 56 分を消費しています。もし合算カウントの仕様であれば、タスク全体に残された時間はわずか 4 分程度しかありません。

そのまま 2 台目の完了を待った結果が以下となります。

結果は、2 台目のインスタンスも「成功」となりました。
2 台目の開始時刻は 02:16:17 GMT、終了時刻は 02:57:58 GMT であり、約 42 分を要して完了しています。
タスク全体の経過時間は約 98 分に達しています。

この結果から、タスク全体の経過時間に対して 3600 秒が適用されているのではなく、インスタンス 1 台ごとに個別のタイムアウト枠(3600 秒)が割り当てられていることが分かりました。
つまり、実行タイムアウト(StepTimeoutSeconds)の適用スコープは「ターゲットごとに個別」であると判定できます。

5.検証3:補足検証(タイムアウトパラメータの実証)

検証の目的

本格検証により「ターゲットごとに個別にカウントされる」という結論となりましたが、「実行タイムアウト(StepTimeoutSeconds) のパラメータがタイムアウト制御として機能しているのか」を追加で確認してみます。

あえて 1 台あたりの想定所要時間(約 50 分)よりも大幅に短い「600 秒(10 分)」を実行タイムアウトに設定し、意図的にタイムアウトを発生させてみます。
もし期待通り動作するのであれば、1 台目が 10 分経過時点でタイムアウトして失敗となり、かつ「MaxErrors = 0」の制御が働いて 2 台目は実行されずに停止するはずです。

本検証においても環境を再作成し、実行タイムアウト(StepTimeoutSeconds) には「600」を設定します。

検証の実行と結果

実行タイムアウト(StepTimeoutSeconds) を「600」に設定した画面が以下となります。

タスクを実行した直後の状態が以下となります。

これまでと同様、1 台目が「進行中」、2 台目が「保留中」となります。
そして約 10 分が経過した後の実行結果を確認した画面が以下となります。

期待通り、1 台目のインスタンスがタイムアウトになりました。
開始時刻が 03:16:53 GMT、終了時刻が 03:26:55 GMT となっており、約 10 分(602 秒)で実行が打ち切られていることが確認できます。
さらに、1 台目がタイムアウトしたことによって「MaxErrors = 0」のしきい値に達し、待機中だった 2 台目は実行されることなく処理が終了しました。

実行タイムアウト(StepTimeoutSeconds) がタイムアウト制御として機能していること、および MaxErrors = 0 による停止の仕組みが正常に動作していることが確認できました。

6.おわりに

Patch Manager において、1 つのメンテナンスウィンドウタスク配下で MaxConcurrency = 1 を指定した際、実行タイムアウト(StepTimeoutSeconds)がどのようにカウントされるかを検証しました。

検証の結果、実行タイムアウトは「ターゲット(1 台ごと)に個別でカウントされる」ことが確認できました。
そのため、今回検証を行った構成においては、実行タイムアウト(StepTimeoutSeconds) には台数分をかけた時間ではなく、1 台あたりの所要時間に合わせた値を設定するアプローチが適切と考えられます。

同様の構成でのインフラ設計で悩まれている方の参考になれば幸いです。