もくじ
Serverlessフレームワークを利用して
- Lambdaアプリケーション, Lambda関数の作成
- SNSの作成 + SNSとLambda関数との連携
- 上記のデプロイ
これが出来ます。
通知の流れ
- Cloudwatch Alarm → SNS → Lambda → Chatwork
動作
- Cloudwatch Alarmで設定したメトリクスに対して、警告時にSNSトピックスに通知する
- SNSはLambdaを叩く
- LambdaはChatwork APIを通してルームIDを指定したルームに投稿
クライアント側の作業をします
# python --version Python 2.7.14
Python3のインストール
$ sudo yum install python3 Installed: python3.x86_64 0:3.7.3-1.amzn2.0.1 Dependency Installed: python3-libs.x86_64 0:3.7.3-1.amzn2.0.1 python3-pip.noarch 0:9.0.3-1.amzn2.0.1 python3-setuptools.noarch 0:38.4.0-3.amzn2.0.6 Complete!
バージョンの確認
$ python3 --version Python 3.7.3
Python 3.7を確認
AWS CLI
AWS CLIのインストール
# curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" # python get-pip.py # pip install awscli
設定を行います
# aws configure AWS Access Key ID [None]: xxxxxxxxxxxxx AWS Secret Access Key [None]: xxxxxxxxxxxxxxxxxxxx Default region name [None]: ap-northeast-1 Default output format [None]: json
設定の確認
# aws configure list Name Value Type Location ---- ----- ---- -------- profile <not set> None None access_key ****************7BIA shared-credentials-file secret_key ****************bA4M shared-credentials-file region ap-northeast-1 config-file ~/.aws/config
Node.js
$ sudo su - # yum -y install gcc-c++ git # git clone https://github.com/creationix/nvm.git ~/.nvm
パスを通す
# source ~/.nvm/nvm.sh
$ nvm ls-remote mkdir: cannot create directory ‘/home/ec2-user/.nvm/alias’: Permission denied mkdir: cannot create directory ‘/home/ec2-user/.nvm/alias’: Permission denied v0.1.14 v0.1.15 v0.1.16 v0.1.17
$ nvm install v8.10.0 Downloading and installing node v8.10.0... Downloading https://nodejs.org/dist/v8.10.0/node-v8.10.0-linux-x64.tar.xz... ######################################################################################################################## 100.0% Computing checksum with sha256sum Checksums matched! Now using node v8.10.0 (npm v5.6.0) Creating default alias: default -> v8.10.0
バージョンの確認
# node -v v8.10.0
ローカルでLambdaスクリプト実行する為のライブラリ # pip install python-lambda-local デプロイテストで利用するライブラリ # pip install python-levenshtein
Serverlessフレームワーク
インストール
# npm install -g serverless
Serverlessフレームワークのテストをします。
# sls create -t aws-python -p slstest Serverless: Generating boilerplate... Serverless: Generating boilerplate in "/root/slstest" _______ __ | _ .-----.----.--.--.-----.----| .-----.-----.-----. | |___| -__| _| | | -__| _| | -__|__ --|__ --| |____ |_____|__| \___/|_____|__| |__|_____|_____|_____| | | | The Serverless Application Framework | | serverless.com, v1.44.1 -------' Serverless: Successfully generated boilerplate for template: "aws-python"
デプロイ
# sls deploy
helloファンクションの実行
# sls invoke -f hello { "body": "{\"input\": {}, \"message\": \"Go Serverless v1.0! Your function executed successfully!\"}", "statusCode": 200 }
ヴァージニアリージョンにアクセスするとLambda関数がセットされており、Serverlessフレームワークできちんとデプロイできていることがわかります。
Chatwork通知用の関数を作成
@see https://dev.classmethod.jp/server-side/sls-lambda-chatwork/
クラスメソッドさんが既に作ってあるのでこれを頂きます。
# sls create -t aws-python3 -p chatwork-cloudwatch Serverless: Generating boilerplate... Serverless: Generating boilerplate in "/root/chatwork-cloudwatch" _______ __ | _ .-----.----.--.--.-----.----| .-----.-----.-----. | |___| -__| _| | | -__| _| | -__|__ --|__ --| |____ |_____|__| \___/|_____|__| |__|_____|_____|_____| | | | The Serverless Application Framework | | serverless.com, v1.44.1 -------' Serverless: Successfully generated boilerplate for template: "aws-python3"
必要なライブラリ「serverless-python-requirements」をインストール
# cd chatwork-cloudwatch # npm install --save serverless-python-requirements
コンフィデンシャル設定
# vi ~/.aws/credentials [default] aws_access_key_id=xxxxxxxxxxxxxxxxx aws_secret_access_key=xxxxxxxxxxxxxxxxxxxx output = json region = ap-northeast-1
IAMユーザでAdminfullAccessのポリシーのユーザを指定しています。
全体の設定
# vi serverless.yml service: chatwork-cloudwatch provider: name: aws runtime: python3.7 #←●Pythonのバージョンを合わせること region: ap-northeast-1 profile: default #←●参照するコンフィデンシャルのプロフィール名 environment: CHATWORK_API_KEY: xxxxxxxxxxxxxxxxxxxx #←●Chatwork API Keyを指定 CHATWORK_HEADER: X-ChatWorkToken CHATWORK_ROOM_ID: xxxxxxxxx #←●ChatworkルームIDを指定 CHATWORK_URL: https://api.chatwork.com/v2 plugins: - serverless-python-requirements functions: dispatcher: # file_name handler: dispatcher.dispatch #←●ハンドラ名.関数 events: - sns: sls-cloudwatch #←●作成するSNSトピック名を指定
# vi dispatcher.py import json import logging import requirements import requests import urllib import os logger = logging.getLogger() logger.setLevel(logging.INFO) message_header = "============ Alart ===========\n" def dispatch(event, context): logger.info("Event: " + str(event)) message = json.loads(event['Records'][0]['Sns']['Message']) logger.info("Message: " + str(message)) # 環境変数から情報取得 CHATWORK_API_KEY = os.environ['CHATWORK_API_KEY'] CHATWORK_HEADER = os.environ['CHATWORK_HEADER'] CHATWORK_ROOM_ID = os.environ['CHATWORK_ROOM_ID'] CHATWORK_URL = os.environ['CHATWORK_URL'] # Chatwork APIを利用するためのURL URL = '{0}/rooms/{1}/messages'.format(CHATWORK_URL,CHATWORK_ROOM_ID) # メッセージ取得 chatwork_message = get_cloudwatch_message(message) payload = {'body': chatwork_message} headers = {CHATWORK_HEADER: CHATWORK_API_KEY} try: # Chatworkに投稿 requests.post(URL, headers=headers, params=payload) except: logger.info("Failed! Message : \n" + str(chatwork_message)) else: logger.info("Success! Message posted to: \n" + str(chatwork_message)) def get_cloudwatch_message(data): logger.info("get data: " + str(data)) # 渡ってきたデータからほしい情報を抽出 alarm_name = data['AlarmName'] new_state = data['NewStateValue'] reason = data['NewStateReason'] metric_name = data['Trigger']['MetricName'] target_name = data['Trigger']['Dimensions'][0]['name'] target_value = data['Trigger']['Dimensions'][0]['value'] # Chatworkに投稿したいメッセージ chatwork_message = '{0}\n\ アラーム名:{1} \n\ new_state:{2} \n\ reason:{3} \n\ metric_name - {4} \n\ target_name - {5} \n\ target_value - {6}'.format(message_header,alarm_name,new_state,reason,metric_name,target_name,target_value) return chatwork_message
※Chatworkにrequestライブラリで送るのに必要なコード
import requests payload = {'body': '<メッセージ>'} headers = {'X-ChatWorkToken': 'YOUR CHATWORK TOKEN'} requests.post('https://api.chatwork.com/v1/rooms/****/messages', headers=headers, params=payload)
必要なライブラリを記述します
# vi requirements.txt requests
# vi requirements.py import os import sys requirements = os.path.join( os.path.split(__file__)[0], '.requirements', ) if requirements not in sys.path: sys.path.append(requirements)
デプロイ
# sls deploy -v Serverless: Generated requirements from /root/chatwork-cloudwatch/requirements.txt in /root/chatwork-cloudwatch/.serverless/requirements.txt... Serverless: Installing requirements from /root/chatwork-cloudwatch/.serverless/requirements/requirements.txt ... Serverless: Running ... Serverless: Packaging service... Serverless: Excluding development dependencies... Serverless: Injecting required Python packages to package... Serverless: Creating Stack... Serverless: Checking Stack create progress... CloudFormation - CREATE_IN_PROGRESS - AWS::CloudFormation::Stack - chatwork-cloudwatch-dev CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket CloudFormation - CREATE_COMPLETE - AWS::S3::Bucket - ServerlessDeploymentBucket CloudFormation - CREATE_COMPLETE - AWS::CloudFormation::Stack - chatwork-cloudwatch-dev Serverless: Stack create finished... Serverless: Uploading CloudFormation file to S3... Serverless: Uploading artifacts... Serverless: Uploading service chatwork-cloudwatch.zip file to S3 (1.95 MB)... Serverless: Validating template... Serverless: Updating Stack... Serverless: Checking Stack update progress... CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - chatwork-cloudwatch-dev CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - DispatcherLogGroup CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - DispatcherLogGroup CloudFormation - CREATE_COMPLETE - AWS::Logs::LogGroup - DispatcherLogGroup CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution CloudFormation - CREATE_COMPLETE - AWS::IAM::Role - IamRoleLambdaExecution CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - DispatcherLambdaFunction CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - DispatcherLambdaFunction CloudFormation - CREATE_COMPLETE - AWS::Lambda::Function - DispatcherLambdaFunction CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - DispatcherLambdaPermissionRDSDiskCheckAlertSNS CloudFormation - CREATE_IN_PROGRESS - AWS::SNS::Topic - SNSTopicRDSDiskCheckAlert CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - DispatcherLambdaPermissionRDSDiskCheckAlertSNS CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - DispatcherLambdaVersionP57YI0boyhmGea9ZOcUhTZoHvhE7X6VriQ9CQxhCLn8 CloudFormation - CREATE_IN_PROGRESS - AWS::SNS::Topic - SNSTopicRDSDiskCheckAlert CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - DispatcherLambdaVersionP57YI0boyhmGea9ZOcUhTZoHvhE7X6VriQ9CQxhCLn8 CloudFormation - CREATE_COMPLETE - AWS::Lambda::Version - DispatcherLambdaVersionP57YI0boyhmGea9ZOcUhTZoHvhE7X6VriQ9CQxhCLn8 CloudFormation - CREATE_COMPLETE - AWS::Lambda::Permission - DispatcherLambdaPermissionRDSDiskCheckAlertSNS CloudFormation - CREATE_COMPLETE - AWS::SNS::Topic - SNSTopicRDSDiskCheckAlert CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - chatwork-cloudwatch-dev CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - chatwork-cloudwatch-dev Serverless: Stack update finished... Service Information service: chatwork-cloudwatch stage: dev region: ap-northeast-1 stack: chatwork-cloudwatch-dev resources: 7 api keys: None endpoints: None functions: dispatcher: chatwork-cloudwatch-dev-dispatcher layers: None Stack Outputs (略) Serverless Enterprise: Run `serverless login` and deploy again to explore, monitor, secure your serverless project for free.
デプロイによって下記が出来ています。
- Lambda関数のデプロイ
- SNSとLambda関数の連携とデプロイ
Cloudwatch Alarm
今回はRDSの容量を監視します。
Cloudwatch Alarmの作成を行います。
- メトリクス
「FreeStorageSpace」を選択します。 - ディスク容量の閾値を設定します。
FreeStorageSpace (FreeStorageSpace) <= 3000000000
※ 3000000000 = 3GB - アラームが次の時
「警告」 - SNSのトピック
「sls-cloudwatch」
Chatworkに通知が行くかテストする
RDSの容量をCloudwatch Alarmの警告閾値まで減らします。
EC2からRDSに接続します
# mysql -u <DBマスターユーザ> -h <RDSエンドポイント> -p Enter password:<RDSパスワード> Welcome to the MariaDB monitor. Commands end with ; or \g. Your MySQL connection id is 7 Server version: 5.7.22-log Source distribution Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | innodb | | mysql | | performance_schema | | sys | | yuutestdb | +--------------------+ 6 rows in set (0.00 sec)
yuutestdbがターゲットです。
MySQL [(none)]> USE yuutestdb; Database changed
CREATE TABLE item ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(10), description VARCHAR(30), price INT UNSIGNED, created_at DATETIME );
INSERT INTO item () VALUES (); --1行作成 INSERT INTO item (id) SELECT 0 FROM item; --2行になる INSERT INTO item (id) SELECT 0 FROM item; --4行になる INSERT INTO item (id) SELECT 0 FROM item; --8行になる INSERT INTO item (id) SELECT 0 FROM item; --16行になる ・・・ 繰り返す
データを入れ込む
UPDATE item SET name = CONCAT('商品', id), description = SUBSTRING(MD5(RAND()), 1, 30), price = CEIL(RAND() * 10000), created_at = ADDTIME(CONCAT_WS(' ','2014-01-01' + INTERVAL RAND() * 180 DAY, '00:00:00'), SEC_TO_TIME(FLOOR(0 + (RAND() * 86401))));
これでRDSの容量が圧迫されます。
通知されたら成功です。
[amazon_link asins=’4295006653,4822237443,B07HJ12LJT’ template=’ProductCarousel’ store=’izayoi55-22′ marketplace=’JP’ link_id=’3840eb13-f1e4-4150-9a4f-afa11efd6458′]
[amazon_link asins=’4046042036,B07M7S9GDL,479739739X’ template=’ProductCarousel’ store=’izayoi55-22′ marketplace=’JP’ link_id=’d4bbfa38-ac08-4933-9c99-04dc3ba4b9ee’]