Lambdaでサーバーレスボットを作った話みんなのウェディングのインフラエンジニア横山です。今回はAWSのサービスを利用したサーバーレスなデプロイボットの作り方についてお伝えします。弊社には、rubotyで作られた、minaというデプロイ用のボットが存在しており、こちらのボットにSlack上で話しかけることで本番環境へのデプロイを行っていました。今回は、このminaの置き換えとしてサーバーレスなデプロイボットが作れないか取り組みました。作成の動機は以下の2点です。全体の流れは以下の図の通りです。Gatewayに紐づけられたLambdaでデプロイ処理が実行されるデプロイされる※AWS側のリソースはSAMで管理。以下では各ツールの概要と今回どのような用途に使っているのかについて説明します。Slackのスラッシュコマンドスラッシュコマンドは、Slackの標準機能です。以下のように様々な操作のショートカットとして利用できます。標準で用意されているコマンドだけでなく、自分でコマンドを作ることができ、指定したURLにPOST、GETリクエストを送ることができます。Gatewayのエンドポイントに、以下のようなリクエストボディを持つリクエストを送信するようにしています。token=XXXXXXXXXXXXXXteam_id=T0001team_domain=examplechannel_id=C2147483705channel_name=testuser_id=U2147483697user_name=Stevecommand=/deploytext=wedding+productionresponse_url=https://hooks.slack.com/commands/1234/5678text部分に、スラッシュコマンド実行時の引数が記載されます。複数ある場合は+で結合されます。GatewayはAWSフルマネージドなAPI作成サービスです。リソースごと、HTTPメソッドごとに対応する動作を指定していくだけでAPIの作成ができます。以下の例だと/に対してPOSTリクエストがきた際の動作について指定しています。今回は、スラッシュコマンドからのPOSTリクエストの受け取りに利用しています。受け取ったリクエストは対応するLambdaに送られ、デプロイ処理が行われます。LambdaLambdaはサーバーのプロビジョニングや管理なしでコードを実行できるサービスです。今回は、普段利用しているRubyに近い言語ということでPythonを選択しました。今回はデプロイ処理の実行環境としてLambdaを利用しています。Gatewayから受け取ったリクエストの内容を元に、CodeDeployやCodePipelineといったデプロイツールを実行します。Lambda関数は以下の3種類に分けています。Gatewayからのリクエストを受け取るDeployStarterと、実際のデプロイ処理を行うDeployExecutor、デプロイロックの処理を行うDeployLockに分けています。分けた理由は、スラッシュコマンドの仕様で3秒以内にレスポンスを返さないとエラーになってしまうためです。DeployStarterでの処理を、スラッシュコマンドから送られてくるトークンを元にした認証処理と、DeployExecutorまたはDeployLockの実行処理だけにすることで3秒以内にレスポンスを返せるようにしています。Model)とは、今回のようなサーバーレスアプリを作成、管理するのに適したツールです。GatewayもLambdaも設定項目が多く、構成管理しないまま使うと同様の構成を作り直す必要がある時に苦労します。SAMを使うと簡単なyamlファイルで構成管理ができます。GatewayとLambdaの管理に利用しています。cloudformationコマンドでpackageしてdeployすることで、APIGatwaway:1つとLambdaFunction:2つを持つCloudFormationのスタックが出来上がります。コードの内容を変更した際も再度packageしてdeployすることですぐに変更を反映可能です。使うことで、インフランエジニアでも簡単にサーバーレスボットを作ることができました。SAMを使うことで、構成管理までお手軽にできてしまいました。複雑なことをしないのであれば、専用のボットフレームワークではなく、今回作成したようなサーバーレスボットで十分であることがお分りいただけたかと思います。機会がありましたら、皆さんも是非作ってみてください!(2018年06月25日)twitterfacebookhatenabookmark最新の記事みんなのウェディングはEKSで動いていますタイポグラフィとCSSのスタイル宣言2019年新卒エンジニア研修もそろそろ終盤です。