この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
CloudWatch Events について
CloudWatch Eventは2016年1月に発表された比較的新しいサービスで、AWSリソースの変更情報をタイムリーにストリーム伝達します。
CloudWatch Events はイベントソースとして AWS API に対応しています。
AWS のリソースを変更する
- AWS マネージメントコンソール
- AWS CLI
- AWS SDK
といった手段はいずれも API を呼び出しているだけのため、AWS API をイベントソースに指定すると、変更手段によらずAWSリソースを変更するイベント全般をフックすることができます。
Route 53 リソースと連携させてみる
AWSにはAmazon Route 53というDNSサービスがあります。
一般的にDNS設定を変更する頻度は多くないものの、オペミスなどにより誤って設定変更すると、サービスへの影響が甚大です。 更新した時には即座に通知(周知)したいこともあるかと思います。
そこで CloudWatch Events を活用して、Route 53 のリソース変更に対してイベント発火する方法を紹介します。
アーキテクチャー
イベントのトリガー
今回は、Route 53 に対する更新系 API 操作をトリガーにします。
イベントの発火先
トリガーの発火先として、今回は Amazon SNS を利用します。
発火先には Amazon SNS 以外にも
- AWS Lambda
- Amazon SQS
- Amazon Kinesis Stream
- Bullet-in ターゲット
などに対応しています。
発火先には複数のターゲットを指定できます。
やってみた
Route 53 の API 呼び出しと CloudWatch Events/SNS を連携させましょう。
以下の順で作業します。
- CloudTrail の有効化
- SNS トピックの作成
- CloudWatch Eventsの作成
重要な点として、 Route 53 は API のエンドポイントが N. Virginia(us-east-1) リージョンのため、CloudTrail や SNS の操作は同リージョンで行います。
1. CloudTrail の有効化
今回は API 呼び出しをトリガーにするため、API 呼び出しが記録されるように AWS CloudTrail を有効にします。 CloudWatch Events を利用する・しないにかかわらず、API のログを残しておかないと、障害発生時の問題解決が困難になります。
AWS CloudTrailが無効だった場合は、今回を機に有効にしましょう。
Route 53 は API のエンドポイントが N. Virginia リージョンのため、少なくとも同リージョンで Cloud Trail を有効にします。
2. SNS トピックの作成
イベントの通知先 SNS トピックを作成します。
今回はトピック名を「cloudwatch-events-test」としました。 このトピックに対して確認のしやすさを優先してプロトコル「Email-JSON」でサブスクライブします。
運用にあわせて、プロトコル/エンドポイントは変更してください。
プロトコル「Email-JSON」の場合は疎通確認のEmailが届きます。 メールに記載されたリンクをクリックして疎通確認します。
3. AWS CloudWatch Eventsの作成
最後にメインとなる AWS CloudWatch Events を作成します。
管理画面の CloudWatch から Events -> Rules と選択し、ルールの作成画面に遷移します。
イベントのインプットとして
- 種類は「AWS API call」
- Service name は「Route 53」
を選択します。
イベントの発火先ターゲットとしてとして
- 種類は「SNS topic」
- トピック名は先程作成した「cloudwatch-events-test」
- Configure Input は「Matched event」
を選択します。
ルールの定義が完了すると、次のようになります。
動作確認
それでは、Route 53 の更新系 API を呼び出してみましょう。
AWS マネージメントコンソールから A レコードを変更した時
route53 の管理画面から A レコードを変更します。
変更すると以下のようなメールが通知されます。
Message キーが肝なため、Message キーの値を見やすく加工したのが以下です。
{
"version": "0",
"id": "47399003-f31a-49f0-b1a6-a5976673bb0b",
"detail-type": "AWS API Call via CloudTrail",
"source": "aws.route53",
"account": "123456789012",
"time": "2016-05-21T16:30:51Z",
"region": "us-east-1",
"resources": [],
"detail": {
"eventVersion": "1.04",
"userIdentity": {
"type": "IAMUser",
"principalId": "DUMMY",
"arn": "arn:aws:iam::123456789012:user/cm-jane.doe",
"accountId": "123456789012",
"accessKeyId": "DUMMY",
"userName": "cm-jane.doe",
"sessionContext": {
"attributes": {
"mfaAuthenticated": "true",
"creationDate": "2016-05-21T05:46:38Z"
}
},
"invokedBy": "signin.amazonaws.com"
},
"eventTime": "2016-05-21T16:30:51Z",
"eventSource": "route53.amazonaws.com",
"eventName": "ChangeResourceRecordSets",
"awsRegion": "us-east-1",
"sourceIPAddress": "1.2.3.4",
"userAgent": "signin.amazonaws.com",
"requestParameters": {
"changeBatch": {
"changes": [
{
"action": "CREATE",
"resourceRecordSet": {
"type": "A",
"name": "www.dummy.com.",
"resourceRecords": [
{
"value": "192.0.2.235"
}
],
"tTL": 300
}
}
]
},
"hostedZoneId": "Z27S25GZV7IGA9"
},
"responseElements": {
"changeInfo": {
"submittedAt": "May 21, 2016 4:30:51 PM",
"status": "PENDING",
"id": "/change/C2ROIRXW3Y2VIN"
}
},
"additionalEventData": {
"Note": "Do not use to reconstruct hosted zone"
},
"requestID": "61f6368c-1f71-11e6-beec-215485e52783",
"eventID": "812ced6d-4d54-4ba9-870e-2df73b494648",
"eventType": "AwsApiCall",
"apiVersion": "2013-04-01"
}
}
detail キーの以下のキー
- "eventSource": "route53.amazonaws.com",
- "eventName": "ChangeResourceRecordSets",
- "awsRegion": "us-east-1",
から Route 53 の ChangeResourceRecordSets
API が us-east-1 リージョンに向けて呼ばれたことがわかります。
API のリクエストパラメーターは "requestParameters" キーにあります。
"requestParameters": {
"changeBatch": {
"changes": [
{
"action": "CREATE",
"resourceRecordSet": {
"type": "A",
"name": "www.dummy.com.",
"resourceRecords": [
{
"value": "192.0.2.235"
}
],
"tTL": 300
}
}
]
},
"hostedZoneId": "Z27S25GZV7IGA9"
},
detail -> userIdentity -> invokedBy
が "signin.amazonaws.com" であることから AWS マネージメントコンソール 経由で実行されたこともわかります。
CLI からヘルスチェックを追加した時
{
"Port": 80,
"Type": "HTTP",
"ResourcePath": "/foo",
"FullyQualifiedDomainName": "www.example.com",
"RequestInterval": 10,
"FailureThreshold": 1
}
というような JSON ファイル(test.json)を用意して CLI から Route 53 の API を叩いてみます。
$ aws route53 create-health-check --caller-reference 2014-04-01-18:47 --health-check-config file://test.json
A client error (HealthCheckAlreadyExists) occurred when calling the CreateHealthCheck operation: A different health check has already been created with the specified caller reference.
create-helth-check API はエラーが起きたので実際には更新されませんが、CloudWatch Events のイベントは発火します。
先ほどと同じく、SNS 経由で送信された Email-JSON 形式のメールから重要な Message キーのバリューを見やすく加工したのが以下です。
{
"version": "0",
"id": "a6b7cea4-2c4f-4589-b29f-b6396c8c75bd",
"detail-type": "AWS API Call via CloudTrail",
"source": "aws.route53",
"account": "123456789012",
"time": "2016-05-21T16:44:25Z",
"region": "us-east-1",
"resources": [],
"detail": {
"eventVersion": "1.04",
"userIdentity": {
"type": "IAMUser",
"principalId": "DUMMY",
"arn": "arn:aws:iam::123456789012:user/cm-jane.doe",
"accountId": "123456789012",
"accessKeyId": "DUMMY",
"userName": "cm-jane.doe"
},
"eventTime": "2016-05-21T16:44:25Z",
"eventSource": "route53.amazonaws.com",
"eventName": "CreateHealthCheck",
"awsRegion": "us-east-1",
"sourceIPAddress": "1.2.3.4",
"userAgent": "aws-cli/1.10.32 Python/2.7.11 Darwin/15.4.0 botocore/1.4.22",
"errorCode": "HealthCheckAlreadyExists",
"errorMessage": "A different health check has already been created with the specified caller reference.",
"requestParameters": {
"healthCheckConfig": {
"fullyQualifiedDomainName": "www.example.com",
"failureThreshold": 1,
"requestInterval": 10,
"resourcePath": "/foo",
"port": 80,
"type": "HTTP"
},
"callerReference": "2014-04-01-18:47"
},
"responseElements": null,
"requestID": "47467ad5-1f73-11e6-a791-6756bc02631c",
"eventID": "5518a3f5-70c8-4a95-8d6f-c6f076179c45",
"eventType": "AwsApiCall",
"apiVersion": "2013-04-01"
}
}
detail -> userAgent が AWS CLI のもの("aws-cli/1.10.32 Python/2.7.11 Darwin/15.4.0 botocore/1.4.22"
)なので CLI 経由で呼び出されたことがわかります。
detail -> errorCode/errorMessage には AWS サーバーの返したエラーメッセージが含まれています。
- "errorCode": "HealthCheckAlreadyExists",
- "errorMessage": "A different health check has already been created with the specified caller reference.",
注意点
CloudWatch Events も万能ではありません。
List/Get/Describe 系のリードオンリーAPIには対応していません。 あくまで更新系 API が呼び出された場合のみイベントが発火されます。
また、更新系 API に利用したリクエストパラメーターはイベントメッセージに含まれますが、リソースが更新前にどういう状態だったかについては、知るすべがありません。
まとめ
今回は CloudWatch Events を使い、API 更新操作時にメール通知する方法を紹介しました。
CloudWatch Events を活用して安心・安定したサービス運用を目指しましょう。