AWS Systems Managerが思ってたより怖くなくて、便利だった。～複数のEC2インスタンスをログ監視できるようにしてみた～

# はじめに
豊富な機能を持つことから、Systems Manager（以下、SSM）への苦手意識があったのですが、
先日、builders-flashで以下の記事を読み、少し見え方が変わりました。

https://aws.amazon.com/jp/builders-flash/202405/systems-manager-series/

読むと分かるのですが、SSMは結構便利そうで、楽しそうです！

今回はSSMの触りとして、
CloudWatchエージェントのインストールと設定を、**複数のEC2を対象に一括で**実行してみようと思います！！

# やってみた
## EC2を用意する
### SSMで操作するための要件を確認する
まずはEC2を用意します。

EC2インスタンスをSSMで操作するためには、以下を満たす必要があります。
① SSMエージェントがインストールされている
② SSMやCloudwatchを操作するポリシーがEC2にアタッチされている
③ EC2から外部インターネットにアウトバウンドが可能である

また、これらの条件を満たし、SSMが操作可能なインスタンスを**マネージドインスタンス**と呼びます。

参考）

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-prerequisites.html

### AMIの選定
いくつかのAMIでは、デフォルトでSSMエージェントがインストールしています。

参考）

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/ami-preinstalled-agent.html

今回はAmazonLinuxとUbuntuのAMIを使用してみます。

![cap01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/6128f8e0-357d-2165-3ae5-b1a2c0f7530b.png)

![cap02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/10e69e96-f2fa-89ad-53a4-707b1502249e.png)

### IAMポリシーの選定
必要なIAMポリシーですが、AWSマネージドのものが存在するので、それを利用します。

SSMエージェント用と、CloudWatchエージェント用の2つのポリシーをアタッチしています。

![cap03.5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/0d0b4482-d00e-7602-c8f4-f41fbbecc0ea.png)

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started-instance-profile.html

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/create-iam-roles-for-cloudwatch-agent.html

### SSMで操作できるか確認

上述した設定で、EC2が作成できました！

SSMにはフリートマネージャーという機能があり、マネージドインスタンスの一覧が簡単にできます。

![cap03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/c0e340a0-fa87-8471-057c-09c3c4ed078b.png)

マネージドインスタンスとして表示されており、
SSMエージェントのインストールやポリシーなどに問題がなさそうなことが確認できました！

## CloudWatch エージェントをインストールする
それでは、2つのマネージドインスタンスを一括操作していきます！
まずはエージェントのインストールからです。

### SSM Run Commandを準備する
SSMでは、複数のマネージドインスタンスに一括で同じコマンドを実行するRunCommandという機能が存在します。
（OSが異なっていても一括で命令できるため、実際には宣言型の命令が可能なイメージ）

![cap04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/07e25916-ce83-6397-dd4b-17e67d16d9dd.png)


Run Commandをクリックします

### 目的のドキュメントを検索する
SSMでは、インスタンスへの命令は「ドキュメント」という単位で管理されています。
今回は、「AWS-ConfigureAWSPackage」というドキュメントを実行させます。

参考）

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-on-EC2-Instance-fleet.html#download-CloudWatch-Agent-on-EC2-Instance-SSM-fleet

![cap05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/cee0e3cc-2a84-2918-6b73-0d36ff1075f7.png)

検索ボックスに「configure」を入力してフィルタしていきます

![cap07.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/e125996e-0949-393d-dcd6-4a589ca9111e.png)

ドキュメントを選択すると、ドキュメントの説明が表示されます

> ディストリビューターパッケージをインストールまたはアンインストールします。最新バージョン、デフォルトバージョン、または指定したパッケージのバージョンをインストールできます。AmazonCloudWatchAgent、AwsEnaNetworkDriver、AWSPVDriverなどのAWSが提供するパッケージもサポートされています。

よさそうですね！

### Run Commandのオプションを設定する
Run Commandにはオプションを設定できます
ドキュメントによって、特定のインプット情報が必要だったり、
ドキュメントを問わず、結果をS3にアップロードしたりなど、です

![cap08.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/13d2d3a5-01d9-a6ab-cd12-438090dcf053.png)

installするパッケージ名に「AmazonCloudWatchAgent」を入力します
そのほかの設定はデフォルトのままで問題なさそうなので、次のオプションに進みます。

![cap09.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/ea9c21f8-d222-3901-b4ce-ddaf85463828.png)

RunCommandの対象となるマネージドインスタンスを指定します。

![cap09.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/6db52e40-dda5-4e23-4b85-85fdf815c082.png)


今回は手で設定しましたが、タグやリソースグループ単位で指定できるのはかなり便利そうですね！！

その他のパラメータも埋めていきます。

![cap10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/61348c99-9581-cdb7-a44d-434b767ed91d.png)


S3へのアップロードがデフォルトで有効化されていましたが、不要に感じたので無効にしました。

![cap11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/d380a97a-6e5f-0b6f-424a-68c820fb1054.png)

その他の設定もデフォルトで無効になっており、問題はなさそうだったので、実行してみます！

### Run Commandの実行結果を確認する

![cap12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/222557d8-b186-dc76-0596-4ebf2499aeab.png)

実行をクリックすると、RunCommandが正常に開始されました！

![cap13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/e430f656-678c-caf7-5ebf-4ce9caf71c23.png)

10秒ほど待つと、どちらのインスタンスもRunCommandが成功していることが確認できました

インスタンスIdが結果詳細画面へのリンクになっているので、クリックしてみます

![cap14.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/88e8135a-aae0-c37d-5a41-2e373b473987.png)

フェーズごとに細かくログが確認できそうです！

ステップ2を確認してみます

![cap15.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/5b602d25-45bf-3de6-e07b-08e9abcdf8b1.png)

アウトプットタブを開くと、無事CloudWatchエージェントがインストールできてそうです

他方のインスタンスも確認してみます

![cap16.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/5d4b7ac0-3af7-02ca-00c0-538405465b80.png)

簡単！！凄い！！

### CloudWatch エージェントの設定を確認する
RunCommandが成功しているのが確認できたので、インスタンスに接続し、設定状況を確認します。

参考）

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/troubleshooting-CloudWatch-Agent.html#CloudWatch-Agent-troubleshooting-verify-running

>Linux サーバーで、次のように入力します。
```sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a status```

![cap17.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/d825408c-035a-e51a-e626-7aa0f7aef560.png)

![cap18.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/b92344e4-c746-c96c-674d-6f53281c4d06.png)


インストールしただけで、まだ設定・起動は行っていないので、```stopped```で```not configured ```状態なのが確認できました
良い感じですね！

## CloudWatch エージェントのログ配信設定を行う
同じくRunCommand機能を使ってCloudWatch エージェントのログ配信設定を行ってみます

参考）

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-on-EC2-Instance-fleet.html#start-CloudWatch-Agent-EC2-fleet

### CloudWatchエージェントの配信設定jsonを用意する
CloudWatchエージェントの配信設定は、jsonで定義されています
この定義用jsonを保存、使いまわすことで、複数のインスタンスに同じ設定でログなどを出力させることができます。凄い！

今回は以下のようなjsonを用意しました
```config.json
{
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "file_path": "/var/log/apache2/access.log",
            "log_group_name": "/ec2/agent",
            "log_stream_name": "{instance_id}-access"
          },
          {
            "file_path": "/var/log/apache2/error.log",
            "log_group_name": "/ec2/agent",
            "log_stream_name": "{instance_id}-error"
          }
        ]
      }
    },
   "log_stream_name": "{instance_id}-default"
  }
}
```

/var/log/apache2/access.logに記載されるログを、「/ec2/agent」というロググループの、「{instance_id}-access」ログストリームに転送します

参考）

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html

### SSMパラメータストアでパラメータを作成する
設定jsonを複数のインスタンスでシェアできるように、SSMパラメータストアに保存します！

![cap19.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/9966e8f7-6ea0-ee94-9e70-c92beb66b7ab.png)

「パラメータの作成」をクリックします
（この文脈で触ると、secretを保存する機能ではまったくない感じがしますね・・・）

![cap20.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/4c3468e3-b107-626a-ccab-621f3150c80c.png)

パラメータ名を入力します。他の値はデフォルトでよさそうです

![cap21.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/d8baaaab-ad05-b682-d651-54bc409263a5.png)

jsonの値を入力します
作成ボタンをクリックします

![cap22.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/9cd05dd1-e896-0cd8-e3ba-0f4ea1a4ae2f.png)

パラメータが作成されました！
ではこのパラメータを使用し、再度RunCommandしていきます！

### SSMドキュメントから実行するドキュメントを指定する
先ほどはRunCommand画面からドキュメントを指定しましたが、ドキュメントの一覧からRunCommand画面を呼び出すことも可能です

![cap23.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/54719c77-83a8-a974-d0a5-7f08d80a9044.png)

ドキュメントが一覧できます
今回は使用しませんが、StepFunction のような、Automationというドキュメントもあるそうです。楽しそう

![cap24.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/07a4d711-0b85-d4be-68bb-52a218a3325b.png)

「ManageAgent」でfilterし、目的のドキュメントをクリックします。

![cap24.5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/432bc25b-36db-398c-3d0c-5a209edb50cd.png)

ドキュメントの説明や、コンテンツタブで動作の内容などが確認できます
「コマンドを実行する」をクリックします

![cap25.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/79dc288e-4aad-d7d2-0711-be4872f027c5.png)

RunCommandの画面に遷移しました。先ほどと違い、遷移元のドキュメントがすでに選択されています

### Run Commandを実行する
実行のため、オプションを入力していきます

![cap26.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/4d76b677-3d58-4c2a-cafc-91122d48e69e.png)

パラメータストア経由でコマンドの詳細を引き渡します
optionalConfigurationLocationに、先ほど作成したパラメータの名前を入力します

![cap27.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/fdc34a38-452c-e302-bec3-46f1ce6367a6.png)

ターゲットを先ほど同様に指定します。

![cap28.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/dd3e937b-5874-694a-3914-a49790939bf3.png)

S3アップロードを無効化し、その他はデフォルトのまま、コマンドを実行します！!

![cap29.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/0ce988d4-ea9e-39c3-62c4-c7fbc44c66ba.png)

ステータスが成功になりました！

<details><summary>プチ疑問</summary>

ステータス上は成功と表示されるのですが、実行結果詳細画面では以下のように表示されます。


![cap30.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/07b0b4e7-c804-928c-38fa-ab9bb0e51c31.png)

OutPutに```amazon-cloudwatch-agent has already been stopped```と表示されたり、
Errorに数行のログが出ていたり、少し不安です

問題ない旨を言及する記事がいくつかあったり、
動作には問題なく、実際のエージェントの起動にも成功しているのですが、少し気持ち悪いですね

</details>

### Run Command実行結果を確認する
先ほど同様、インスタンスに接続し、CloudWatchエージェントのステータスを確認します

![cap31.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/01085910-31cf-ab8c-a572-310c18cda82b.png)

![cap32.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/ed497d78-8636-e28c-92c4-1c1d91e22745.png)

どちらも問題なく動いてそうです！！

### ログ配信を確認する
インスタンスにapacheをインストールして動作を確認してみます

![cap33.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/88c6ca9e-381c-68cc-78a3-b4392d587b36.png)

ログが転送されていることが確認できました！！

これでCloudWatchエージェントのインストールと設定を、**複数のEC2を対象に一括で**実行できました、楽で簡単でした！！

<details><summary>プチやらかし</summary>

ひとえにapacheサーバーと言っても、ディストリビューションによって使うパッケージやインストールするぷろっグラムが違うことを初めてしりました。

今回の設定だと、apache2をインストールするubuntuインスタンスはアクセスログがCloudWatchに配信されますが、
httpdをインストールするAmazonLinuxインスタンスはアクセスログの場所が異なるため、別途設定を行う必要があります

今回は動作確認のため、メチャクチャ汚くテストしました・・・

![cap34.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/e432c635-47c1-b999-a6f2-b355d471d98e.png)

</details>


# おわりに
実際に触ってみることで、SSMへの恐怖感が少し紛れました
SSMを忌避していた理由の一つに、機能の多さ・機能の一貫性のなさ（個人的感想）があるのですが、
少しずつ慣れていければな、と思います。