起動直後のCloudWatchアラームの通知を抑止したいという要望があったので、AWSサービスを組み合わせて実現してみました。
#構成
EventBridge + Lambdaで実現します。
EC2起動直後の一定時間を待つために、起動時にはStep FunctionsからLambdaを呼び出します。
EventBridgeやStep Functionsは応用の幅が広いので、その一例としても役立ちそうです。
Lambdaコード
まずはLambdaコードから見ていきます。
import boto3
target = {
"test-instance" : ['test-alarm']
}
def lambda_handler(event, context):
client = boto3.client('cloudwatch')
if event["Action"] == 'enable':
response = client.enable_alarm_actions(
AlarmNames=target[event["Target"]]
)
if event["Action"] == 'disable':
response = client.disable_alarm_actions(
AlarmNames=target[event["Target"]]
)
EventBridgeからキーバリューを受け取ることを前提としたコードです。
Actionキーでアラームの有効or無効を切り替えます。TargetキーでEC2を識別します。ここではインスタンス名(test-instance)とします。あらかじめインスタンス名に対応したアラーム名(test-alarm)を辞書型のtargetで定義しておきます。
これにより、EventBridgeで指定したインスタンスに対応するアラームの有効化or無効化を実行することができます。
##IAMポリシー
Lambda用のIAMポリシーです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"cloudwatch:EnableAlarmActions",
"cloudwatch:DisableAlarmActions",
"logs:CreateLogGroup",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
標準で付与されるログ周りを除くと、EnableAlarmActionsとDisableAlarmActionsが必要です。
これらのアクションはAWSコンソールからは実行できず、LambdaやCLIで実行する必要があるようです。
#Step Functionsステートマシン
EC2起動時に実行するステートマシンを定義します。
{
"StartAt": "Wait",
"States": {
"Wait": {
"Type": "Wait",
"Seconds": 60,
"Next": "MainTask"
},
"MainTask": {
"Type": "Task",
"Resource": "arn:aws:lambda:リージョン名:アカウントID:function:AlarmSwitch",
"End": true
}
}
}
リージョン名とアカウントIDは置き換えてください。ステートマシン内で前述のLambdaを呼び出します。ここでは実行までに1分間待つことにします。
IAMポリシー
ステートマシン用のIAMポリシーです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"arn:aws:lambda:リージョン名:アカウントID:function:AlarmSwitch:*"
]
},
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"arn:aws:lambda:リージョン名:アカウントID:function:AlarmSwitch"
]
},
{
"Effect": "Allow",
"Action": [
"xray:PutTraceSegments",
"xray:PutTelemetryRecords",
"xray:GetSamplingRules",
"xray:GetSamplingTargets"
],
"Resource": [
"*"
]
}
]
}
リージョン名とアカウントIDは置き換えてください。xray周りは標準で付与されるものです。前述のLambdaの実行権限を付与しておきます。
EventBridge
あとはEventBridgeで対象のEC2の起動停止をトリガーにして、先ほどのLambdaとステートマシンを実行します。
EC2起動
イベントパターン
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"detail": {
"state": ["running"],
"instance-id": ["インスタンスID"]
}
}
インスタンスIDは置き換えてください。
ターゲット
先ほどのステートマシンを選択します。Lambdaに引き渡すキーバリューをJSONで指定します。
IAMポリシー
EC2起動EventBridge用のIAMポリシーです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"states:StartExecution"
],
"Resource": [
"arn:aws:states:リージョン名:アカウントID:stateMachine:AlarmSwitchStateMachine"
]
}
]
}
リージョン名とアカウントIDは置き換えてください。先ほどのステートマシンの実行権限が必要です。
EC2停止
イベントパターン
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"detail": {
"state": ["stopped"],
"instance-id": ["インスタンスID"]
}
}
ターゲット
停止時は待機しないので、直接Lambdaを呼び出します。AWSコンソールで作成すれば、実行権限はLambdaパーミッションで自動的に付与されます。CloudFormationで作成する際はLambdaパーミッションの設定に注意です。キーバリューもEC2起動と同じ形式で入力します。
実行結果
準備が整ったら、対象のEC2インスタンスを起動および停止します。
停止すると、インスタンスに対応したアラームが無効になります。
起動すると、ステートマシンが実行され、指定した時間(1分間)待機した後、Lambdaを実行してアラームを有効化します。
これにより、起動後の任意の一定時間、CloudWatchアラームを無効化することができるので、アラームの抑止を実現できました。
今回は停止と起動のセットで動作する構成になりますが、再起動時にも抑止したい場合を考えると、起動時のみをトリガーとしてアラームの有効無効を切り替えるようにするなどの工夫が必要そうです。