Posted at

serverless framework をつかったデプロイをwerckerで自動化する

More than 1 year has passed since last update.


はじめに


  • Serverless Frameworkを利用してAWS Lambdaの関数をpythonで開発しています。

  • 機能実装するたびにデプロイするのが面倒だったので、CIサービスであるWerckerを使って自動化したときのメモとなります。


AWS LambdaのFunctionデプロイ


  • 何も考えずにデプロイしようとすると、ローカル環境で開発したコード群をzipファイルにアーカイブしてAWSのコンソールからアップロードする感じになります。

  • デプロイ以外にもテスト実行など色々と面倒なので、多くの人がServerless Frameworkを利用していると思います。


Serverless Frameworkを利用したデプロイ



  • Serverless Frameworkはサーバレス環境でのAPIやFunctionの開発をいいかんじにサポートしてくれるライブラリです。

  • デプロイも以下のようなコマンドでコードのアーカイブとアップロードから設定変更までもろもろやってくれます。

 sls deploy --stage prd


  • これだけでも十分に便利なのですが、毎回ローカル環境で手動でこのコマンドを実行する必要があります。


    • もしくは、デプロイするのを忘れてしまっていたり。。




Werckerを利用した自動デプロイ


  • ぼくらの会社ではCIツールにWerckerを利用しています。

  • 他のwebアプリケーションではプロツールにdeployerを利用していて、githubのmasterブランチにマージされるとWercker上でビルド、テスト、サーバへのデプロイを自動実行するようにしています。

  • LambdaのFunctionも同様にmasterブランチにマージで自動でデプロイされるようにします。


設定


  • Dockerイメージ


    • Wercker上で実行されるDockerイメージは、テストコードの実行もあるのでLambdaの実行環境と同じであることが望ましいです。


    • lambci/docker-lambdaというLambda用Dockerイメージがあるのでこれを利用します。



  • デプロイ実行


    • slsのコマンドを直接実行するように設定してもよいのですが、werckerにはSteps Marketplaceというものがあり、自分で作ったstepを公開してだれでも利用することが出来る環境があります。


    • こちらに公開されているstepがそのものズバリだったので利用させて頂きます。



  • 設定内容


    • 上記の内容を以下のように設定に反映させます。




wercker.yml

box: lambci/lambda:build-python3.6

build:
steps:
- script:
name: run test
code: |
pip install -r requirements.txt
$WERCKER_SOURCE_DIR/bin/run_test
deploy:
steps:
- script:
name: install node
code: |
sudo yum install -y gcc-c++ make
curl -sL https://rpm.nodesource.com/setup_6.x | sudo bash -
yum install -y nodejs
- script:
name: npm install
code: |
npm install
- ajagnanan/serverless:
task: "deploy"
region: ap-northeast-1
stage: prd



その他


テスト実行


  • 今回の記事とは直接関係ないですが、以下のようなシェルスクリプトを用意して全てのテストコードを実行できるようにしています。


    • テストコードはtest_*.pyのような名前にしいて、この名前のテストコードが全て実行されます。

    • 上記のwercker.ymlの$WERCKER_SOURCE_DIR/bin/run_testで実行するようにしています。




run_test

#!/usr/bin/env python

import sys
import os
import unittest

sys.path.append(os.getcwd())

def suite():
test_suite = unittest.TestSuite()
all_test_suite = unittest.defaultTestLoader.discover(
"test", pattern="test_*.py")

print(all_test_suite)

for ts in all_test_suite:
test_suite.addTest(ts)
return test_suite

if __name__ == "__main__":
suite = suite()
unittest.TextTestRunner().run(suite)



python実行に必要なモジュールの管理



  • Serverless Python RequirementsというServerless Frameworkのプラグインを利用して、python実行に必要なモジュールの管理を行っています。

  • このプラグインの機能で以下のように設定をおこなっておくと、デプロイコマンド実行時に、OSに依存するようなモジュールはLambda用Dockerイメージをダウンロードしてきてその中でビルドしてデプロイしてくれます。


pythonRequirements:
dockerizePip: true


  • ただし、この設定のままだとwercker上でも同様の動きになってしまうので、環境にあわせて設定を変えられるようにしておきます。


    • 本番環境のデプロイ時のみ上記の設定をfalse(実行されない)にします。



  • serverless.ymlに以下のような記述をして環境ごとに設定ファイルを作ります。


serverless.yml


custom:
otherfile:
environment:
lcl: ${file(./conf/lcl.yml)}
dev: ${file(./conf/dev.yml)}
prd: ${file(./conf/prd.yml)}


  • prd.ymlファイル(本場環境用の設定ファイル)に以下のように記述します。


prd.yml

DOCKERIZE_PIP: false



  • serverless.ymlの該当する箇所を以下のように設定します。


serverless.yml


pythonRequirements:
dockerizePip: ${self:custom.otherfile.environment.${self:provider.stage}.DOCKERIZE_PIP}



  • 開発環境などではtrueにしておくことでローカルでデプロイ実行する際にはこの機能が有効になるようにします。


最後に


  • AWS Lambdaはとても便利なので、色々な用途で利用していますが、一番面倒なのがテストとデプロイだと思います。

  • 上記の方法で、このあたりを他のwebアプリケーションと同じように自動実行化できるのでとても便利です!