1つのSSMドキュメントで複数OSのEC2インスタンスに対し、OSごとに異なるコマンドを実行する

1つのSSMドキュメントで複数OSのEC2インスタンスに対し、OSごとに異なるコマンドを実行する

Clock Icon2025.01.24

はじめに

通常、異なるOSに対してAWS Systems Manager オートメーションでコマンドを実行する場合、OSごとに個別のSSMドキュメントを作成します。

しかし、1つのSSMドキュメントでOS別のコマンドを実行する方が、以下の利点があります。

  • 一度の実行で完了
  • EC2インスタンスを指定する場合、タグの管理が1つで済ませられる

本記事では、1つのSSMドキュメント(以降、オートメーションランブック)で、複数OSのEC2インスタンスに対してOS別のコマンドを実行する方法を紹介します。

オートメーションランブックを作成

各OSに対して実行するオートメーションランブックを作成します。

SSMドキュメントに遷移し、[ドキュメントの作成]から[オートメーション]を選択します。

cm-hirai-screenshot 2025-01-17 17.16.16
以下のコードを貼り付けます。

check-linux-windows
schemaVersion: '0.3'
description: Check OS settings using SSM Automation with loop.
assumeRole: '{{ AutomationAssumeRole }}'
parameters:
  AutomationAssumeRole:
    type: String
    description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
  InstanceId:
    type: StringList
    description: The IDs of the EC2 instances to check.
  CheckHostname:
    type: String
    default: check
    description: Check hostname or skip.
    allowedValues:
      - check
      - skip
mainSteps:
  - name: ProcessInstances
    action: aws:loop
    isEnd: true
    inputs:
      Iterators: '{{ InstanceId }}'
      Steps:
        - name: GetInstancePlatform
          action: aws:executeAwsApi
          nextStep: CheckPlatform
          isEnd: false
          inputs:
            Service: ec2
            Api: DescribeInstances
            InstanceIds:
              - '{{ ProcessInstances.CurrentIteratorValue }}'
          outputs:
            - Name: Platform
              Selector: $.Reservations[0].Instances[0].PlatformDetails
              Type: String
        - name: CheckPlatform
          action: aws:branch
          inputs:
            Choices:
              - NextStep: RunWindowsCommand
                Variable: '{{ GetInstancePlatform.Platform }}'
                Contains: Windows
              - NextStep: RunLinuxCommand
                Variable: '{{ GetInstancePlatform.Platform }}'
                Contains: Linux
            Default: ThrowError
        - name: ThrowError
          action: aws:executeScript
          isEnd: true
          inputs:
            Runtime: python3.11
            Handler: throw_error
            Script: |
              def throw_error(events, context):
                  raise Exception("Unsupported platform detected. Only Linux and Windows are supported.")
        - name: RunLinuxCommand
          action: aws:runCommand
          maxAttempts: 1
          timeoutSeconds: 10
          isEnd: true
          inputs:
            DocumentName: AWS-RunShellScript
            Parameters:
              commands:
                - if [[ "{{ CheckHostname }}" == "check" ]]; then hostname; else echo "Skipping hostname check"; fi
              executionTimeout: '10'
            InstanceIds:
              - '{{ ProcessInstances.CurrentIteratorValue }}'
        - name: RunWindowsCommand
          action: aws:runCommand
          maxAttempts: 1
          timeoutSeconds: 180
          isEnd: true
          inputs:
            DocumentName: AWS-RunPowerShellScript
            Parameters:
              commands:
                - chcp 65001
                - hostname
            InstanceIds:
              - '{{ ProcessInstances.CurrentIteratorValue }}'

cm-hirai-screenshot 2025-01-23 13.40.47

各ステップの内容の概要を説明します。

aws:loop

aws:loopアクションは、指定されたEC2インスタンスの数だけ処理を繰り返します(for each処理)。

イテレーター
'{{ InstanceId }}'

ステップ名はProcessInstancesです。
cm-hirai-screenshot 2025-01-24 8.37.46

aws:executeAwsApi

EC2のDescribeInstances APIを使用して、インスタンスのOS情報を取得します。

platform-details

  • The platform (Linux/UNIX | Red Hat BYOL Linux | Red Hat Enterprise Linux | Red Hat Enterprise Linux with HA | Red Hat Enterprise Linux with SQL Server Standard and HA | Red Hat Enterprise Linux with SQL Server Enterprise and HA | Red Hat Enterprise Linux with SQL Server Standard | Red Hat Enterprise Linux with SQL Server Web | Red Hat Enterprise Linux with SQL Server Enterprise | SQL Server Enterprise | SQL Server Standard | SQL Server Web | SUSE Linux | Ubuntu Pro | Windows | Windows BYOL | Windows with SQL Server Enterprise | Windows with SQL Server Standard | Windows with SQL Server Web

https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html

aws:loopアクションから以下の値が利用可能です。以下は、2つのEC2インスタンスを実行した場合の例です。

{"CurrentIteration":1,"CurrentIteratorValue":"i-aaaaaaaaa"}

このステップが終了後、loopしますので、次に、以下の値が取得できます。

{"CurrentIteration":1,"CurrentIteratorValue":"i-bbbbbbbbb"}

そのため、inputとしてEC2インスタンスIDを取得します。

  • 名前:InstanceIds
  • 入力値:- '{{ ProcessInstances.CurrentIteratorValue }}'
    cm-hirai-screenshot 2025-01-23 16.27.03

EC2インスタンス情報の取得結果からOSのみを出力します。

  • 名前:Platform
  • セレクター:$.Reservations[0].Instances[0].PlatformDetails

ステップ名はGetInstancePlatformです。
cm-hirai-screenshot 2025-01-23 16.28.00

aws:branch

aws:branchアクションにより、OSタイプに応じて以下の3つに分岐します。

  • Windows
  • Linux
  • その他

分岐条件は以下の通りです。

  1. Windows判定(ルール #1)

    • 条件:{{ GetInstancePlatform.Platform }} contains "Windows"
    • 結果:Windowsコマンド実行ステップへ移行
  2. Linux判定(ルール #2)

    • 条件:{{ GetInstancePlatform.Platform }} contains "Linux"
    • 結果:Linuxコマンド実行ステップへ移行
  3. その他(デフォルト)

    • 上記以外の場合
    • 結果:エラー処理ステップへ移行

cm-hirai-screenshot 2025-01-23 16.29.20

以降のステップ

WindowsやLinuxステップに遷移すると、それぞれaws:runCommandでコマンドを実行します。
コマンド内容は、hostnameの出力です。

Linux/Windows以外のOSの場合、以下の処理を実行します。

  1. aws:executeScriptアクションを使用してPythonスクリプトを実行
  2. Exceptionを発生させ、エラーメッセージを表示
def throw_error(events, context):
    raise Exception("Unsupported platform detected. Only Linux and Windows are supported.")

cm-hirai-screenshot 2025-01-23 16.46.08

実行してみる

EC2インスタンス2台を対象に、AWS CloudShellから以下の設定でSSMオートメーションを実行します。
なお、対象のEC2インスタンスには以下のタグを付与しています。

  • キー名:ssm-automation
  • 値:true
aws ssm start-automation-execution \
    --document-name "check-linux-windows" \
    --parameters "AutomationAssumeRole=arn:aws:iam::012345678901:role/AWS-SystemsManager-AutomationExecutionRole,\
        CheckHostname=check" \
    --target-parameter-name InstanceId \
    --targets Key=tag:ssm-automation,Values=true 

実行結果は以下の通りです。各EC2インスタンスの実行結果を個別に確認できます。

cm-hirai-screenshot 2025-01-23 17.50.03
Windowsの実行結果です。
cm-hirai-screenshot 2025-01-23 17.50.15
Linuxの実行結果です。
cm-hirai-screenshot 2025-01-23 17.50.25

OSごとに異なるステップに分岐し、コマンド実行できていることが確認できました。

なお、Automationでは、条件分岐などの条件付きアクションにおいて実行条件を満たさないステップは、オートメーション完了後もPendingステータスのまま残ります。

そのため、使用されなかったステップは Pending ステータスとなります。

Pending
ステップの実行が開始されていません。オートメーションで条件付きアクションが使用されている場合、ステップを実行するための条件が満たされなかった場合、オートメーションが完了した後も、ステップはこの状態のままになります。ステップが実行される前にオートメーションがキャンセルされた場合も、ステップはこの状態のままになります。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-statuses.html

参考

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-action-loop.html

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/monitor-commands.html

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.