6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AWS CloudWatch Synthetics Monitoring を CloudFormation で設定する

Last updated at Posted at 2020-07-12

参考) 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 を設定することで削除されるようになりました。
6
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?