Systems Manager Distributor によるソフトウェア配布と一元管理

はじめに

こんにちは。kanazawaです。
AWSの運用業務において、複数サーバーに対してソフトウェアの配布や管理に活用できるサービスがSystems Manager Distributorです。
本記事では、Distributorの概要とソフトウェア配布の実践例をいくつかご紹介します。

1. Systems Manager Distributorとは

Systems Manager Distributorの概要

AWS Systems Manager Distributorは、EC2インスタンスやオンプレミスサーバーに対してソフトウェアパッケージを配布・管理するサービスです。
パッケージの配布、インストール、アンインストール、更新を自動化し、大規模な環境でも効率的にソフトウェア管理を行うことができます。

主な特徴:
- AWS公式パッケージの簡単配布
- カスタムパッケージの作成・配布
- バージョン管理と自動更新
- 配布状況の可視化とログ管理
- Systems Manager Run Commandとの連携

他の方法との使い分け

手動運用 vs Distributor

項目 手動運用 Distributor
作業時間 台数×作業時間 一括実行(数分)
設定統一 ミスが発生する可能性あり 完全に統一
夜間作業 必要 自動実行可能
作業証跡 手動記録 自動保存
スケール 限界あり 数百台でも対応可

Distributor vs Ansible

Distributorが有利なケース:
- AWS公式パッケージ(CloudWatch Agent等)の配布
- シンプルなソフトウェアインストール
- AWS環境のみの管理

Ansibleが有利なケース:
- 複雑な構成管理(設定ファイル、サービス連携等)
- マルチクラウド・オンプレミスが混在する環境
- 条件分岐や変数を多用する複雑な処理

2. AWS公式パッケージの活用

CloudWatch Agentの配布実践例

AWS公式パッケージの代表例として、CloudWatch Agentの配布手順を説明します。
前提として、以下の環境で行っています。
- 配布対象サーバーは2台
- OS:Amazon Linux 2023 - SSM Agentはデフォルトでインストール済み
- 配布対象サーバーのIAMロールにAmazonSSMManagedInstanceCoreを付与
- EC2インスタンスのタグを以下で設定
 - キー:Env
 - 値:test-distributor
- AWSコンソール画面で操作します。
- ※AWS CLIでも実行可能です。

手順
1. Systems Managerから、「ディストリビューター」を開きます。
2. 検索欄に「AmazonCloudWatchAgent」と入力し、「AmazonCloudWatchAgent」パッケージをクリックします。 3. パッケージのバージョンや説明を確認することができます。「バージョン」タブから、過去のバージョンも指定可能です。 4. 今回は「1回限りのインストール」を選択します。「スケジュールへのインストール」を選択すると、実行する時間を指定することが可能です。
5. ターゲットを指定して「実行」をクリックします。今回はタグから実行対象を判定させ、複数台のサーバーを対象とします。

結果の確認
実行後、以下の画面に進みます。 対象サーバーで、CloudWatch Agentがインストールされていることが確認できました。

# rpm -qa | grep amazon-cloudwatch-agent
amazon-cloudwatch-agent-1.300043.0-1.amzn2023.x86_64
# systemctl status amazon-cloudwatch-agent
○ amazon-cloudwatch-agent.service - Amazon CloudWatch Agent
     Loaded: loaded (/etc/systemd/system/amazon-cloudwatch-agent.service; disabled; preset: disabled)
     Active: inactive (dead)

3. メンテナンスウィンドウと組み合わせた自動更新設定

2章でインストールしたCloudWatch Agentを、Maintenance Windowsと組み合わせて定期的に自動更新する設定を行います。

手順
1. Systems Managerから、「メンテナンスウィンドウ」を開きます。
2. 「メンテナンスウィンドウの作成」をクリックします。
3. スケジュールをcron式で指定します。画像の例では、毎月1日の午前3時に設定しています。 4. メンテナンスウィンドウを作成後、「アクション」>「ターゲットの登録」をクリックします。
5. 2章と同様に、実行対象をタグで指定します。 6. 「タスク」タブから「タスクの登録」 > 「Run Command タスクの登録」をクリックします。
7. コマンドドキュメントでAWS-ConfigureAWSPackageを選択します。
8. 登録したターゲット、同時実行数、IAMロールをそれぞれ選択・入力します。
9. 「Run Command タスクの登録」をクリックして設定完了です。

結果の確認
メンテナンスウィンドウの「履歴」から結果を確認できます。
エラーが発生したので「詳細の表示」から確認してみます。 エラーメッセージは以下が表示されました。

Unable to assume the provided role.

IAMロールに権限が足りていなかったようです。
AmazonSSMMaintenanceWindowRoleを追加して再度実行すると成功しました。

4. カスタムパッケージの作成

4-1. カスタムパッケージの概要

Distributorでは、AWS公式パッケージ以外に独自のファイルやスクリプトも配布できます。
- Distributor でパッケージを作成する

基本的な仕組みと要件

  • S3バケットにファイルを置く
  • Systems Managerドキュメントで配布手順を定義
  • Run Commandで実行
  • オペレーティングシステムプラットフォームごとに最低1つのファイルが必要
  • 1つのドキュメントに最大20ファイルまで添付可能
  • 各ファイルの最大サイズは1GB
  • パッケージ作成時に新しいSSMドキュメントが自動生成される

シンプルワークフローと高度なワークフロー

シンプルワークフロー
- 対象ファイル: .rpm、.msi、.deb形式のインストール可能ファイル
- 自動生成: インストール/アンインストールスクリプト、ファイルハッシュ、JSONマニフェストを自動作成
- ファイル圧縮: 不要(Distributorが自動処理)
- 適用場面: 単純なソフトウェア配布

高度なワークフロー
- 対象ファイル: 事前に.zip形式で圧縮したファイル
- 手動作成: インストール/アンインストールスクリプト、JSONマニフェストを手動作成
- ファイル圧縮: 必要(事前に.zipファイルとして準備)
- 適用場面: 複雑な設定や複数プラットフォーム対応

今回は、シンプルワークフローを利用した例を紹介したいと思います。

4-2. Zabbix Agentの配布

監視エージェントであるZabbix Agentを配布する例です。
今回はrpmbuildを使用してカスタムRPMパッケージを作成し、それをDistributorで配布します。
Zabbix Agentのインストールだけでなく、自動起動設定とサービスの起動までを実施します。

1. RPMパッケージの作成

Zabbix AgentをインストールするRPMパッケージを作成します。
RPMパッケージの作成方法についての詳細は割愛します。
ディレクトリの構造は下記の通りです。

# tree ~/rpmbuild/
/root/rpmbuild/
├── BUILD
├── RPMS
├── SOURCES
│   └── install-zabbix.sh
├── SPECS
│   └── zabbix-agent-custom.spec
└── SRPMS

5 directories, 2 files

作業環境の準備

yum install -y rpm-build rpmdevtools
rpmdev-setuptree

SPECファイルの作成
ファイル名:~/rpmbuild/SPECS/zabbix-agent-custom.spec

# パッケージの基本情報
Name:           zabbix-agent-custom
Version:        1.0.0
Release:        1%{?dist}
Summary:        Custom Zabbix Agent installer

# ソースファイルの指定
Source0:        install-zabbix.sh

# 依存関係とアーキテクチャ
Requires:       bash
BuildArch:      noarch

# パッケージの説明
%description
Custom Zabbix Agent installer package for AWS Distributor

# インストール処理
%install
# スクリプト配置用ディレクトリの作成
mkdir -p %{buildroot}/usr/local/bin
# スクリプトファイルのインストール
install -m 755 %{SOURCE0} %{buildroot}/usr/local/bin/install-zabbix.sh

# パッケージに含まれるファイル一覧
%files
/usr/local/bin/install-zabbix.sh

# パッケージインストール後に実行される処理
%post
/usr/local/bin/install-zabbix.sh

インストールスクリプトの作成
ファイル名:~/rpmbuild/SOURCES/install-zabbix.sh

#!/bin/bash
# Zabbix Agentインストールスクリプト

echo "Zabbix Agentをインストールします"

# Zabbixリポジトリの追加
rpm -Uvh https://repo.zabbix.com/zabbix/6.0/rhel/9/x86_64/zabbix-release-6.0-4.el9.noarch.rpm

# Zabbix Agentのインストール
yum install -y zabbix-agent

# サービスの有効化と開始
systemctl enable zabbix-agent
systemctl start zabbix-agent

echo "Zabbix Agentのインストールが完了しました"

RPMパッケージのビルドとアップロード

# パッケージのビルド
rpmbuild -ba ~/rpmbuild/SPECS/zabbix-agent-custom.spec

# 作成されたRPMファイルの確認
ls ~/rpmbuild/RPMS/noarch/

# S3へのアップロード
# RPMファイルをS3にアップロード
aws s3 cp <パッケージのフルパス> <保存するS3バケットのURL>

2. Distributorでパッケージ作成

  1. AWSコンソールからディストリビューターを開き、「パッケージの作成」をクリックします。
  2. シンプルワークフローにあたる「簡単」を選択し、パッケージ名を入力します。
  3. ディストリビューターの保存先と、ダウンロードしたRPMパッケージの選択をします。
  4. 「パッケージの作成」をクリックすると以下の画面に移るため、作成が完了したことを確認します。

3. 実行結果の確認

2章と同様に1回限りのインストールで、実行対象はタグで指定します。
実行に成功したことが確認できました。 実際にサーバーでZabbix Agentの起動状態を確認し、想定通りであることも確認できました。

# systemctl status zabbix-agent
● zabbix-agent.service - Zabbix Agent
     Loaded: loaded (/usr/lib/systemd/system/zabbix-agent.service; enabled; preset: disabled)
     Active: active (running) since Tue 2026-04-21 13:55:35 UTC; 1min 22s ago

4-3. システム設定パッケージの配布

システム設定用のスクリプトを配布する例です。

新しいサーバーを構築する際、タイムゾーン設定、基本パッケージのインストール、ファイアウォールの設定など、毎回同じ作業を繰り返すことがあります。
これらの作業をシェルスクリプトとしてまとめ、Distributorで配布することで、複数のサーバーに一括で初期設定を適用できます。
今回はシンプルなシステム設定スクリプトを作成して配布します。

1. RPMパッケージの作成

システム初期設定用のRPMパッケージを作成します。

SPECファイルの作成
ファイル名:~/rpmbuild/SPECS/system-setup.spec

# パッケージの基本情報
Name:           system-setup
Version:        1.0.0
Release:        1%{?dist}
Summary:        System initial setup script
License:        MIT

# ソースファイルの指定
Source0:        system-setup.sh

# 依存関係とアーキテクチャ
Requires:       bash
BuildArch:      noarch

# パッケージの説明
%description
System initial setup script for AWS Distributor

# インストール処理
%install
# スクリプト配置用ディレクトリの作成
mkdir -p %{buildroot}/usr/local/bin
# スクリプトファイルのインストール
install -m 755 %{SOURCE0} %{buildroot}/usr/local/bin/system-setup.sh

# パッケージに含まれるファイル一覧
%files
/usr/local/bin/system-setup.sh

# パッケージインストール後に実行される処理
%post
/usr/local/bin/system-setup.sh

システム設定スクリプトの作成
ファイル名:~/rpmbuild/SOURCES/system-setup.sh

#!/bin/bash
# 基本的なシステム設定

echo "システム設定を開始します"

# タイムゾーン設定
timedatectl set-timezone Asia/Tokyo

# 基本パッケージのインストール
if command -v dnf &> /dev/null; then
    dnf update -y
    dnf install -y vim wget curl
elif command -v yum &> /dev/null; then
    yum update -y
    yum install -y vim wget curl
fi

echo "設定完了"

RPMパッケージのビルドとアップロード

# パッケージのビルド
rpmbuild -ba ~/rpmbuild/SPECS/system-setup.spec

# 作成されたRPMファイルの確認
ls ~/rpmbuild/RPMS/noarch/

# S3へのアップロード
aws s3 cp <パッケージのフルパス> <保存するS3バケットのURL>

2. Distributorでパッケージ作成

  1. AWSコンソールからディストリビューターを開き、「パッケージの作成」をクリックします。
  2. シンプルワークフローにあたる「簡単」を選択し、パッケージ名を入力します。
  3. ディストリビューターの保存先と、ダウンロードしたRPMパッケージの選択をします。
  4. 「パッケージの作成」をクリックすると作成が完了します。

3. 実行結果の確認

2章と同様に1回限りのインストールで、実行対象はタグで指定します。
実行に成功したことが確認できました。
Outputを見ると、パッケージのインストールに成功しています。 実行対象のサーバーで、想定通りにインストール・設定されたことも確認できました。

# timedatectl
               Local time: Wed 2026-04-22 12:21:38 JST
           Universal time: Wed 2026-04-22 03:21:38 UTC
                 RTC time: Wed 2026-04-22 03:21:38
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
# rpm -qa | grep -E "vim|wget|curl"
vim-data-9.1.1591-1.amzn2023.0.1.noarch
vim-minimal-9.1.1591-1.amzn2023.0.1.x86_64
vim-filesystem-9.1.1591-1.amzn2023.0.1.noarch
vim-common-9.1.1591-1.amzn2023.0.1.x86_64
libcurl-minimal-8.11.1-4.amzn2023.0.1.x86_64
vim-enhanced-9.1.1591-1.amzn2023.0.1.x86_64
wget-1.21.3-1.amzn2023.0.4.x86_64
curl-minimal-8.11.1-4.amzn2023.0.1.x86_64

4-4. 補足

  • 実際の運用ではエラーハンドリングやロールバックの処理も追加すべきでしょう。
  • 機密情報はスクリプトに記載せず、Parameter Storeとの連携を検討すると適切かと思います。
  • 今回の例は非常にシンプルで小規模ですが、高度なワークフローを利用して複雑な要件に対応するケースもあると思います。以下は高度なワークフローを作成する場合のパッケージ構造の例です。
my-advanced-package/
├── MANIFEST.json
├── install.sh              # Linux用インストールスクリプト
├── install.ps1             # Windows用インストールスクリプト
├── uninstall.sh            # Linux用アンインストールスクリプト
├── uninstall.ps1           # Windows用アンインストールスクリプト
└── files/
    ├── config-linux.conf   # Linux用設定ファイル
    ├── config-windows.ini  # Windows用設定ファイル
    └── application.zip     # アプリケーション本体
  • パッケージの実行は、以下のようにAWS CLIでも可能です。AWSコンソール画面での操作を減らすことで、運用コストはさらに下げられます。
aws ssm send-command --document-name "AWS-ConfigureAWSPackage" --document-version "1" --parameters '{"action":["Install"],"installationType":["Uninstall and reinstall"],"name":["System-Setup-Package"],"version":[""],"additionalArguments":["{}"]}' --timeout-seconds 600 --max-concurrency "50" --max-errors "0" --region ap-northeast-1

まとめ

Distributorを活用することで、大規模環境でも効率的で一貫性のあるソフトウェア配布が実現できます。
個人的に、AWS公式ドキュメントを読んで仕様を把握することは難しく、実際に触ってみることでイメージしやすくなると感じました。
まずはシンプルワークフローで簡易的なパッケージを作成し、段階的にエラーハンドリングなどの処理を追加していく方針がよいかと思います。
Automationドキュメントと同様にバージョン管理も可能なため、継続的な改善とロールバックが容易に行えます。
ぜひ活用してみてください。