CloudWatch Syntheticsで外形監視!!!
はじめに
「外形監視」って知ってますか?
私はSAPを勉強している時に聞いたような、聞いていないような、そんな感じです。外形監視の機能を提供してくれるAWSサービスは「Amazon CloudWatch Synthetics」(cwsyn)ですか、これも同様であまり覚えていません。
最近、外形監視を導入する機会があったのでまとめたいと思います。CloudFormationテンプレートも作りました。( -`ω-)✧
Amazon CloudWatch Synthetics
- 外形監視とは?
- Webサイトを利用するユーザと同じネットワーク(インターネット)からアクセスして、ユーザ視点でシステムが正常に稼働しているかを監視する手法である。
- 内部監視とは?
- 外形監視がユーザ視点からの監視であるのに対し、内部監視はシステム視点からの監視を指す。
- リソース監視(CPU/メモリ/ストレージ)、ログ監視、ネットワーク監視(PING)、ポート監視等が該当する。
- Canary
- cwsynで外形監視を実施するにはcwsynでCanaryというリソースを作成する。
- Canaryの実態はLambda関数であり、Webサイト/Webアプリケーションへアクセスし実行結果をS3バケットやCloudWatch Logs, X-Rayに保存する。
- 関数コードはブループリントが容易されているため、ノーコーディングで始められる(Node.js or Python)。
- Webページのスクリーンショットを取得することも可能で、S3バケットに保存される。
アーキテクチャ
各リソースの役割とアーキテクチャは下記の通りである。
- Lambda: 外形監視の実行主体
- Lambdaレイヤー:Seleniumとブループリント(アーキ図では省略)
- S3: モニタリング結果の保存場所
- CloudWatch Logs: Lambdaのログを保管
- IAM: Lambdaの実行ロール
テンプレート
- TargetUrlに監視対象のURLを指定します。
- 関数コードはブループリント(ハートビートのモニタリング)を使用します。
AWSTemplateFormatVersion: 2010-09-09
Description: ""
Parameters:
PjName:
Type: String
Env:
Type: String
TargetUrl:
Type: String
Resources:
CloudWatchSyntheticsCanary:
Type: AWS::Synthetics::Canary
Properties:
ArtifactS3Location: !Sub s3://${S3BucketCwsynResult}
Code:
Handler: pageLoadBlueprint.handler
Script: !Sub
- |
from selenium.webdriver.common.by import By
from aws_synthetics.selenium import synthetics_webdriver as syn_webdriver
from aws_synthetics.common import synthetics_logger as logger
def main():
url = "${TargetUrl}"
# Set screenshot option
takeScreenshot = True
browser = syn_webdriver.Chrome() # Chromeを操作するドライバー
browser.get(url) # URLを開く
if takeScreenshot:
browser.save_screenshot("loaded.png") # スクリーンショットを取得してファイルに保存
response_code = syn_webdriver.get_http_response(url) # URLにアクセスしてステータスコードを取得
if not response_code or response_code < 200 or response_code > 299:
raise Exception("Failed to load page!")
logger.info("Canary successfully executed.")
def handler(event, context):
# user defined log statements using synthetics_logger
logger.info("Selenium Python heartbeat canary.")
return main()
- {
TargetUrl: !Ref TargetUrl
}
ExecutionRoleArn: !GetAtt CwsynExecutionRole.Arn
FailureRetentionPeriod: 31
Name: !Sub ${PjName}-cwsyn-${Env}
RuntimeVersion: syn-python-selenium-4.1
Schedule:
DurationInSeconds: 0
Expression: rate(5 minutes)
StartCanaryAfterCreation: true
SuccessRetentionPeriod: 31
Tags:
- Key: Name
Value: !Sub ${PjName}-cwsyn-${Env}
S3BucketCwsynResult:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- BucketKeyEnabled: true
ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
BucketName: !Sub ${PjName}-s3-bucket-cwsyn-result-${Env}
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
Tags:
- Value: Name
Key: !Sub ${PjName}-s3-bucket-cwsyn-result-${Env}
CwsynExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: /service-role/
RoleName: !Sub ${PjName}-iamrole-cwsyn-execution-${Env}
Tags:
- Key: Name
Value: !Sub ${PjName}-iamrole-cwsyn-execution-${Env}
CwsynExecutionPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: !Sub ${PjName}-iampolicy-cwsyn-execution-${Env}
Roles:
- !Ref CwsynExecutionRole
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
Resource:
- !Sub ${S3BucketCwsynResult.Arn}/*
- Effect: Allow
Action:
- s3:GetBucketLocation
Resource:
- !Sub ${S3BucketCwsynResult.Arn}
- Effect: Allow
Action:
- logs:CreateLogStream
- logs:PutLogEvents
- logs:CreateLogGroup
Resource:
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/cwsyn-*
- Effect: Allow
Action:
- s3:ListAllMyBuckets
- xray:PutTraceSegments
Resource:
- '*'
- Effect: Allow
Resource: '*'
Action: cloudwatch:PutMetricData
Condition:
StringEquals:
cloudwatch:namespace: CloudWatchSynthetics
Canaryの実行結果
- 「Synthetics Canaryの概要」を確認→5分ごとに実行され、すべて「成功」しています。
- Canaryを確認→スクリーンショットが正常に取得されています。
疑問点
-
そもそも「Selenium」とは?
- WEBブラウザを操作するためのPython/Node.jsのライブラリ
- 標準インストールされていないため別途インストールが必要
- Lambdaで使う場合はレイヤーとして配置
- 最新バージョンは4.26.1→PyPI Selenium
-
2つのレイヤーの役割は?
- arn:aws:lambda:ap-northeast-1:172291836251:layer:Synthetics_Selenium:41
- 本レイヤーがPythonの外部ライブラリであるSelenium本体
- PyPIで提供されているものと異なり、AWSによりカスタマイズされている
- 下記サイトにARNの記載あり
- arn:aws:lambda:ap-northeast-1:${AccountId}:layer:cwsyn-zenn-cwsyn-dev-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX:2
- ブループリントのPythonプログラム(ローカルにダウンロードして中身を確認)。
- 独自のモニタリングを行いたい場合はここに実装する。
- arn:aws:lambda:ap-northeast-1:172291836251:layer:Synthetics_Selenium:41
-
Canary Lambdaに渡されるeventの中身は?
- 気になったのでログ出力させました。
{ "canaryName": "zenn-cwsyn-dev", "s3BaseFilePath": "${バケット名}", "customerCanaryHandlerName": "pageLoadBlueprint.handler", "customerCanaryCodeLocation": "arn:aws:lambda:${AWS::Region}:XXXXXXXXXXXX:layer:cwsyn-zenn-cwsyn-dev-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX:1", "invocationTime": 1732352615487, "runtimeVersion": "syn-python-selenium-4.1", "activeTracing": false, "canaryRunId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "artifactS3Location": { "s3Bucket": "${バケット名}", "s3Key": "canary/${AWS::Region}/zenn-cwsyn-dev/yyyy/mm/dd/hh/mm-ss-sss" }, "canaryRunStartTime": 1732352624558 }
- 気になったのでログ出力させました。
-
AWSのリソースを監視対象にする際、Canary LambdaをVPCLambdaにすることも可能だが...
今回はAWS Cloud外部にホストされているサービスを監視対象にしました。AWSに構築したサービスを監視対象とする場合はどんな構成になるでしょうか。
オーソドックスな構成として、プライベートサブネットにWebサーバ、前段のパブリックサブネットにALBを配置するとします。ユーザ→ALB→Webサーバとなるので、ALBに割り当てられたURLを監視対象とすれば、ユーザ視点のモニタリングができそうです。
一方、プライベートサブネットにCanary Lambda(VPCLambda)を配置し、VPCLambda→Webサーバ、もしくはVPCLambda→ALBという構成も可能です。ユーザとWebサーバの間には大抵WAF、ALB、SGなどが配置されるため、これではネットワークの設定不備・障害を発見できない恐れがあります。
あくまでも、外形監視はユーザ視点であるかが大切なポイントです。※VPCLambdaにする必要はない。
さいごに
今回はCloudWatch Syntheticsで外形監視を行いました。
URLにアクセス後、IDとパスワードを入力しログインする、といった処理も実装次第で可能らしいです。作り込みはまたの機会に。( 。。•ᴗ• )੭⁾⁾
今後Google Cloudの資格に挑戦する予定なので、それに関連した記事も書いていこうと思います。
Discussion