目次
全般
AWS公式のハンズオンをやってみたという内容です。
CloudFormationを使用してEC2(WordPress),RDS,ALBを構築した後、CloudWatch、SNSを使用してアラートを通知する構成を構築します。
参考サイト
Amazon CloudWatchの概要と基本 AWS Black Belt
構成
CloudWatchエージェント、WordPressをEC2にインストールします。
CloudFormation
AWS公式が作成したコードを使用して環境を構築します。
ファイルをサイトからダウンロードして少し編集してスタックを更新していきます。
※RDSのインスタンスクラスを「db.t2.micro」から「db.t3.micro」へ編集します。
AWSTemplateFormatVersion: "2010-09-09"
Description: AWS Hands-on for Beginners monitoing-1 template
Parameters:
EC2InstanceType:
Type: String
Default: t2.micro
EC2AMI:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
RDSInstanceType:
Type: String
Default: db.t3.micro
DBUser:
Type: String
Default: dbmaster
DBPassword:
Type: String
Default: H&ppyHands0n
NoEcho: true
Resources:
CFnVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
InstanceTenancy: default
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-vpc
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.0.0/24
VpcId: !Ref CFnVPC
AvailabilityZone: !Select [0, !GetAZs ]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: PublicSubnet1
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.1.0/24
VpcId: !Ref CFnVPC
AvailabilityZone: !Select [1, !GetAZs ]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: PublicSubnet2
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.2.0/24
VpcId: !Ref CFnVPC
AvailabilityZone: !Select [0, !GetAZs ]
Tags:
- Key: Name
Value: PrivateSubnet1
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.3.0/24
VpcId: !Ref CFnVPC
AvailabilityZone: !Select [1, !GetAZs ]
Tags:
- Key: Name
Value: PrivateSubnet2
CFnVPCIGW:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-igw
CFnVPCIGWAttach:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref CFnVPCIGW
VpcId: !Ref CFnVPC
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref CFnVPC
Tags:
- Key: Name
Value: Public Route
PublicRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref CFnVPCIGW
PublicSubnet1Assoc:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicSubnet2Assoc:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
EC2WebServer01:
Type: AWS::EC2::Instance
Properties:
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-WebServer01
ImageId: !Ref EC2AMI
InstanceType: !Ref EC2InstanceType
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: '0'
SubnetId: !Ref PublicSubnet1
GroupSet:
- !Ref SecurityGroupWebServer
UserData: !Base64 |
#! /bin/bash
yum update -y
amazon-linux-extras install php7.2 -y
yum -y install mysql httpd php-mbstring php-xml
wget http://ja.wordpress.org/latest-ja.tar.gz -P /tmp/
tar zxvf /tmp/latest-ja.tar.gz -C /tmp
cp -r /tmp/wordpress/* /var/www/html/
touch /var/www/html/.check_alive
chown apache:apache -R /var/www/html
systemctl enable httpd.service
systemctl start httpd.service
wget https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm -P /tmp/
sudo rpm -U /tmp/amazon-cloudwatch-agent.rpm
mv /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/default /home/ec2-user/
wget https://raw.githubusercontent.com/nikuyoshi/aws-monitoring-hands-on-1/master/amazon-cloudwatch-agent.json -P /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/
sudo systemctl restart amazon-cloudwatch-agent
IamInstanceProfile: !Ref IAMInstanceProfile
DependsOn: IAMInstanceProfile
EC2WebServer02:
Type: AWS::EC2::Instance
Properties:
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-WebServer02
ImageId: !Ref EC2AMI
InstanceType: !Ref EC2InstanceType
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: '0'
SubnetId: !Ref PublicSubnet2
GroupSet:
- !Ref SecurityGroupWebServer
UserData: !Base64 |
#! /bin/bash
yum update -y
amazon-linux-extras install php7.2 -y
yum -y install mysql httpd php-mbstring php-xml
wget http://ja.wordpress.org/latest-ja.tar.gz -P /tmp/
tar zxvf /tmp/latest-ja.tar.gz -C /tmp
cp -r /tmp/wordpress/* /var/www/html/
touch /var/www/html/.check_alive
chown apache:apache -R /var/www/html
systemctl enable httpd.service
systemctl start httpd.service
wget https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm -P /tmp/
sudo rpm -U /tmp/amazon-cloudwatch-agent.rpm
mv /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/default /home/ec2-user/
wget https://raw.githubusercontent.com/nikuyoshi/aws-monitoring-hands-on-1/master/amazon-cloudwatch-agent.json -P /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/
sudo systemctl restart amazon-cloudwatch-agent
IamInstanceProfile: !Ref IAMInstanceProfile
DependsOn: IAMInstanceProfile
SecurityGroupWebServer:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref CFnVPC
GroupName: !Sub ${AWS::StackName}-WebServer
GroupDescription: !Sub ${AWS::StackName}-WebServer
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-WebServer
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Monitoring1EC2RoleforSSM:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: 'sts:AssumeRole'
Effect: Allow
Principal:
Service: ec2.amazonaws.com
Description: Allows EC2 instances to call AWS services on your behalf.
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
- arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
MaxSessionDuration: 3600
Path: "/"
RoleName: Monitoring1EC2RoleforSSM
IAMInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles: [ !Ref Monitoring1EC2RoleforSSM ]
Path: "/"
FrontLB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub ${AWS::StackName}-elb
Subnets:
- !Ref PublicSubnet1
- !Ref PublicSubnet2
SecurityGroups:
- !Ref SecurityGroupLB
FrontLBListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref FrontLB
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref FrontLBTargetGroup
FrontLBTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub ${AWS::StackName}-tg
VpcId: !Ref CFnVPC
Port: 80
Protocol: HTTP
HealthCheckPath: /.check_alive
Targets:
- Id: !Ref EC2WebServer01
- Id: !Ref EC2WebServer02
SecurityGroupLB:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref CFnVPC
GroupName: !Sub ${AWS::StackName}-lb-security-group
GroupDescription: !Sub ${AWS::StackName}-lb-security-group
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-lb-security-group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
DBInstance:
Type: AWS::RDS::DBInstance
DeletionPolicy: Delete
Properties:
DBInstanceIdentifier: !Sub ${AWS::StackName}-rds
DBName: wordpress
Engine: MySQL
MasterUsername: !Ref DBUser
MasterUserPassword: !Ref DBPassword
DBInstanceClass: !Ref RDSInstanceType
StorageType: gp2
AllocatedStorage: '20'
BackupRetentionPeriod: 0
DBSubnetGroupName: !Ref DBSubnetGroup
MultiAZ: true
VPCSecurityGroups:
- !Ref SecurityGroupDB
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: DB Subnet Group for Private Subnet
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
SecurityGroupDB:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref CFnVPC
GroupName: !Sub ${AWS::StackName}-MySQL
GroupDescription: !Sub ${AWS::StackName}-MySQL
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-MySQL
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
CidrIp: 10.0.0.0/16
Outputs:
VPCID:
Description: VPC ID
Value: !Ref CFnVPC
PublicSubnet1:
Description: PublicSubnet 1
Value: !Ref PublicSubnet1
PublicSubnet2:
Description: PublicSubnet 2
Value: !Ref PublicSubnet2
PrivateSubnet1:
Description: PrivateSubnet 1
Value: !Ref PrivateSubnet1
PrivateSubnet2:
Description: PrivateSubnet 2
Value: !Ref PrivateSubnet2
EC2WebServer01:
Value: !Ref EC2WebServer01
EC2WebServer01DNS:
Value: !GetAtt EC2WebServer01.PublicDnsName
EC2WebServer02:
Value: !Ref EC2WebServer02
EC2WebServer02DNS:
Value: !GetAtt EC2WebServer02.PublicDnsName
FrontLBEndpoint:
Value: !GetAtt FrontLB.DNSName
RDSEndpointAddress:
Value: !GetAtt DBInstance.Endpoint.Address
スタックを作成するためファイルをアップロードします。
任意にスタック名を決め、パラメータは表示されたもののまま進めます。
あとはデフォルトでスタックを作成しましょう。
作成完了まで10分ほど待ちます。
ここでCloudWatchの構成を改めて確認します。
SNSを使用して通知を飛ばしたいと考えています。
インストールしたWordPressを開きます。
CloudFormationの画面の出力タブから、webサーバー2台のDNS名からWordPressに接続していきます。
(ハンズオンに従って設定します。)
データベース名:wordpress
ユーザー名:dbmaster
パスワード:H&ppyHands0n
データベースのホスト名:データベースのエンドポイント
サイトのタイトル: Monitoring #1
ユーザー名: admin
パスワード: 出力された文字列をコピーしておきましょう。
メールアドレス: username@example.com
検索エンジンでの表示: チェックを入れる。
事象に応じた対応
・サーバーが過負荷状態
・サービスが使えない。
⇒リソース監視(CPU、メモリ使用率を確認)
メトリクスを見る場合は、リージョン毎に管理されたメトリクスの各インスタンス(ディメンション)にアクセスして確認していきます。
今回はエージェントをインストールしているので確認できる。
CloudWatch Metrics
CloudWatch⇒メトリクス⇒すべてのメトリクス⇒EC2
CPUを検索窓から検索
タイムゾーンを設定できます。
ネットワークのIN,OUTを見てみる。
CloudWatch⇒メトリクス⇒すべてのメトリクス⇒ELB⇒AppELB 別、TG 別メトリクス
CloudWatch⇒メトリクス⇒すべてのメトリクス⇒RDS⇒ADBInstanceIdentifier
読み書きをチェック
RDSはデフォルトで1分間隔でデータを取得
オプションから数値で見ることもできる。
CloudWatch⇒メトリクス⇒すべてのメトリクス⇒CWAgent⇒ImageId,InstanceId,InstanceType,device,fstype,path
ディスクの使用率を確認することができる。
CloudWatch⇒メトリクス⇒すべてのメトリクス⇒CWAgent⇒ImageId,InstanceId,InstanceType
メモリの使用率を確認することができる。
CloudWatch Alarm
ここでできるアクション例
- SNSで通知
- Server再起動や停止
- Auto Scaling
- Lambdaでコードを実行
今回はSNSで通知を送るためアラームを作成します。
「ディスク使用率90%を超えた場合」に通知を送る設定を行う。
メトリクスの選択
CWAgent⇒ImageId,InstanceId,InstanceType,device,fstype,path⇒
disk_used_percent
メトリクスの選択をクリック
ここで細部アラームの発報基準を決めていく。
今回は「静的」を選択して90%以上を示した時に発報。「異常検知」を選択した場合、これまでの履歴によって、ある基準を検知した時に発報するような設定にもできる。
次のような振る舞いもあるようです。
しきい値を超えた時にSNSトピックによってメールが欲しいので、設定していきます。
これでトピックの作成をクリック。
SNSのセットアップ用のメールが届きました。このリンクを踏んで設定を完了させます。
ここでLambda、EC2の振る舞いを決めることができるようです。
CloudWatch Logs
多くの台数を管理する際に1台1台確認するのは非効率であるため、ログを集約する機能を使用する。
ロググループを確認するとCloudFormationで作成されたロググループが表示され、ログの保持期間を設定できる。
デフォルトは失効しない。となっているので変更する。
作成されたロググループのaccessログを確認すると次の画面になり、文字列で検索する機能が存在する。
検索条件も「カスタム」から設定可能です。
CloudFormation内でwgetツールを使用し、S3から設定ファイルをダウンロードしますが、今回はカスタムのAmazon CloudWatch Agent設定ファイルを使用しています(CFnのコード内に記載済み。)。
次は参考としてウィザードを表示してエージェントを設定するドキュメントです。
CloudWatch エージェント設定ファイルを作成
CloudWatch Logs Insights
ログ分析エラーの根本原因を知るためにログをパース(非構造化データから特定の情報を抽出する)したりや、エラー発生時刻を調べたりなど、クエリを実行して、限定して表示させる。
「ログのインサイト」をクリックして試してみる。
どうやらこのリンクにクエリについて解説されているようです。
Amazon CloudWatch | Amazon Web Services(YouTube)
know-howの欠片が落ちています。。
CloudWatch Logs Insights クエリ構文
parseしてみる。まずは公式が示すクエリを実行
parse '* - * [*] "* * *" * *' as host, identity, dateTimeString, httpVerb, url, protocol, statusCode, bytes
| stats max(bytes) as maxBytes, avg(bytes) by url
| sort maxBytes desc
解説者が示すknow-howたっぷりのクエリを実行してみる。
parse '* - * [*] "* * *" * *' as host, identity, dateTimeString, httpVerb, url, protocol, statusCode, bytes
| sort maxBytes desc
分析したくなるような見た目になりました!!
次にここからHTTPのstatusCodeが400番台のレコードを確認していきます。
parse '* - * [*] "* * *" * *' as host, identity, dateTimeString, httpVerb, url, protocol, statusCode, bytes
| filter statusCode like /(4\d\d)/
CloudWatch Dashboards
横断的にステータスを確認できる。
サービスのメトリクスをまとめて一個の画面に表示できる。
EC2のCPU使用率を表示させるために「線」を選択
両方のEC2を追加する。
次はテキストで非常時のショートカットボタンを作成できる。
WordPressのaccesslogを表示する。
例えばエラー抽出する設定、また500番台を抽出する設定にしたログを表示するなどできる。
ダッシュボードの保存をクリックして完成。
自動で作成するダッシュボードも存在する。
次のサービスを検索する。
「AWS Resource Groups」
リソースグループを「タグベース」か「CloudFormation」で選択できる。
今回はCloudFormationで作成しているので、CloudFormationを選択
CloudWatch画面に戻り、サイドバーのCloudWatchボタンをクリックし、EC2を例にリソースグループで絞って表示させてみます。
CloudWatchボタン⇒概要⇒サービスダッシュボード⇒EC2⇒作成したリソースグループを選択
RDS
その他、様々な表示条件によって任意にカスタムできます。
サービス間ダッシュボードにし、リソースグループで限定すると、EC2とRDSがサービスの垣根を越えて表示させることができます。
次にすべてのサービスを表示させたい場合は、リソースグループを指定せず、サービス間ダッシュボードを選択することで、ELBやSNSなども一緒に表示させることができます。
EventBridge(CloudWatch Events)
起きた事象に応じて、トリガー役として機能。
イベントを収集し、Lambda関数、Step Functions、SQSキュー、SNSトピック、Kinesisストリームなどのターゲットにルーティングして動かすことが可能。
Cronのように定時実行設定も可能
今回はEC2が停止した場合、SNS通知を飛ばす設定にする。
EC2の状態変化があった場合を想定
aws.ec2@EC2InstanceStateChangeNotificationを選択
これでルールができたので、EC2を停止させ、通知が来るか確認します。
通知が問題なく来ていることが確認できました!
ここまででハンズオンは終了です。
後片付け
- CloudFormationのスタックを削除
- CloudWatch Dashboardsを削除
- CloudWatch Alarmを削除
- CloudWatch Logsを削除
- EventBridge(CloudWatch Events)を削除
- SNSトピックを削除
- S3バケットを削除
- Resource Groups
お疲れ様でした!
では!
1つずつ誠実に取り組み、技術を身に着けて発信も併せて行っていきます!