参考) Using Synthetic Monitoring - Amazon CloudWatch Documentation
リソース
管理コンソールから CloudWatch Synthetics の Canary を作成すると、以下のリソースが展開される。
これを参考にして CloudFormation で各リソースを作成する。
CloudFormation テンプレート
Parameters
以下をパラメタ化した。
- CanaryName : Canary の名前。配下にいろいろリソースを作る都合上からか、Canary の名前は
[a-z\-_]{,21}
と厳しい制約になっている。 - BucketName : 結果の保存先とするバケット名
- TargetURL : 監視対象の URL
参考) Parameters - AWS CloudFormation
Parameters:
CanaryName:
Description: Synthetics Canary name to create
Type: String
BucketName:
Description: Bucket name to save Synthetics results
Type: String
TargetURL:
Description: Target URL to monitor
Type: String
Service Role
自動で作られる Role を参考に作成した。必要な permissions は Canary リソースに指定する ExecutionRoleArn の説明に書かれている。
- S3 バケットに結果を書き込むための s3:PutObject と s3::GetBucketLocation、あと s3:ListAllMyBuckets
- Lambda から実行ログを出力するための logs:CreateLogStream, logs:PutLogEvents, logs:CreateLogGroup
- CloudWatch Metrics に送信するための cloudwatch:PutMetricData
参考) AWS::IAM::Role - AWS CloudFormation
Resources:
SyntheticsIamRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: "sts:AssumeRole"
Policies:
- PolicyName: "SyntheticsPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetBucketLocation
Resource:
- !Sub "${SyntheticsResultsBucket.Arn}/*"
- Effect: Allow
Action:
- logs:CreateLogStream
- logs:PutLogEvents
- logs:CreateLogGroup
Resource:
- !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/cwsyn-${CanaryName}-*"
- Effect: Allow
Action:
- s3:ListAllMyBuckets
Resource: "*"
- Effect: Allow
Resource: "*"
Action: cloudwatch:PutMetricData
Condition:
StringEquals:
cloudwatch:namespace: CloudWatchSynthetics
S3 Bucket
参考) AWS::S3::Bucket - AWS CloudFormation
SyntheticsResultsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
Synthetics Canary
参考) AWS::Synthetics::Canary - AWS CloudFormation
上で生成した IAM Role、保存先バケット名を指定して作る。
Canary を生成すると Lambda 関数も自動的に生成される。
ここで設定しているスクリプトは Blueprint として用意されている Heatbeat monitoring そのまま持ってきたもの。スクリプトは Code
に直接記述するほか、S3 に保存しておいて場所を指定することができる。SAM で管理できると良いと思うのだけど...
Canary:
Type: AWS::Synthetics::Canary
Properties:
Name: !Ref CanaryName
ExecutionRoleArn: !GetAtt SyntheticsIamRole.Arn
Code:
Handler: pageLoadBlueprint.handler
Script: !Sub >
var synthetics = require('Synthetics');
const log = require('SyntheticsLogger');
const pageLoadBlueprint = async function () {
const URL = "${TargetURL}";
let page = await synthetics.getPage();
const response = await page.goto(URL, {waitUntil: 'domcontentloaded', timeout: 30000});
//Wait for page to render.
//Increase or decrease wait time based on endpoint being monitored.
await page.waitFor(15000);
await synthetics.takeScreenshot('loaded', 'loaded');
let pageTitle = await page.title();
log.info('Page title: ' + pageTitle);
if (response.status() !== 200) {
throw "Failed to load page!";
}
};
exports.handler = async () => {
return await pageLoadBlueprint();
};
ArtifactS3Location: !Sub "s3://${SyntheticsResultsBucket}"
RuntimeVersion: syn-1.0
Schedule:
DurationInSeconds: 0
Expression: "rate(5 minutes)"
RunConfig:
TimeoutInSeconds: 60
FailureRetentionPeriod: 31
SuccessRetentionPeriod: 31
StartCanaryAfterCreation: true
DeleteLambdaResourcesOnCanaryDeletion: true
SNS Topic
Alarm の通知先トピック
参考) AWS::SNS::Topic - AWS CloudFormation
AlarmTopic:
Type: AWS::SNS::Topic
CloudWatch Alarm
Canary の実行結果は固定名の Metrics に送信されるので、それに対して Alarm を設定する。
参考) AWS::CloudWatch::Alarm - AWS CloudFormation
CanaryAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
MetricName: "SuccessPercent"
Namespace: "CloudWatchSynthetics"
Dimensions:
- Name: CanaryName
Value: !Ref CanaryName
Statistic: Average
Period: 300
EvaluationPeriods: 1
Threshold: 90
AlarmActions:
- Ref: AlarmTopic
OKActions:
- Ref: AlarmTopic
InsufficientDataActions:
- Ref: AlarmTopic
TreatMissingData: breaching
ComparisonOperator: LessThanThreshold
注意点
-
Canary を生成するとcwsyn-(Canary 名)-xxxx
という Lambda が生成されるが、スタックを削除しても Lambda までは削除されないようなので、手動で削除する必要がある。
→DeleteLambdaResourcesOnCanaryDeletion
を設定することで削除されるようになりました。