こんにちは
ちょっとタイトルがうまくまとめられず、残念な日本語力のものです
今回は以前書いた下記記事を利用して、httpdプロセスが落ちたら自動的に再起動する機構を作ってみました
なお、機構としては、割とよくあるものなので、完全自分用の備忘録です
【AWS】AlmaLinux9にCloudWatch エージェントを導入してhttpdプロセスを監視してみる
▼前提 (※記事の通りに対応していれば下記は完了しています)
・EC2にhttpdがインストールずみ
・EC2にCLoudWatchエージェントがインストール済み
・CloudWatchコンソール上でhttpdプロセスのメトリクスが取得できていること
▼機構
1. CloudWatchでhttpdプロセスが0になったらアラームが発火
2. トリガーに設定しているLambda関数の実行
3. EC2のhttpdが再起動される
4. アラームの復旧
▼手順
1. Lambda用IAMロールの作成
信頼されたエンティティタイプ:AWSのサービス
ユースケース:Lambda
許可ポリシー:AmazonSSMFullAccess、CloudWatchLogsFullAccess
ロール名:lambda-to-ssm-role
→内容に問題がないことを確認したら、ロールを作成する
2. Lambda関数の作成
・関数の作成
Lambda > 関数 > 関数を作成 > 1から作成 を選択する
:restart-httpd-function
アーキテクチャ:x86_64
実行ロール:lambda-to-ssm-role
import boto3
import logging
import json
logger = logging.getLogger()
logger.setLevel(logging.INFO)
ssm = boto3.client('ssm')
def lambda_handler(event, context):
try:
# CloudWatchから渡ってきたjsonデータのログを出力
#logger.info("Received event: " + json.dumps(event, indent=2))
# metricsはリストなので [0] で最初の要素を指定
instance_id = event['alarmData']['configuration']['metrics'][0]['metricStat']['metric']['dimensions']['InstanceId']
# instance_idを出力
logger.info(instance_id)
# instance_idで取得したEC2に対して、コマンドを実行
command = "systemctl restart httpd"
ssm.send_command(
InstanceIds = [
instance_id
],
DocumentName = "AWS-RunShellScript",
Parameters = {
"commands": [
command
],
"executionTimeout": ["600"]
},
)
logger.info("send_command")
except Exception as e:
logger.error(e)
→コードを記載したら、Deployを押下して更新する
★CloudWatchLogsから送られてるの下記のようになっています
{
"source": "aws.cloudwatch",
"alarmArn": "arn:aws:cloudwatch:ap-northeast-1:xxxxxxxxxxxx:alarm:restart-httpd-alarm",
"accountId": "xxxxxxxxxxxx",
"time": "xxxx-xx-xxxx:xx:xx.xxx+xxxx",
"region": "ap-northeast-1",
"alarmData": {
"alarmName": "restart-httpd-alarm",
"state": {
"value": "ALARM",
"reason": "Threshold Crossed: 1 out of the last 1 datapoints [0.0 (xx/xx/xx xx:xx:xx)] was less than or equal to the threshold (0.0) (minimum 1 datapoint for OK -> ALARM transition).",
"reasonData": "{\"version\":\"1.0\",\"queryDate\":\"xxxx-xx-xxxx:xx:xx.xxx+xxxx\",\"startDate\":\"xxxx-xx-xxxx:xx:xx.xxx+xxxx\",\"statistic\":\"Maximum\",\"period\":60,\"recentDatapoints\":[0.0],\"threshold\":0.0,\"evaluatedDatapoints\":[{\"timestamp\":\"xxxx-xx-xxxx:xx:xx.xxx+xxxx\",\"sampleCount\":1.0,\"value\":0.0}]}",
"timestamp": "xxxx-xx-xxxx:xx:xx.xxx+xxxx"
},
"previousState": {
"value": "OK",
"reason": "Threshold Crossed: 1 out of the last 1 datapoints [5.0 (xx/xx/xx xx:xx:xx)] was not less than or equal to the threshold (0.0) (minimum 1 datapoint for ALARM -> OK transition).",
"reasonData": "{\"version\":\"1.0\",\"queryDate\":\"xxxx-xx-xxxx:xx:xx.xxx+xxxx\",\"startDate\":\"xxxx-xx-xxxx:xx:xx.xxx+xxxx\",\"statistic\":\"Maximum\",\"period\":60,\"recentDatapoints\":[5.0],\"threshold\":0.0,\"evaluatedDatapoints\":[{\"timestamp\":\"xxxx-xx-xxxx:xx:xx.xxx+xxxx\",\"sampleCount\":1.0,\"value\":5.0}]}",
"timestamp": "xxxx-xx-xxxx:xx:xx.xxx+xxxx"
},
"configuration": {
"metrics": [
{
"id": "xxxxxxxxxxxxxxxxxxxxxxxx",
"metricStat": {
"metric": {
"namespace": "CWAgent",
"name": "procstat_lookup_pid_count",
"dimensions": {
"InstanceId": "i-xxxxxxxxxxxx"
}
},
"period": 60,
"stat": "Maximum"
},
"returnData": true
}
]
}
}
}
・CloudWatch からのアクセス権限を付与
関数 > 設定 > アクセス権限 > アクセス権限を追加 を押下する
3. CloudWatchアラームの作成
CloudWatch > アラーム > アラームの作成 を押下
メトリクス名:procstat_lookup_pid_count
統計:1
期間:1分
条件:0 以下
アラーム状態トリガー:アラーム状態
関数タイプ:サインインしたアカウントから Lambda 関数を選択
関数:restart-httpd-function
アラーム名:restart-httpd-alarm
→内容に問題がなければ、アラームを作成する
→OKになれば準備完了です
4. テスト実行
・httpdの停止
systemctl stop httpd
・CloudWatch
→アラーム状態になることを確認
・Lambdaが実行されることを確認
→モニタリング より関数の実行が成功していることを確認
・CloudWatchLogsから確認
→エラーが出ずに、send_command が出力されていることを確認する
・プロセスの確認
→EC2でhttpdプロセスが active (running) になっていること、および CloudWatchアラームが復旧することを確認する
※アラームの復旧まで結構時間がかかります
▼まとめ
いかがでしたでしょうか?
機構自体はそこまで難しくはなかったですが、どのIAMロールが必要になるのかや、CLoudWatchとLambdaの接続でアクセス権限を付与する必要があるなど少し厄介なところもありました
ただ、簡単な再起動などのオペレーションを自動化するときに便利であり、SNSと組み合わせてSlackやメール通知を組み込めばかなり実務でも使えそうでした
それではまたーー
