AWS Systems Manager Automation で一部アカウントを除外しながら組織配下の全 EC2 を対象に Distributor パッケージを配布してみた
はじめに
以前、AWS Systems Manager Distributor と Automation を組み合わせて、管理アカウントから組織配下の複数メンバーアカウントに存在する EC2 インスタンスへソフトウェアを配布する方法を試しました。
前回の記事では、配布対象のアカウント ID と EC2 インスタンス ID を明示的に指定して SSM Automation を実行しました。
全体のコマンドは以下のような形です。
aws ssm start-automation-execution \
--document-name "CM-InstallDistributorPackage" \
--parameters '{
"AutomationAssumeRole": ["arn:aws:iam::111111111111:role/AWS-SystemsManager-AutomationAdministrationRole"],
"PackageArn": ["arn:aws:ssm:ap-northeast-1:111111111111:document/test-1"]
}' \
--target-parameter-name "InstanceId" \
--target-locations '[
{
"Accounts": ["222222222222"],
"Regions": ["ap-northeast-1"],
"ExecutionRoleName": "AWS-SystemsManager-AutomationExecutionRole",
"Targets": [
{
"Key": "ParameterValues",
"Values": [
"i-xxxxxxxxxxxxxxxxxx",
"i-yyyyyyyyyyyyyyyyyyy"
]
}
],
"TargetLocationMaxConcurrency": "50",
"TargetLocationMaxErrors": "100%",
"TargetsMaxConcurrency": "5",
"TargetsMaxErrors": "100%"
},
{
"Accounts": ["333333333333"],
"Regions": ["ap-northeast-1"],
"ExecutionRoleName": "AWS-SystemsManager-AutomationExecutionRole",
"Targets": [
{
"Key": "ParameterValues",
"Values": [
"i-zzzzzzzzzzzzzzzzz"
]
}
],
"TargetLocationMaxConcurrency": "50",
"TargetLocationMaxErrors": "100%",
"TargetsMaxConcurrency": "5",
"TargetsMaxErrors": "100%"
}
]' \
--region ap-northeast-1
この中で、アカウントごとに対象 EC2 インスタンス ID を指定している箇所は以下です。
{
"Accounts": ["222222222222"],
"Regions": ["ap-northeast-1"],
"ExecutionRoleName": "AWS-SystemsManager-AutomationExecutionRole",
"Targets": [
{
"Key": "ParameterValues",
"Values": [
"i-xxxxxxxxxxxxxxxxxx",
"i-yyyyyyyyyyyyyyyyyyy"
]
}
]
}
この方式は、対象 EC2 を明確に指定できるため安全です。
一方で、配布対象がほぼ全 EC2 インスタンスである場合、アカウントごとにインスタンス ID を洗い出して指定するのは手間がかかります。
今回は、以下の要件を想定し、組織配下の全アカウントを対象にしつつ、一部の OU / アカウントを除外し、対象アカウント内の全 EC2 インスタンスへ Distributor パッケージを配布する方法を試しました。
- Organizations Root 配下のアカウントを対象にする
- 一部の OU またはアカウント ID は除外する
- 対象アカウントの
ap-northeast-1に存在する全 EC2 インスタンスへ Distributor パッケージをインストールする - アカウントごとに EC2 インスタンス ID を列挙しない
前提
前提は前回の記事と同様です。
- 管理アカウントに Distributor パッケージドキュメントを作成済み
- Distributor パッケージドキュメントをメンバーアカウントへ共有済み
- 管理アカウントに Automation ランブックを作成済み
- 管理アカウントに
AWS-SystemsManager-AutomationAdministrationRoleを作成済み - 対象アカウントに
AWS-SystemsManager-AutomationExecutionRoleを作成済み - 正常に配布する対象 EC2 は、Systems Manager のマネージドノードとして登録されている
- 対象 EC2 から Distributor パッケージ取得に必要な AWS 管理 S3 バケットへ到達可能
今回使用する Automation ランブックは、前回と同じものです。
description: Install shared Distributor package to one EC2 instance in target account
schemaVersion: '0.3'
assumeRole: '{{ AutomationAssumeRole }}'
parameters:
AutomationAssumeRole:
type: String
description: ARN of AWS-SystemsManager-AutomationAdministrationRole in management account
InstanceId:
type: String
description: Target EC2 instance ID in member account
PackageArn:
type: String
description: Shared Distributor package ARN
mainSteps:
- name: installPackage
action: aws:runCommand
isEnd: true
inputs:
DocumentName: AWS-ConfigureAWSPackage
InstanceIds:
- '{{ InstanceId }}'
Parameters:
installationType:
- Uninstall and reinstall
name:
- '{{ PackageArn }}'
action:
- Install
このランブックは、InstanceId を 1 つ受け取り、その EC2 インスタンスに対して AWS-ConfigureAWSPackage を実行する構成です。
今回のように複数インスタンスを対象にする場合でも、Automation 側のターゲット指定により、対象インスタンスごとに InstanceId が渡されます。
そのため、ランブック自体は前回のものをそのまま利用できます。
実行コマンド
以下が今回検証したコマンドです。
aws ssm start-automation-execution \
--document-name "CM-InstallDistributorPackage" \
--parameters '{
"AutomationAssumeRole": [
"arn:aws:iam::111111111111:role/AWS-SystemsManager-AutomationAdministrationRole"
],
"PackageArn": [
"arn:aws:ssm:ap-northeast-1:111111111111:document/test-1"
]
}' \
--target-parameter-name "InstanceId" \
--targets '[
{
"Key": "AWS::EC2::Instance",
"Values": ["*"]
}
]' \
--target-locations '[
{
"Accounts": ["r-xxxx"],
"IncludeChildOrganizationUnits": true,
"ExcludeAccounts": [
"ou-xxxx-xxxxxxxx",
"222222222222"
],
"Regions": ["ap-northeast-1"],
"ExecutionRoleName": "AWS-SystemsManager-AutomationExecutionRole",
"TargetLocationMaxConcurrency": "50",
"TargetLocationMaxErrors": "100%",
"TargetsMaxConcurrency": "5",
"TargetsMaxErrors": "100%"
}
]' \
--region ap-northeast-1
start-automation-execution の各パラメータについては、以下の AWS CLI リファレンスも参考になります。
コマンドのポイント
Accounts に Root ID を指定する
"Accounts": ["r-xxxx"]
Accounts には、アカウント ID だけでなく Organizations の Root ID や OU ID も指定できます。
今回は組織配下を広く対象にしたいため、Organizations の Root ID を指定しています。
特定のアカウントのみを対象にしたい場合は、以下のようにアカウント ID を直接指定できます。
"Accounts": [
"222222222222",
"333333333333"
]
また、特定のOU 配下のアカウントと特定のアカウントをあわせて対象にしたい場合は、OU ID とアカウント ID を混在して指定することもできます。
"Accounts": [
"ou-xxxx-xxxxxxxx",
"333333333333"
],
"IncludeChildOrganizationUnits": true
アカウント ID のみを指定する場合、配下の OU を展開する必要がないため、IncludeChildOrganizationUnits の指定は不要です。
OU ID や Root ID を指定し、子 OU 配下のアカウントも含めたい場合に IncludeChildOrganizationUnits を true にします。
IncludeChildOrganizationUnits を true にする
"IncludeChildOrganizationUnits": true
Root ID や OU ID を指定した場合、配下の子 OU まで含めて対象にするために IncludeChildOrganizationUnits を true にしています。
これにより、Root 配下の OU / 子 OU に所属するアカウントも対象に含められます。
ExcludeAccounts で一部 OU / アカウントを除外する
"ExcludeAccounts": [
"ou-xxxx-xxxxxxxx",
"222222222222"
]
ExcludeAccounts を使用すると、Root ID や OU ID によって展開された対象から、一部の OU またはアカウント ID を除外できます。
今回の検証では、ExcludeAccounts に OU ID とアカウント ID を混在して指定し、対象から除外して実行できることを確認しました。
ただし、ExcludeAccounts で除外できるのは OU またはアカウント ID 単位です。
同一アカウント内の一部 EC2 インスタンスのみを除外することはできません。
そのため、同一アカウント / 同一リージョン内で一部の EC2 インスタンスのみを対象外にしたい場合は、タグ指定やインスタンス ID 指定など、別の方法を検討する必要があります。
--targets で全 EC2 インスタンスを対象にする
--targets '[
{
"Key": "AWS::EC2::Instance",
"Values": ["*"]
}
]'
今回は、対象アカウント / 対象リージョン内の EC2 インスタンスを一括対象にするため、AWS::EC2::Instance と Values: ["*"] を指定しています。
前回のように ParameterValues でインスタンス ID を明示的に列挙する必要はありません。
--target-parameter-name でランブックの InstanceId に渡す
--target-parameter-name "InstanceId"
Automation ランブックでは、以下のように InstanceId パラメータを定義しています。
InstanceId:
type: String
description: Target EC2 instance ID in member account
--target-parameter-name "InstanceId" を指定することで、Automation によって解決された EC2 インスタンス ID が、ランブックの InstanceId パラメータに渡されます。
その結果、各 EC2 インスタンスに対して AWS-ConfigureAWSPackage が実行されます。
検証結果
今回の検証では、以下の観点を確認しました。
- Root 配下のアカウントを対象に実行できるか
ExcludeAccountsで一部 OU / アカウントを除外できるか- EC2 インスタンスが存在しないアカウントが対象に含まれた場合の挙動
- 停止中 EC2 または非マネージドインスタンスが対象に含まれた場合の挙動
Root 配下のアカウントを対象に実行できた
まず、Accounts に Root ID を指定し、IncludeChildOrganizationUnits を true にすることで、Root 配下のアカウントを対象に実行できることを確認しました。
今回の検証環境では、除外指定をしない場合、3 アカウントに対して Automation が実行されました。
親 Automation の実行結果を見ると、アカウントごとに実行されたステップが記録されていることが分かります。

この結果から、Root ID 指定により、配下の複数アカウントに対して Automation を展開できることを確認できました。
ExcludeAccounts で一部 OU / アカウントを除外できた
次に、ExcludeAccounts に除外対象の OU ID またはアカウント ID を指定し、対象から除外できるかを確認しました。
"ExcludeAccounts": [
"ou-xxxx-xxxxxxxx",
"222222222222"
]
除外指定をしない場合は 3 アカウントに対して実行されましたが、ExcludeAccounts を指定した場合は、実行対象が 2 アカウントになりました。

この結果から、ExcludeAccounts に OU ID またはアカウント ID を指定することで、Root 配下の対象から一部の OU / アカウントを除外して実行できることを確認できました。
EC2 インスタンスが存在しないアカウントはエラーにならなかった
次に、実行対象アカウントに EC2 インスタンスが存在しない場合の挙動を確認しました。
検証の結果、EC2 インスタンスが存在しないアカウントが実行対象に含まれていても、親 Automation と子 Automation のステータスはいずれも成功となりました。

子 Automation の詳細を見ると、対象となる EC2 インスタンスが存在しないため、実行されたステップはありませんでした。
この結果から、今回の指定方法では、実行対象アカウント内に EC2 インスタンスが存在しない場合でも、エラーにはならないことを確認できました。
停止中 EC2 または SSM 管理対象外の EC2 が含まれるとエラーになった
今回の検証では、停止中の EC2 インスタンスや、SSM 管理対象外の EC2 インスタンスが対象に含まれると、エラーになることを確認しました。
この場合、親 Automation と、対象アカウントの子 Automation の両方がエラーになりました。
子 Automation のステータスはタイムアウト済みとなっています。

エラー詳細は以下です。
Step timed out while step is verifying the SSM Agent availability on the target instance(s). SSM Agent on Instances: [i-09228b24d177f602c] are not functioning. Please refer to Automation Service Troubleshooting Guide for more diagnosis details.

エラーメッセージのとおり、Automation のステップ内で対象インスタンスの SSM Agent の利用可否を確認した際にタイムアウトしています。
まとめ
Organizations Root 配下のアカウントを対象にしつつ、ExcludeAccounts で一部の OU / アカウントを除外して、対象アカウント内の全 EC2 インスタンスへ Distributor パッケージを配布できました。
アカウントごとに EC2 インスタンス ID を列挙しなくてよいため、ほぼ全台へ展開したいケースでは便利です。
一方で、停止中 EC2 や SSM 管理対象外の EC2 が含まれると失敗するため、実行前に SSM 管理状態を確認しておくのがよさそうです。







