[レポート] JAWS-UG CLI 専門支部 #167R EventBridge入門 に参加しました #jawsug_cli
2020-09-10JAWS-UG CLI 専門支部 #167R EventBridge入門 に参加したので、その参加レポートです。
connpass のイベントページはこちら。
目次
Amazon EventBridge の概要
- CloudWatch から分離
- 大きく分けて2つの API
- events
- EventBridge (旧 CLoudWatch Events)
- schemas
- EventBridge スキーマレジストリ
- データ構造の確認
- events
- ユースケース
- イベントの発生元 (他の AWS アカウントも含む) からのイベントを検知
- AWS リソース (他の AWS アカウントも含む) にイベントを通知
- イベントの構造化データ (スキーマ) を参照できるのが EventBridge スキーマレジストリ
EventBridge
- イベントソース
- AWS リソースとしては約 90 のサービスに対応
- 他の AWS アカウントからのイベントには パーミッション の設定が必要
- SaaS ベンダー (Auth0 、 Mackerel 、 Zendesk など) からのイベントでは、イベントバス内に パートナーイベントソース が作成される
- Amazon EventBridge の統合
- パートナー企業だけが使える CLI コマンドがある
- 止めたり再開したりが可能
- イベントターゲット
- 約 20 の AWS リソースに対応
- イベント
- フォーマットが決まっている
time
、source
、resource
、detail-type
、detail
、event-bus-name
- AWS イベント - Amazon EventBridge
- AWS リソースからのイベントでは CloudTrail 経由でないと受け取れないイベントがある
- e.g) S3 のオブジェクト単位のイベント (バケット単位のイベントは直接通知できる)
- フォーマットが決まっている
- イベントバス
- デフォルトイベントバス
- 各アカウントに一つ (意識せず動いている)
- カスタムイベントバス
- アカウントあたり 100 個作成可能
- イベントバスの作成 - Amazon EventBridge
- デフォルトイベントバス
- ルール
- イベントバス内に作成
- 一つのルールに登録できるターゲットは 5 つ
- ターゲット
- ターゲット ID 、 ターゲット ARN 、 IAM ロール
- その他、 EventBridge の制限
EventBridge スキーマレジストリ
- レジストリ
- スキーマの保存
- リソースポリシー (S3 のバケットポリシー的なもの)
- スキーマ
- OpenAPI 3.0 形式
- ディスカバラー
- スキーマの検索
ハンズオン
今回のハンズオンでは、 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