🌩️

ASGのイベントを検知して他のAWSサービスを操作する

2023/12/22に公開

この記事はTechCommit Advent Calendar 2023の22日目の記事です。

データ基盤エンジニアをしてる i-hrm です。
ASG(Auto Scaling Group)での変更イベントを検知したい、それをトリガーにAWSサービスを操作したいシーンがあったので記事を書きます。

使うもの

  • ASG
    • 関連リソースはEC2を想定
  • Event Bridge
  • Lambda

処理フロー

以下のように処理が行われます。

  1. ASGが動作しイベントが発生
  2. イベントがEvent Bridgeへ伝播
  3. Event BridgeがLambdaへ伝播
  4. Lambdaがイベントをトリガーに発火

ASGイベントをLambdaでどう処理するか

ASGで発生したイベント(EC2のterminateやstart etc...)は複数ありますが、特定のイベントだけをEvent Bridgeへ伝播するためにはEvent Bridge Ruleを設定します。
ただASGでどのEC2がイベントを起こしたのか、というのはわかりません。

例えば(terraformベースではありますが)ASGでterminateイベントをキャッチするためには以下のような実装になります。

resource "aws_cloudwatch_event_rule" "example" {
  name        = "example-rule"
  description = "Trigger Lambda on specific events"

  event_pattern = jsonencode({
    "source" : [
      "aws.ec2",
    ],
    "detail-type" : [
      "EC2 Instance State-change Notification"
    ],
    "detail" : {
      "state" : [
        "terminated"
      ]
    }
  })
}

ここではdetail.stateでterminatedを指定してます。
設定の方はlistなので複数設定可能です。(startなど)

以下はlambdaのhandlerのexampleコードです。

def handler(event, context):
    ec2_client = boto3.client('ec2')
    instance_id = event['detail']['instance-id']
    response = ec2_client.describe_tags(
        Filters=[
            {
                'Name': 'resource-id',
                'Values': [instance_id]
            }
        ]
    )

    if 'hoge' in [v.get('Value') for v in response['Tags']]:
        return {
            'statusCode': 200,
            'body': 'found hoge tag!'
        }
    else:
        return {
            'statusCode': 200,
            'body': 'not found hoge tag!'
        }

lambdaに来たイベントからEC2のインスタンスIDを取得し、インスタンスIDからタグ情報を取得しています。
そのタグに特定の値が含まれていた場合の分岐処理が最後の箇所になります。
実装内部でフィルター処理を挟むことで、細かな操作を実装できます。

おわりに

lambdaの中でboto3を利用することでAWSサービスに対して様々な操作ができます。
また今回はEvent BridgeにEC2を設定しましたが、他の設定も可能です。

個人的にはインフラ側で細かな操作を行うことなく簡易に設定できれば運用保守的には良いはずです。
ただ細かな操作もAWSサービスを組み合わせることで実現可能なことを知ることが出来ました。

なんでも出来ちゃいますね…

Discussion