AWS Lambda, CloudWatch, SNS, SSMを活用したApache Webサーバーの監視と自動再起動の技術検証

## はじめに
この記事は、前回の記事に続き、AWS Lambdaを活用したApache Webサーバーの監視・自動再起動設定について解説します。

前回の記事の内容をもとに、Lambda関数を使ったさらなる自動化の手順を紹介します。

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

今回の記事では、Lambda関数を使ってApacheサービスを自動再起動する手順を追加し、その設定方法を詳しく説明します。

## 知識整理

:::note warn
[前回の記事](https://qiita.com/free-honda/items/d7eb9e39cfc95ac6e91b)では、以下の内容について説明しました。

**前提準備：AWS環境の準備**
**⓵Apacheのインストールと設定**
**⓶CloudWatchエージェントのインストール**
**⓷CloudWatchエージェントの設定ファイルの作成**
**⓸ApacheのHTTPポート監視**
**⓹CloudWatchアラームの作成**
:::

これにより、CloudWatchアラームを使ってApache Webサーバーの状態を監視し、問題が発生した場合はSNSで通知する設定が完了します。

### **前回のAWSアーキテクチャー**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/92cf8e31-e350-4a5c-4557-1b36e592da79.png)
引用画像：https://itsakura.com/aws-cloudwatch-sns

今回の記事では、Apacheサービスが停止したときに自動で再起動するよう、Lambda関数を設定していきます。

### **今回のAWSアーキテクチャー**

今回は、以下の赤枠部分の機能を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/30b900b6-7301-449a-a49d-c115d0d4b722.png)

SSMのRun Commandについては、以下の記事で詳しく解説していますので、参考にしてください。

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

https://qiita.com/free-honda/items/1ebd3d9341299713357e

## 構築・検証手順
ここからは、Lambda関数を使用してApache Webサーバーの自動再起動を設定する手順について説明します。

なお、[手順⓵から⓹については前回の記事](https://qiita.com/free-honda/items/d7eb9e39cfc95ac6e91b)で詳しく説明しているので、そちらをご参照ください。

## 6. AWS Lambda関数を使ってApacheサービスの再起動を設定
ここでは、Apache Webサーバーのサービスが停止した際に、AWS Lambda関数を利用して自動的にサービスを再起動する手順を説明します。

Lambda関数とCloudWatchアラームを連携させ、サービス停止時に自動再起動を行う設定を構築します。

### Lambda関数の作成

AWS Management Consoleにログインし、Lambdaサービスに移動して「関数の作成」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/498d735a-e36c-e489-524f-67a004814ab9.png)

以下の設定で新しい関数を作成します。

:::note
関数名: RestartApacheService
ランタイム: Python 3.x
実行ロール: 既存のロールを使用するか、新しいロールを作成（EC2インスタンスにアクセスできる権限を設定）
:::

IAMロールの詳細設定は後ほど行うので、ここではデフォルトの実行ロールを使用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/2cd7c060-0e89-a25d-61cf-d2b98da0894a.png)

### Lambda関数のコード

関数を作成したら、以下のPythonコードを追加します。このコードは、EC2インスタンスのApacheを再起動するためのコマンドを実行します。

```py
import boto3

def lambda_handler(event, context):
    # EC2インスタンスのIDを指定
    instance_id = 'i-xxx'
    ssm_client = boto3.client('ssm')  # SSMクライアントを使用
    
    try:
        # SSMでコマンドを送信してApacheを再起動
        ssm_client.send_command(
            InstanceIds=[instance_id],
            DocumentName="AWS-RunShellScript",
            Parameters={'commands': ['sudo systemctl restart httpd']}
        )
        
        return {
            'statusCode': 200,
            'body': 'Restart command sent successfully'
        }

    except Exception as e:
        return {
            'statusCode': 500,
            'body': f"Error: {str(e)}"
        }
```

上記のコード中の**instance_id**は、実際のEC2インスタンスIDに置き換えてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/0429516e-e78c-3912-e6e5-fd99452f50fb.png)

このコードは、AWS Systems Manager (SSM) を使用してEC2インスタンスにApacheの再起動コマンドを送信します。

### Lambda関数に必要なIAMロールの設定

Lambda関数が正常に動作するためには、以下のIAMポリシーを持つロールを作成し、Lambda関数にアタッチする必要があります。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ssm:SendCommand",
        "ec2:DescribeInstances"
      ],
      "Resource": "*"
    }
  ]
}
```

このポリシーを適用したIAMロールを作成し、Lambda関数にアタッチしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/b89dde1c-bb97-6a56-4156-aea2cffffdd5.png)

IAMロールに作成したカスタムポリシーが正しくアタッチされていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/b7a5de95-e195-4d7d-986e-fc6cab0c5f68.png)

:::note alert
**追記：Lambda 側にリソースベースポリシーが必要**
CloudWatchアラーム側でサービスロールを指定できないため、Lambda関数側でリソースベースポリシーの設定が必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/8244994e-442b-0a4f-72b4-ae36a6be8b9f.png)
:::

私の環境では、以下の記事を参考にして設定を進めました。

https://dev.classmethod.jp/articles/cloudwatch-alarms-lambda-change-action/

Lambda関数の「リソースベースのポリシーステートメント」に、CloudWatchのトリガー権限を正しく設定できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/8badc5c2-6357-049f-ec8f-36b852a4a9c1.png)

##  CloudWatchアラームの設定変更

CloudWatchアラームが発生した際に、Lambda関数がトリガーされるように設定を変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/463c1318-b6fa-6a3a-56a9-24495060f49e.png)

CloudWatchアラームの設定画面で、アラームアクションに移動し、既存のSNS通知に加えて、Lambda関数 **RestartApacheService** をトリガーする設定を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/5f543e5c-508e-1420-635e-b1ba9152138d.png)

設定を保存後、アクションタブからSNSによるメール通知と、Lambda関数が正常にトリガーされていることを確認しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/4caacf64-8478-1ca8-e199-0cd8f2a7b798.png)

##  動作確認

Apache Webサーバーのサービスを手動で停止し、CloudWatchアラームとLambda関数の動作を確認します。

```bash
sudo systemctl stop httpd
```

このコマンドでApacheサービスを停止すると、CloudWatchアラームが発生し、Lambda関数が実行されてApacheサービスが自動で再起動されることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/76369d4f-b4de-e7a1-3490-c060cb79ba2c.png)

Apache Webサーバーが停止した際に、Lambda関数が自動的に再起動を行う様子が確認できました。

また、「CloudWatch」の実行履歴でも想定通りの結果が得られました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/0b590169-4124-2cdd-7179-ddcfe0167521.png)

同時に、SNSを通じてメール通知が受信できることも確認しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/e4653107-c0be-991a-4fce-4ed0c45a1f73.png)

今回の検証では、SNSによるアラートメール通知と、Lambda関数によるApacheサービスの自動再起動が正常に動作したため、検証は成功といえます！

(ぶっちゃけ、かなり時間かかりました笑)

## まとめ
この記事では、AWS Lambdaを用いてApache Webサーバーの自動再起動を実現する手順を解説しました。

[前回の記事で構築したシステム](https://qiita.com/free-honda/items/d7eb9e39cfc95ac6e91b)にLambda関数を追加することで、障害対応がさらに効率化されました。

AWSの監視ツールと自動化機能を組み合わせることで、柔軟で迅速なサービス運用が可能になり、今後のシステム運用に役立つと感じました！

## 参考文献

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-sns-example.html

https://zenn.dev/rescuenow/articles/da33826e0afe03