michimani.net

[レポート] JAWS-UG CLI 専門支部 #167R EventBridge入門 に参加しました #jawsug_cli

2020-09-10

JAWS-UG CLI 専門支部 #167R EventBridge入門 に参加したので、その参加レポートです。

connpass のイベントページはこちら。

目次

Amazon EventBridge の概要

EventBridge

EventBridge スキーマレジストリ

ハンズオン

今回のハンズオンでは、 EBS のイベントを検知して、 Lambda 経由で CloudWatch Logs にイベントを書き込むという内容でした。詳細についてはイベントページに記載されている手順におまかせするとして、使ったコマンドとその出力について簡単に触れておきます。

各手順で使用したコマンド

EventBridge Registru のスキーマ確認

schemas describe-schema コマンドを使います。

$ aws schemas describe-schema help
...
SYNOPSIS
            describe-schema
          --registry-name <value>
          --schema-name <value>
          [--schema-version <value>]
          [--cli-input-json | --cli-input-yaml]
          [--generate-cli-skeleton <value>]
          [--cli-auto-prompt <value>]

今回は EBS をイベントソースとするので、その際に発行されるイベントのスキーマを確認しました。

$  aws schemas describe-schema \
> --registry-name aws.events \
> --schema-name aws.ec2@EBSVolumeNotification
{
    "Content": "{ \"openapi\" : \"3.0.0\", \"info\" : { \"version\" : \"1.0.0\", \"title\" : \"EBSVolumeNotification\" }, \"paths\" : { }, \"components\" : { \"schemas\" : { \"AWSEvent\" : { \"type\" : \"object\", \"required\" : [ \"detail-type\", \"resources\", \"id\", \"source\", \"time\", \"detail\", \"region\", \"version\", \"account\" ], \"x-amazon-events-detail-type\" : \"EBS Volume Notification\", \"x-amazon-events-source\" : \"aws.ec2\", \"properties\" : { \"detail\" : { \"$ref\" : \"#/components/schemas/EBSVolumeNotification\" }, \"detail-type\" : { \"type\" : \"string\" }, \"resources\" : { \"type\" : \"array\", \"items\" : { \"type\" : \"string\" } }, \"id\" : { \"type\" : \"string\" }, \"source\" : { \"type\" : \"string\" }, \"time\" : { \"type\" : \"string\", \"format\" : \"date-time\" }, \"region\" : { \"type\" : \"string\" }, \"version\" : { \"type\" : \"string\" }, \"account\" : { \"type\" : \"string\" } } }, \"EBSVolumeNotification\" : { \"type\" : \"object\", \"required\" : [ \"result\", \"cause\", \"event\", \"request-id\" ], \"properties\" : { \"result\" : { \"type\" : \"string\" }, \"cause\" : { \"type\" : \"string\" }, \"event\" : { \"type\" : \"string\" }, \"request-id\" : { \"type\" : \"string\" } } } } } }",
    "Description": "Schema for event type EBSVolumeNotification, published by AWS service aws.ec2",
    "LastModified": "2019-12-01T00:31:47+00:00",
    "SchemaArn": "",
    "SchemaName": "aws.ec2@EBSVolumeNotification",
    "SchemaVersion": "1",
    "Tags": {},
    "Type": "OpenApi3",
    "VersionCreatedDate": "2019-12-01T00:31:47+00:00"
}

Content の内容がイベントのスキーマで、整形すると下記のような内容になっています。

{
    "openapi": "3.0.0",
    "info": {
        "version": "1.0.0",
        "title": "EBSVolumeNotification"
    },
    "paths": {},
    "components": {
        "schemas": {
            "AWSEvent": {
                "type": "object",
                "required": [
                    "detail-type",
                    "resources",
                    "id",
                    "source",
                    "time",
                    "detail",
                    "region",
                    "version",
                    "account"
                ],
                "x-amazon-events-detail-type": "EBS Volume Notification",
                "x-amazon-events-source": "aws.ec2",
                "properties": {
                    "detail": {
                        "$ref": "#/components/schemas/EBSVolumeNotification"
                    },
                    "detail-type": {
                        "type": "string"
                    },
                    "resources": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "id": {
                        "type": "string"
                    },
                    "source": {
                        "type": "string"
                    },
                    "time": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "region": {
                        "type": "string"
                    },
                    "version": {
                        "type": "string"
                    },
                    "account": {
                        "type": "string"
                    }
                }
            },
            "EBSVolumeNotification": {
                "type": "object",
                "required": [
                    "result",
                    "cause",
                    "event",
                    "request-id"
                ],
                "properties": {
                    "result": {
                        "type": "string"
                    },
                    "cause": {
                        "type": "string"
                    },
                    "event": {
                        "type": "string"
                    },
                    "request-id": {
                        "type": "string"
                    }
                }
            }
        }
    }
}

ちなみに、 aws.events レジストリに含まれるスキーマの一覧は下記のコマンドで確認できます。

$ aws schemas list-schemas \
--registry-name aws.events \
--query "Schemas[].SchemaName"

EventBridge ルールの作成

events put-rule コマンドを使用します。

$ aws events put-rule help
...
SYNOPSIS
            put-rule
          --name <value>
          [--schedule-expression <value>]
          [--event-pattern <value>]
          [--state <value>]
          [--description <value>]
          [--role-arn <value>]
          [--tags <value>]
          [--event-bus-name <value>]
          [--cli-input-json | --cli-input-yaml]
          [--generate-cli-skeleton <value>]
          [--cli-auto-prompt <value>]

今回は EBS の通知をイベントソースとするので、イベントパターンを {"source":["aws.ec2"],"detail-type":["EBS Volume Notification"]} とします。ここで指定する source および detail-type に関しては、先ほど取得したスキーマ内の Content の内容から確認できます。

$ aws events put-rule \
--name handson-cli-events-gettings-ebs-rule \
--description "EBS event rule." \
--event-pattern '{"source":["aws.ec2"],"detail-type":["EBS Volume Notification"]}'

EventBridge にターゲット登録

events put-targets コマンドを使用します。

$ aws events put-targets help
...
SYNOPSIS
            put-targets
          --rule <value>
          [--event-bus-name <value>]
          --targets <value>
          [--cli-input-json | --cli-input-yaml]
          [--generate-cli-skeleton <value>]
          [--cli-auto-prompt <value>]
$ aws events put-targets \
--rule handson-cli-events-gettings-ebs-rule \
--targets "Id=lambda-handson-cli-events-gettings-ebs-function,Arn=arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:handson-cli-events-gettings-ebs-function"

--target ではイベントターゲットを指定しますが、今回は Lambda 関数を指定しています。 Id はターゲット ID になるもので、ルールに追加できるターゲットが 5 つまでということから、各ターゲットを識別するために付与します。Arn は Lambda 関数の ARN です。

ログの確認

CloudWatch Logs のログイベントを確認するには、ロググループ名とログストリーム名が必要です。

Lambda で作成されるロググループ名は /aws/lambda/{関数名} という形式になるので、今回は /aws/lambda/handson-cli-events-gettings-ebs-function となります。ログストリームは実行されるタイミングでハッシュ値を含んだ名前で作成されます。今回は直近のログイベントを取得したいので、ログストリームも直近のものを取得します。

$ aws logs describe-log-streams \
--log-group-name /aws/lambda/handson-cli-events-gettings-ebs-function \
--query 'max_by(logStreams[], &lastEventTimestamp).logStreamName' \
--output text

2020/09/10/[$LATEST]544ac06f414a47f6b49395b56db4a762

ログイベントの内容は、タイムスタンプとメッセージだけ抜き出して出力します。

$ aws logs get-log-events \
--log-group-name /aws/lambda/handson-cli-events-gettings-ebs-function \
--log-stream-name '2020/09/10/[$LATEST]544ac06f414a47f6b49395b56db4a762' \
--limit 7 \
--query 'events[].[join(``, [ to_string(timestamp) ,`: `,message])]' \
--output text

...
1599735257694: ## EVENT

1599735257694: {'version': '0', 'id': '672deda3-a5d2-84f9-97b9-2d7531855a2e', 'detail-type': 'EBS Volume Notification', 'source': 'aws.ec2', 'account': 'XXXXXXXXXXXX', 'time': '2020-09-10T10:54:17Z', 'region': 'ap-northeast-1', 'resources': ['arn:aws:ec2:ap-northeast-1:XXXXXXXXXXXX:volume/vol-02871700072f113f1'], 'detail': {'result': 'deleted', 'cause': '', 'event': 'deleteVolume', 'request-id': '213c7669-dee3-4223-a994-6f17af23d650'}}
...

ちなみに、タイムスタンプは文字列ではないためそのままでは join できないようです。 join したい場合は to_string で文字列に変換します。

知らんかったぞ、それ

今回に限らずハンズオンでは新しく知ることがたくさんあるので、この 知らんかったぞ、それ 項目では新しく知ったことを自分なりに深堀りしてみたいと思います。(恒例化したい)

Python 3 の json.tool

JAWS-UG CLI 専門支部では JSON のフォーマット確認に jsonlint を利用していました。が、今回の手順では Python 3 に含まれる json.tool というモジュールを使っていました。使い方は簡単で、 JSON の出力をパイプで渡す形で、次のように実行します。

$ cat ${JSON_FILE_PATH} | python3 -m json.tool

例えば次のような JSON ファイルを準備して、フォーマットチェックしてみます。

$ cat sample.json 
{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}

$ cat sample.json | python3 -m json.tool
{
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
}

特にエラーがなければ JSON が出力されます。フォーマットが崩れていたりすると、エラーが出力されます。(2 つ目のカンマを削除してみます)

$ cat sample.json | python3 -m json.tool
Expecting ',' delimiter: line 4 column 3 (char 43)

--query オプション内での max_by

直近のログストリーム名を取得する際に、 --query オプションの中で max_by というクエリを使っていました。これは AWS CLI の機能というよりは JMESPath の機能で、配列内の最大要素を返してくれます。

今回実行したのは次のようなコマンドでした。

$ aws logs describe-log-streams \
--log-group-name /aws/lambda/handson-cli-events-gettings-ebs-function \
--query 'max_by(logStreams[], &lastEventTimestamp).logStreamName' \
--output text

max_by でログストリームの lastEventTimestamp が最大のもの、つまり直近のものを取得するようなクエリになっていました。

例えば、 Lambda でコードサイズが一番大きい関数の名前が取得したい場合は、次のようなコマンドになります。

$ aws lambda list-functions \
--query 'max_by(Functions, &CodeSize).FunctionName'

ちなみに、 max_by の逆は min_by です。

まとめ

JAWS-UG CLI 専門支部 #167R EventBridge入門 の参加レポートでした。

今回は EventBridge 入門ということ、そもそも EventBridge とは何なのかについて再確認することができました。スキーマレジストリの存在については知らなかったのですが、イベントルール作成時に必要な情報が参照できるのは便利だなと思いました。

CLI 専門支部では、各回で扱うサービスの内容はもちろん、 AWS CLI の --query および --filter オプションの便利な使い方を知ることもできます。ハンズオンの手順によっては実行するコマンドが多くてついていくのが大変ですが、毎回得るものがたくさんあるので めっちゃインプットしてるな〜 と感じます。

インプットしたままで終わらないように、今後も参加レポ書いていきたいと思います。


comments powered by Disqus