Amazon CloudWatch SyntheticsでVPC内にあるエンドポイントを監視する機会があったのでブログに残します。
環境
今回はCloudWatch Syntheticsを使用してプライベートサブネット内にあるEC2 (Webサーバー) を監視します。
以下のドキュメントに記載されている通りVPC内でCanaryを実行するにはインターネットアクセスもしくはVPC エンドポイントが必要となるのでCloudWatchのVPCエンドポイントとS3のVPCエンドポイントを作成します。
VPC で Canary を実行する
- 構成図は今回メインとなる部分を抜粋して記載しています。
- EC2への接続はSession Managerを使用するのでインターフェイス型VPCエンドポイントを作成します。
設定
CloudWatch Synthetics以外の部分は全てCloudFormationで作成します。
作成は以下のCloudFormationテンプレートで行います。
CloudFormationテンプレート (ここをクリックしてください)
AWSTemplateFormatVersion: "2010-09-09"
Description: Test Stack
Parameters:
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
VPCCIDR:
Default: 192.168.0.0/16
Type: String
PrivateSubnet01CIDR:
Default: 192.168.0.0/24
Type: String
EC2VolumeSize:
Default: 32
Type: Number
EC2VolumeIOPS:
Default: 3000
Type: Number
EC2AMI:
Default: ami-06fdbb60c8e83aa5e
Type: AWS::EC2::Image::Id
EC2InstanceType:
Default: t3.micro
Type: String
Resources:
# ------------------------------------------------------------#
# VPC
# ------------------------------------------------------------#
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCIDR
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: test-vpc
# ------------------------------------------------------------#
# Subnet
# ------------------------------------------------------------#
PrivateSubnet01:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
CidrBlock: !Ref PrivateSubnet01CIDR
Tags:
- Key: Name
Value: test-subnet-private-1a
VpcId: !Ref VPC
# ------------------------------------------------------------#
# RouteTable
# ------------------------------------------------------------#
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: test-private-rtb
PrivateRtAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable
SubnetId: !Ref PrivateSubnet01
# ------------------------------------------------------------#
# Security Group
# ------------------------------------------------------------#
EC2SG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: for EC2
GroupName: test-sg-ec2
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
FromPort: -1
IpProtocol: -1
ToPort: -1
SecurityGroupIngress:
- CidrIp: 192.168.0.0/16
FromPort: 80
IpProtocol: tcp
ToPort: 80
Tags:
- Key: Name
Value: test-sg-ec2
VpcId: !Ref VPC
VPCEndpointSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: for VPC Endpoint
GroupName: test-sg-vpc-endpoint
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
FromPort: -1
IpProtocol: -1
ToPort: -1
SecurityGroupIngress:
- CidrIp: 192.168.0.0/16
FromPort: 443
IpProtocol: tcp
ToPort: 443
Tags:
- Key: Name
Value: test-sg-vpc-endpoint
VpcId: !Ref VPC
CloudWatchSyntheticsSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: for CloudWatch Synthetics
GroupName: test-sg-cloudWatch-synthetics
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
FromPort: -1
IpProtocol: -1
ToPort: -1
Tags:
- Key: Name
Value: test-sg-cloudWatch-synthetics
VpcId: !Ref VPC
# ------------------------------------------------------------#
# IAM
# ------------------------------------------------------------#
EC2IAMPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "s3:GetObject"
Resource:
- !Join
- ''
- - 'arn:aws:s3:::amazonlinux.'
- !Sub ${AWS::Region}
- '.amazonaws.com/*'
- !Join
- ''
- - 'arn:aws:s3:::amazonlinux-2-repos-'
- !Sub ${AWS::Region}
- '/*'
ManagedPolicyName: test-iam-policy-ec2
EC2IAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
- !Ref EC2IAMPolicy
RoleName: test-iam-role-ec2
Tags:
- Key: Name
Value: test-iam-role-ec2
EC2IAMInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
InstanceProfileName: test-iam-instanceprofile-ec2
Roles:
- !Ref EC2IAMRole
# ------------------------------------------------------------#
# EC2
# ------------------------------------------------------------#
EC2:
Type: AWS::EC2::Instance
Properties:
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
DeleteOnTermination: true
Encrypted: true
Iops: !Ref EC2VolumeIOPS
VolumeSize: !Ref EC2VolumeSize
VolumeType: gp3
DisableApiTermination: false
IamInstanceProfile: !Ref EC2IAMInstanceProfile
ImageId: !Ref EC2AMI
InstanceType: !Ref EC2InstanceType
NetworkInterfaces:
- DeleteOnTermination: true
DeviceIndex: 0
GroupSet:
- !Ref EC2SG
SubnetId: !Ref PrivateSubnet01
Tags:
- Key: Name
Value: test-ec2
UserData: !Base64 |
#!/bin/bash
yum update -y
yum install httpd -y
systemctl start httpd
systemctl enable httpd
echo "CloudWatch Synthetics Test" > /var/www/html/index.html
# ------------------------------------------------------------#
# VPC Endpoint
# ------------------------------------------------------------#
S3Endpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
RouteTableIds:
- !Ref PrivateRouteTable
ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
VpcEndpointType: Gateway
VpcId: !Ref VPC
SystemsManagerEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcEndpointType: Interface
PrivateDnsEnabled: true
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm
VpcId: !Ref VPC
SubnetIds:
- !Ref PrivateSubnet01
SecurityGroupIds:
- !Ref VPCEndpointSG
SystemsManagerMessageEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcEndpointType: Interface
PrivateDnsEnabled: true
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages
VpcId: !Ref VPC
SubnetIds:
- !Ref PrivateSubnet01
SecurityGroupIds:
- !Ref VPCEndpointSG
CloudWatchEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcEndpointType: Interface
PrivateDnsEnabled: true
ServiceName: !Sub com.amazonaws.${AWS::Region}.monitoring
VpcId: !Ref VPC
SubnetIds:
- !Ref PrivateSubnet01
SecurityGroupIds:
- !Ref VPCEndpointSG
上記のCloudFormationテンプレートで監視対象のEC2やVPCエンドポイントなどCloudWatch Synthetics以外のリソースが作成されます。
デプロイは以下のコマンドを実行します。
aws cloudformation create-stack --stack-name CloudFormationスタック名 --template-body file://CloudFormationテンプレートファイル名 --capabilities CAPABILITY_NAMED_IAM
リソースの作成が完了したらマネジメントコンソールからCloudWatchのダッシュボードへ移動します。
移動したら画面左の項目から「Synthetics Canaries」をクリックします。
画面が遷移したら「Canaryを作成」をクリックします。
画面が遷移したら設定を行っていきます。
まずは監視スクリプトどのように準備するかの設定です。
今回はAWSの準備したテンプレートを使用するので「設計図を使用する」を選択しています。
監視対象は通常のWebページなので「ハートビートのモニタリング」を選択します。
次に監視するエンドポイントの設定を行います。
「アプリケーションまたはエンドポイント URL」にCloudFormationで作成したEC2のプライベートIPアドレスを設定します。
次の項目で「スクリプトエディタ」が編集できますが今回はデフォルトで設定します。
カスタムしたい場合は以下の公式ドキュメントを参考にしてください。
Canary スクリプトの作成
次の項目で「スケジュール」と「データ保持」の設定が行えます。
「スケジュール」は監視間隔の設定を行う項目です。
「データ保持」は監視を行った際の実行データの保持設定です。
今回はデフォルトで設定します。
次の項目で「データストレージ」と「アクセス許可」の設定が行えます。
「データストレージ」は実行データの保存先S3の設定になります。
「アクセス許可」ではS3にデータを保存したりするのに使用する権限がアタッチされたIAMロールを設定します。
今回は自動で作成されるものを使用していきます。
次の項目で「CloudWatch アラーム」と「VPC」の設定が行えます。
「CloudWatch アラーム」は監視でエラーになった際に通知などが行えますが、今回は設定しません。
「VPC」については、VPC内のエンドポイントを監視するので設定を行っていきます。
「Virtual Private Cloud (VPC)」と「サブネット」でCloudFormationで作成されたVPCを選択します。
「セキュリティグループ」は「for CloudWatch Synthetics」と記載されているものがCloudWatch Synthetics用に作成したものなので選択します。
次の項目で「タグ」、「アクティブトレース」の設定が行えます。
今回は設定を行う必要が無いのでデフォルトのままにします。
全ての設定が完了したら画面下の「Canaryを作成」をクリックします。
作成完了後、しばらく待つと監視が実行されます。
名前の部分をクリックすると実行時のログや画面のスクリーンショットが確認できます。
Webサーバーのアクセスログを確認すると5分おきに監視が行われていることが確認できます。
192.168.0.xx - - [28/Mar/2023:14:58:55 +0000] "GET / HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/92.0.4512.0 Safari/537.36 CloudWatchSynthetics/arn:aws:synthetics:ap-northeast-1:xxxxxxxxx:canary:test-page"
192.168.0.xx - - [28/Mar/2023:15:03:32 +0000] "GET / HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/92.0.4512.0 Safari/537.36 CloudWatchSynthetics/arn:aws:synthetics:ap-northeast-1:xxxxxxxxx:canary:test-page"
192.168.0.xx - - [28/Mar/2023:15:08:32 +0000] "GET / HTTP/1.1" 200 27 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/92.0.4512.0 Safari/537.36 CloudWatchSynthetics/arn:aws:synthetics:ap-northeast-1:xxxxxxxxx:canary:test-page"
さいごに
外部に公開していないエンドポイントについても監視できることは今回初めて知りました。
CloudWatch SyntheticsではAPIの監視なども行えるので、内部向けAPI監視に使えるのは便利だなと思いました。