techveinのozawaです。サーバ周りのインフラ担当しています。現在、当社に固定電話がないということで、クラウド電話APIの先駆けであるTwilio(トゥイリオかツイリオ)とAWSを連携し、留守番電話サービスを構築し、Slack上に通知する仕組みを作りたいと思います。
世の中は、監視としてMackerelなどを利用して障害電話をかけるとか、どちらかというとTwilioから電話に発信するのが主流なのかなと感じました。
概要
システム構成はとにかくコストを下げたいという思いがあったので、今流行りの運用・費用コストが低いサーバレスアーキテクチャで実現するため下記サービスを使用しました。
使用サービス
- Twilio(クラウド電話API)
- AWS API Gateway
- AWS Lambda
- AWS S3
- AWS IAM
- AWS CloudFormation(serverless frameworkで使用)
- Slack
アーキテクチャ
処理の流れ
- (Clients) 電話をかける
- (Twilio) API Gateway(AAG)にリクエストを投げる
- (AAG) Lambda関数(request)を実行する
- (Lambda) record命令と再生メッセージのURL又は機械音声用の文をTwiMLで返す
- (AAG) そのままTwilioに返す
- (Twilio) 受け取った再生メッセージをClientに流した後に録音を開始し、終わり次第AAGにリクエストを投げる
- (AAG) Lambda関数(record)を実行する
- (Lambda) 録音後のメッセージのURL又は機械音声用の文をTwiMLで返し、同時にslackに録音内容のメッセージを送信する。
- (AAG) そのままTwilioに返す
- (Twilio) 受け取った再生メッセージをClientに流した後に処理完了
構築方法
今回、簡単にAPI GatewayとLambdaを設定できるserverless frameworkを使用して進めます。
本当は、AWSより去年公式にAWS Serverless Application Model (AWS SAM)というツールが用意されていたのですが、デプロイ方法などがまだ面倒そうだと感じたので、今回はserverless frameworkにしました。
- Serverless Framework
https://serverless.com/ - AWS Serverless Application Model
https://github.com/awslabs/serverless-application-model
事前準備
AWS IAM設定
Serverless Frameworkを実行するには、下記サービスへの権限が必要になるため専用のユーザー及びグループを作成します。
IAMさえ設定してしまえば、とくにAWSコンソールでどうたらすることはありませんので非常に楽です。
ここでは各サービスフル権限で行いたいと思います。
- API Gateway
- Lambda(AWSLambdaFullAccess)
- IAM(IAMFullAccess)
- S3(AmazonS3FullAccess)
- Cloud Formation(CloudFormationFullAccess 作成ポリシー)
ServerlessはCloud Formation経由でLambdaなどを設定できますが、CloudFormation用のポリシーだけテンプレートが用意されていないため、独自に作成する必要があります。
下記はCloudFormationのフルアクセス権限の例です。
下記のような、ポリシーをグループ又はユーザーに紐づけます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>, <span class="hljs-attr">"Statement"</span>: [ { <span class="hljs-attr">"Sid"</span>: <span class="hljs-string">"Stmt1485930797000"</span>, <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>, <span class="hljs-attr">"Action"</span>: [ <span class="hljs-string">"cloudformation:*"</span> ], <span class="hljs-attr">"Resource"</span>: [ <span class="hljs-string">"*"</span> ] } ] } |
またserverlessは${HOME}/.aws/以下を参照するようなので、awscliを事前にインストールして、ユーザー設定した方が楽です。
1 2 3 4 5 6 |
#awscliのインストール pip install awscli #コンフィグ設定(ユーザーのAPIKEYなどを入力) aws configure |
Serverless Framework設定
Serverless Frameworkはnpmによる提供のため、事前にnodejsをインストールする必要があります。
1 2 3 4 5 6 7 8 9 |
#nodejsのインストール(ないのであれば) brew install nodejs #serverlessのインストール npm install -g serverless #serverlessのプロジェクトを作成(nodejsで) serverless create --template aws-nodejs --path twiliocall |
Twilio設定
https://twilio.kddi-web.com/ にアクセスしアカウントを作成します。
アカウント取得後、電話番号の取得を行います。
設定
Serverless
1 2 3 4 5 6 7 |
twiliocall |-- handler.js Lambda関数記述用 |-- input.json 入力テスト用 |-- node_modules nodeモジュール |-- package.json nodeモジュールの管理用 `-- serverless.yml serverlessの定義ファイル |
nodejsにはtwilioとslackでライブラリがあるので利用します。
1 2 3 4 5 6 |
#slackライブラリ npm install slack-node #twilioライブラリ npm install twilio |
handler.js
handler.jsではLambdaにおける関数を定義します。
今回は、電話が受けた際のリクエスト(request)と録音後のリクエスト(record)の二つの関数を用意をします。
serverless.yml
serverless.ymlでは、
- AWSの設定(リージョンなど)
- Lambdaの環境変数設定
- API Gateway設定
を定義します。
test
serverlessではdeployしなくてもローカルでテストできるため、input.jsonを配置してテストしてみます。
1 2 3 4 |
serverless invoke local -f request -p input.json "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response><Say voice=\"woman\" language=\"ja-jp\">株式会社テックベインです。ビープおんの後に、メッセージをおねがいいたします。</Say><Record action=\"record\" maxLength=\"30\"></Record></Response>" |
deploy
実際にAWSへデプロイします。
AWS側の設定は全て実行されるため、デプロイ後に設定する必要はありません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
serverless deploy -s prod Serverless: Packaging service... Serverless: Uploading CloudFormation file to S3... Serverless: Uploading service .zip file to S3 (2.9 MB)... Serverless: Updating Stack... Serverless: Checking Stack update progress... .................... Serverless: Stack update finished... Service Information service: twiliocall stage: prod region: ap-northeast-1 api keys: None endpoints: POST - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/call/request POST - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/call/record functions: twiliocall-prod-request twiliocall-prod-record |
Twilio
AWSにデプロイ実行後に表示されたURLを、最初に取得した電話番号の「A CALL COME IN」に設定します。
A CALL COMES IN
1 2 |
https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/call/request |
Slack
Slackの設定ではチャンネルのIncoming Webhook urlを取得する必要があります。
録音が終わり次第、lambdaからslackへ通知をするようにします。
確認
後は電話を掛けてみれば、留守番電話サービスとして使用できます。
最後に
最近はこういった電話ですら物理機器を必要とせず、誰でも手軽にプログラムで構築出来る時代です。
私はサーバ・ネットワークを主にやってきたエンジニアですが、こういったコード化されたインフラもプログラムできないと時代についていけないと痛感しました。