SSM Agentの実行スクリプトを削除する方法

# はじめに
前回「[Amazon S3からのスクリプトの実行をやってみた。](https://qiita.com/sakai00kou/items/326a36fbdea10a6b2da8)」という記事で`Systems Manager`の`Run Command`機能を使用して、コマンド実行を試してみましたが、その際に、実行対象のインスタンスに残り続けるスクリプトが気になったので、調べた結果をまとめておきます。

- 【前】[Amazon S3からのスクリプトの実行をやってみた。](https://qiita.com/sakai00kou/items/326a36fbdea10a6b2da8)

# SSM Agentの実行スクリプト格納先
前回説明した`Run Command`だけではなく、`Systems Manager`関連でリモートマシン操作が伴う場合、実行対象インスタンスの以下ディレクトリ配下に実行ステータスや実行スクリプトが格納されるようです。

```bash:/var/lib/amazon/ssm配下のファイル・ディレクトリ構成
/var/lib/amazon/ssm
├── daemons
├── i-0cbfefff950933df4
│   ├── channels
│   ├── document
│   │   ├── orchestration
│   │   │   └── 0f4f1fe2-fef8-41ca-a726-c1507dfe2262　　★コマンド実行したときに毎回作られるディレクトリ
│   │   │       ├── awsdownloadContent
│   │   │       │   └── downloadContent
│   │   │       │       ├── stderr
│   │   │       │       ├── stderrConsole
│   │   │       │       ├── stdout
│   │   │       │       └── stdoutConsole
│   │   │       ├── awsrunShellScript
│   │   │       │   └── runShellScript
│   │   │       │       ├── stderr
│   │   │       │       ├── stderrConsole
│   │   │       │       ├── stdout
│   │   │       │       └── stdoutConsole
│   │   │       ├── downloads
│   │   │       │   ├── 546b91d3f020855852cdf17aa5074800e7b3be82.etag
│   │   │       │   └── test.sh
│   │   │       └── runShellScript
│   │   │           └── _script.sh
│   │   └── state
│   │       ├── completed
│   │       ├── corrupt
│   │       ├── current
│   │       └── pending
│   ├── idempotency
│   │   └── SendCommand
│   │       ├── 584efcee-cbe1-4221-8bc1-d3708900a4ac
│   │       ├── 8d23ed95-1492-4979-9f70-5eb0f9aa8bda
│   │       └── f3d54e23-c835-44e1-8bd3-fd62d255f695
│   ├── inventory
│   │   ├── custom
│   │   ├── file
│   │   └── role
│   ├── longrunningplugins
│   │   ├── datastore
│   │   └── healthcheck
│   ├── replies
│   └── replies_mgs
├── ipc
│   ├── health
│   └── termination
├── localcommands
│   └── completed
└── runtimeconfig
    └── identity_config.json
```

上記のツリーで★で示したディレクトリはコマンド実行するごとに毎回別のUUIDのディレクトリが生成され、ダウンロードしたファイルや実行したときのスクリプトが格納されます。

これは、例えば`Run Command`の「**コマンド履歴**」から過去に実行したコマンドを再実行した場合でも、新たにUUIDを生成＆実行スクリプト等ダウンロードが行われるため、実行回数が多ければ多いほど、数が増えていく仕様となります。

また、`orchestration`配下のファイル・ディレクトリはデフォルトだとそのまま残り続けるようなので、ファイルサイズが大きかったり、ファイル数が多かったりするとそれだけディスクを圧迫したり、`i-node`枯渇の問題が発生する可能性があります。
※調べてみると、実際にディスクフルになったり`i-node`枯渇が発生した人もいるようです。

# SSM Agentの実行スクリプトを削除する設定
`orchestration`配下のディレクトリは消してしまっても問題ないようなので、過去のワークアラウンドとしては`cron`に以下のような処理を追加して、一定期間経ったら削除する処理を加えている人もいたようです。

```bash:過去３日以前のファイル・ディレクトリを削除
0 0 * * * find /var/lib/amazon/ssm/i-*/document/orchestration -mindepth 2 -maxdepth 2 -type d -mtime +3 -print0 | xargs -0 rm -rf
```

ただ、以下`SSM Agent`の`GitHub`ページの`README`を見ると、`amazon-ssm-agent.json`ファイルを編集することでスクリプト実行後に削除させることもできるようなので、やってみようと思います。

- [aws/amazon-ssm-agent (GitHub)](https://github.com/aws/amazon-ssm-agent)

## SSM Agentの設定ファイル格納先
`SSM Agent`の設定ファイル格納先は「**/etc/amazon/ssm**」となり、以下のようなファイル構成となります。

`SSM Agent`の設定は`amazon-ssm-agent.json.template`のファイル名を変更して、ファイル編集、再起動することで有効になります。

|ファイル名|内容|
|:--|:--|
|amazon-ssm-agent.json.template|SSM Agentの設定テンプレート|
|NOTICE.md|ライセンス情報など|
|README.md|GitHubのREADMEと同等のREADMEファイル|
|RELEASENOTES.md|リリースノート|
|seelog.xml.template|ログ設定テンプレート|

また、`SSM Agent`関連のログは「**/var/log/amazon/ssm**」配下に出力されますが、ログのローテーション設定等は`seelog.xml`を編集することで変更することも可能です。

今回は説明しませんが、ログローテーションの設定を変更したい場合は、`seelog.xml.template`を`seelog.xml`にリネームして設定してみてください。

- [SSM Agent ログの表示](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/sysman-agent-logs.html)

## amazon-ssm-agent.jsonの編集
テンプレートファイルをコピーして`amazon-ssm-agent.json`ファイルを作成します。

```bash:amazon-ssm-agent.jsonファイル作成
sudo su -
cd /etc/amazon/ssm/
cp amazon-ssm-agent.json.template amazon-ssm-agent.json
```

ファイルを`vi`等で開き、`orchestration`関連の設定を変更します。

`orchestration`関連の設定項目は`OrchestrationDirectoryCleanup`が該当し、デフォルトでは削除されない設定となっております。

`OrchestrationDirectoryCleanup`は以下の設定値を設定することが可能です。

|設定値|説明|
|:--|:--|
|(設定無し)|実行後にオーケストレーションフォルダーを削除しない（デフォルト）|
|clean-success|ドキュメントの実行が成功した場合にのみ、オーケストレーションフォルダーを削除する。|
|clean-success-failed|成功および失敗したドキュメント実行のオーケストレーションフォルダーを削除する。|

実行に失敗した場合に原因調査のため、ディレクトリを残しておきたい場合は`clean-success`、成功・失敗に関わらず、実行後にディレクトリを消してしまいたい場合は`clean-succecc-failed`を設定します。

ちなみに執筆時点の`SSM Agent`バージョンとなる「**3.1.1575.0**」の`amazon-ssm-agent.json.template`デフォルト設定は以下となります。

<details><summary>amazon-ssm-agent.json.templateのデフォルト設定（展開してください）</summary>

```bash:/etc/amazon/ssm/amazon-ssm-agent.json.template
{
    "Profile":{
        "ShareCreds" : true,
        "ShareProfile" : "",
        "ForceUpdateCreds" : false,
        "KeyAutoRotateDays": 0
    },
    "Mds": {
        "CommandWorkersLimit" : 5,
        "StopTimeoutMillis" : 20000,
        "Endpoint": "",
        "CommandRetryLimit": 15
    },
    "Ssm": {
        "Endpoint": "",
        "HealthFrequencyMinutes": 5,
        "CustomInventoryDefaultLocation" : "",
        "AssociationLogsRetentionDurationHours" : 24,
        "RunCommandLogsRetentionDurationHours" : 336,
        "SessionLogsRetentionDurationHours" : 336,
        "PluginLocalOutputCleanup": "",
        "OrchestrationDirectoryCleanup": ""
    },
    "Mgs": {
        "Region": "",
        "Endpoint": "",
        "StopTimeoutMillis" : 20000,
        "SessionWorkersLimit" : 1000,
        "DeniedPortForwardingRemoteIPs" : [
            "169.254.169.254",
            "fd00:ec2::254",
            "169.254.169.253",
            "fd00:ec2::253",
            "169.254.169.123",
            "169.254.169.250"
        ]
    },
    "Agent": {
        "Region": "",
        "OrchestrationRootDir": "",
        "SelfUpdate": false,
        "TelemetryMetricsToCloudWatch": false,
        "TelemetryMetricsToSSM": true,
        "AuditExpirationDay" : 7,
        "LongRunningWorkerMonitorIntervalSeconds": 60
    },
    "Os": {
        "Lang": "en-US",
        "Name": "",
        "Version": "1"
    },
    "S3": {
        "Endpoint": "",
        "Region": "",
        "LogBucket":"",
        "LogKey":""
    },
    "Kms": {
        "Endpoint": ""
    }
}
```
</details>

今回は`clean-success-failed`を設定して動作確認してみます。

```bash:OrchestrationDirectoryCleanup設定の変更（sedで設定した場合）
sed -i -e "/OrchestrationDirectoryCleanup/s/:.*$/: \"clean-success-failed\"/g" /etc/amazon/ssm/amazon-ssm-agent.json
```

設定したらサービスを再起動して有効化します。

```bash:SSM_Agentの再起動
systemctl restart amazon-ssm-agent
```

## 動作確認
設定を変更したので、動作確認を行います。

`clean-success-failed`の設定を行った場合の動作としては、スクリプト実行中は`orchestration`配下にファイル・ディレクトリが作成され、実行完了したら削除される動作となります。

動作確認を行うため、[前回](https://qiita.com/sakai00kou/items/326a36fbdea10a6b2da8)使ったスクリプトを以下のように修正して`Run Command`を実行、その際に対象のEC2インスタンスの`orchestration`ディレクトリ配下の状況を確認してみます。

```bash:RunCommandで実行するtest.sh
#!/bin/bash
echo "Hello World"
uname -n
sleep 5
pwd
```

```bash:対象EC2インスタンス上で実行する確認用コマンド
while true; do ls -ltr /var/lib/amazon/ssm/[インスタンスID]/document/orchestration; sleep 1; done
```

以下`Run Command`実行時の`orchestration`ディレクトリ状態。

```bash:RunCommand実行前
total 0
drwx------ 6 root root 96 Aug 28 02:50 584efcee-cbe1-4221-8bc1-d3708900a4ac
drwx------ 6 root root 96 Aug 28 02:50 8d23ed95-1492-4979-9f70-5eb0f9aa8bda
```

```bash:RunCommand実行中
total 0
drwx------ 6 root root 96 Aug 28 02:50 584efcee-cbe1-4221-8bc1-d3708900a4ac
drwx------ 6 root root 96 Aug 28 02:50 8d23ed95-1492-4979-9f70-5eb0f9aa8bda
drwx------ 6 root root 96 Aug 28 05:59 dfa66ed2-1bce-4ab0-8aab-8f6c88324fc2　　★ディレクトリが作成された
```

```bash:RunCommand実行完了後
total 0
drwx------ 6 root root 96 Aug 28 02:50 584efcee-cbe1-4221-8bc1-d3708900a4ac
drwx------ 6 root root 96 Aug 28 02:50 8d23ed95-1492-4979-9f70-5eb0f9aa8bda
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　★ディレクトリが削除された
```

想定通り、実行中だけファイル・ディレクトリが作成されて、実行完了後、ディレクトリが削除されることが確認できました。

尚、`orchestration`ディレクトリ配下を削除する設定に変更した場合でも、設定以前に作られたディレクトリは残り続けるため、過去のディレクトリは手動削除するようにしてください。

# おわりに
`SSM Agent`のログについてはデフォルトでローテーションされるような設定となっておりますが、実行スクリプトはデフォルトではそのまま残ってしまうため、通常運用で`SSM Agent`の`Run Command`等を多く使う場合は上記の設定を入れておいたほうが良いと感じました。