AWS EventBridgeでEC2インスタンスの起動を検知し、LambdaとSSMを連携して自動化する方法

## はじめに
AWS Systems Manager (SSM) の Run Command は、AWS環境内のEC2インスタンスなどをリモート操作できる強力なツールです。

この記事では、EventBridgeを使用してEC2インスタンスの起動を検知し、Lambda関数をトリガーとしてSSMコマンドを実行し、指定のインスタンスにメッセージを出力する自動化の流れを解説します。

Run Commandの基本的な使い方については、前回の記事でも詳しく説明していますので、興味がある方はぜひご覧ください。

https://qiita.com/free-honda/items/f2a2e922a826c2b45a18

## 前提条件

この手順では、AWSの各種サービスを活用して、インスタンスの起動を動的に検知し、コマンド実行まで自動化するフローを構築します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/391af16a-d1b1-42ac-784e-d1354399b538.png)

:::note info
**IAM Roleの設定:**
EC2インスタンスには「AmazonSSMManagedInstanceCore」ポリシーがアタッチされたIAMロールが必要です。
Lambda関数には「AmazonSSMFullAccess」ポリシーがアタッチされたIAMロールが必要です。

**SSMエージェントのインストール:**
最新のAmazon LinuxやWindows ServerにはSSMエージェントがプリインストールされていますが、インストールされていない場合は手動でのインストールが必要です。

**AWS CLIのセットアップ:**
コマンドを実行するマシンにAWS CLIがインストールされ、適切に設定されていることを確認してください。
:::

IAMロールの権限が不足していると処理が正しく動作しないことが多いので、**実装時にはロールに必要なポリシーが付与されていること**を必ず確認してください。

## 構成/検証の流れ

ここでは、すでにEC2インスタンスが構築されていることを前提とします。インスタンスの構築やIAMロールの設定に関しては、前回の記事でも解説していますので、そちらも参考にしてください。

https://qiita.com/free-honda/items/f2a2e922a826c2b45a18

### EventBridgeルールの作成
まず、EC2インスタンスの起動を検知するためのEventBridgeルールを設定します。

AWS Management ConsoleでEventBridgeに移動し、新しいルールを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/3b1e923f-5003-ec8e-e880-78a45a773798.png)


イベントソースを「EC2」から選択し、イベントタイプを「EC2インスタンスの状態変更通知」とします。

EC2インスタンスの起動（state: running）を検知するため、以下のカスタムイベントパターンJSONを使用します。

```json
{
  "source": [
    "aws.ec2"
  ],
  "detail-type": [
    "EC2 Instance State-change Notification"
  ],
  "detail": {
    "instance-id": [
      "i-xxx"
    ],
    "state": [
      "running"
    ]
  }
}

```


このように「state: running」としてイベントパターンを指定することで、特定のインスタンスの起動イベントをキャプチャできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/95b3450f-8a03-9153-60cd-c0eaf1d60695.png)


設定内容に問題がないことを確認してから、ルールを作成します。

### Lambda関数の作成
EventBridgeからトリガーされるLambda関数を作成します。AWS Lambdaに移動し、新しい関数を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/4c8316f1-ddad-8d87-609d-7fa56a5b3ec9.png)

:::note warn
 Lambda関数に使用する実行ロールには、AmazonSSMFullAccessポリシーを必ずアタッチしてください。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/c68d85de-372a-ff4e-b086-a70945e8edd9.png)

以下のコードは、トリガーされた際に指定のEC2インスタンスにSSMコマンドを実行し、メッセージを出力します。

```python
import boto3
import datetime

def lambda_handler(event, context):
    # SSMクライアントの作成
    ssm = boto3.client('ssm')
    
    # インスタンスIDを取得
    instance_id = event['detail']['instance-id']
    
    # 現在のタイムスタンプを取得
    timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    
    # SSM Run Commandを使用してメッセージを出力
    command = f"echo '{timestamp} - OSが起動しました' >> /tmp/instance_status.txt"
    
    response = ssm.send_command(
        InstanceIds=[instance_id],
        DocumentName="AWS-RunShellScript",
        Parameters={'commands': [command]},
    )
    
    return {
        'statusCode': 200,
        'body': response
    }
```
    
このLambda関数では、インスタンスが起動した際に、/tmp/instance_status.txt ファイルにタイムスタンプ付きのメッセージを記録します。

### Lambdaトリガーの設定

Lambda関数を作成した後、EventBridgeルールのターゲットとしてこの関数を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/8801274c-02b8-424d-61f4-2f7ecf8f0645.png)

これにより、EC2インスタンスの起動が検知されるたびに、Lambda関数が自動で呼び出されます。

## 検証方法

EC2インスタンスを起動または再起動して、EventBridgeがインスタンスの状態変化を検知し、Lambda関数がトリガーされてSSMコマンドが正常に実行されるか確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/54d960ca-ab55-c3f8-6f4f-959d175d0c23.png)


その結果、/tmp/instance_status.txtに以下のようにタイムスタンプ付きのメッセージが出力されます。

```instance_status.txt
**実際のファイル出力結果**
[ec2-user@ip-10-0-7-121 ~]$ cd /tmp/
[ec2-user@ip-10-0-7-121 tmp]$ cat instance_status.txt 
2024-10-12 09:09:51 - OSが起動しました
2024-10-12 09:11:47 - OSが起動しました
[ec2-user@ip-10-0-7-121 tmp]$ 
```

この結果から、イベントの検知とSSMコマンドの自動実行が成功していることが確認できました。


## 注意点と補足

:::note warn
今回の検証を進める際、以下の点に注意し、検証が完了したら速やかにリソースを削除することをおすすめします。

**コスト管理:** 
SSMとLambdaの利用には料金が発生します。大量のインスタンスや頻繁なイベント処理がある場合は、コストに十分注意してください。

**ログ管理:** 
Lambda関数とSSMの実行ログをCloudWatch Logsに記録することで、トラブルが発生した際に問題の特定や解決が容易になります。
:::

## おわりに
この記事では、EC2インスタンスの起動イベントをEventBridgeで検知し、LambdaをトリガーにSSM Run Commandを実行する自動化の手順を紹介しました。

実際の環境で使用する際は、エラーハンドリングやリトライ設定を追加することで、より安定した運用が可能になります。

## おまけ

EventBridgeやLambdaのモニタリング画面でも、正常にイベントがトリガーされているか確認ができます。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/165afde4-37c3-d7ed-78f6-a7d5a8a2bdb5.png)

加えて、CloudWatch Logsにもエラーログが出力されていないか確認しておくと、より安心です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/09ad9182-0ef1-9f79-109e-b65e787d7838.png)

検証結果が正常に出ている場合、運用準備が完了したと言えるでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/aef83670-99af-2910-8773-b17d1b1063b4.png)


## 参考文献

https://qiita.com/chanP_yamazaki/items/d602c30044a6991c31e1