冥冥乃志

ソフトウェア開発会社でチームマネージャをしているエンジニアの雑記。アウトプットは少なめです。

follow us in feedly

Serverless Frameworkプロジェクトと開発者アセットのCDを回す

前回の続きです。

mao-instantlife.hatenablog.com

mao-instantlife.hatenablog.com

GithubにコードがプッシュされたらServerlessプロジェクトをデプロイし、デプロイ後のAPIドキュメントやクライアントライブラリの生成を継続的にする環境を作ってみましょう。

閑話:外部パッケージ管理の修正

最初からかよ、とか言わない。前回、とあるLambdaファンクションを作る際に外部ライブラリを必要としました。とりあえずは .gitignore に追加してローカルで pip install することでお茶を濁していましたが、やはりかっこ悪いですし、CD環境作るには微妙なところでもあるのでプラグインを導入してなんとかします。

github.com

やはり誰かが考えてるものですよね、遠慮なく乗っからせていただきます。ちなみに、クラメソさんの以下の記事を参考にして使い始めたけど、少しバージョンアップして使い方が変わったっぽいです。最新はドキュメントをみましょう。

dev.classmethod.jp

ローカルでは普通にグローバルに pip install してパスを通して使うという場合はプラグインを入れて requirements.txt を使う感じです。特にプロダクトコードに記載を加える必要はありません。

グローバルに pip install せずに requirements.txt の設定を元にローカルでもキックするよ、という場合は外部ライブラリをzipにまとめて使う設定にしましょう。 serverless.yml に以下の設定を追加します。

custom:
  pythonRequirements:
    zip: true

その上で、対象の外部ライブラリを使うコードの前に

import unzip_requirements

を追加します。

ダウンロードしたライブラリや自動生成されるコードのなどがあるので、以下は.gitignoreに追加しておくのが良いと思います。

  • .requirements
  • .requirements.zip
  • unzip_requirements.py

閑話休題:CD環境の整理

前回の構想、こんな感じでした。

Github(merge)-> CodeBuild -> CodeDeploy -(API Gateway)-> クライアントライブラリの生成とSwagger UIの更新

今回、CodePipelineで全体を管理できないか調べてみました。

CodePipeline is 何?

リリースのための手順、フローのモデル化、自動化のためのAWSのサービスです。で、調べ始めたんですが、割とつらみがあるっぽいです。

qiita.com

CircleCIでいいんじゃない?

ですよねー。

というわけでCircleCIをおさらいしてみました。前にちょっと使ってた時は1系だったので少し進化してましたね。

  • ビルドやテスト実行はDockerが基本になってる
  • 複数のイメージの連携もCirclCIがよしなにしてくれる
  • ジョブ毎に個別のイメージが使える
  • AWSへのデプロイ設定も楽

circleci.com

カスタムコンテナを使う

で、今回のプロジェクトはServerless Framework + Python3なわけですので、ビルド環境のイメージは専用に作ってあげる必要があります。基本的なビルド環境についてはCircleCIが使う各種ツールがインストールされた状態でのオフィシャルイメージがあるので、nodeから派生させることにしましょう。

イメージは .config/images にDockerfileをおくか、リポジトリにプッシュしておいてもいいです。構成が決まればイメージは共有できて、必要なミドルウェアは別のイメージで配備するというてもあるので、Dockerhubとかにプッシュしておくのが楽だと思います。

というわけで出来上がったのがこちらのイメージ。Dockerhubにも公開していますので、必要な方はご自由にどうぞ。

github.com

Serverless Framework + Python3で使うPythonのバージョンが3.6で、apt-getでインストールできるPythonが3.4だったし、いくつかググって出てきたバージョン3.6があると思しきリポジトリは追加しても404だったりで、結局イメージないでコンパイル・インストールしています。このあたりはもっとスマートに行きたいところだったんですが。。。

今回はデプロイまでなのでJREをインストールしていませんが、テストを流すとなるとDynamoDB Localを使うことになるのでJREのインストールが必要になります。これもこれで面倒臭いというか、LocalStackとかの利用で別のイメージ前提にした方がいいのではないかと考え中です。

github.com

qiita.com

閑話:serverless-step-functionsプラグインの制約にハマる

で、意気揚々とイメージ作ってデプロイしてみたら sls invoke stepf が動かないわけですよ。実はローカルで実行してみても同様だったと。StateMachineが見つからないとか言われます、そんなバカな。で、色々とごにょごにょしていて、StateMachineの設定からname属性を外し、命名をキャメルケースにしたらできました。実際にデプロイされた時の名前はこんな感じです。

MyAssistantGenerateClientStepFunctionsStateMachine-************

末尾はなんかハッシュっぽい、念のためマスクしています。この末尾の部分はデプロイするステージを変更したら変わりました。この辺普通に文字列でつけたりできないか確認したいところ。まあ、Step Functionsへのキックイベントも serverless.yml で書けるので実際問題はそこまできにする必要がないのかもしれませんが。

で、前回までの命名とname属性で登録された名前がこちら。

MyDashassistantDashgenerateDashclientDashdev-************

なんかname属性がある場合とか、変換とか文字数とかいくつか原因はありそうな気がします。とりあえず現状はそんなに細かい命名をしたいわけではないので、上の対応策でなんとかしました。

閑話休題:継続的デプロイの設定

というわけで今回の内容を反映した .circleci/config.yml がこちらです。走り過ぎても面倒臭いので現状はmasterへのプッシュ、マージの時のみ発動、CodeGeneratorもまだ常時キックする感じでもないためStepFunctionsの設定をパスするように変更しています。

version: 2
jobs:
  build:
    docker:
      - image: shinsukeabe/circleci-serverless-python3:latest
    steps:
      - checkout
      - run:
          name: install project dependencies plugins
          command: sudo npm install serverless-dynamodb-local
      - run:
          name: deploy serverless functions
          command: sls deploy -v
      - run:
          name: distribute developers assets
          command: sls invoke stepf --name myAssistantGenerateClient
general:
  branches:
    only:
      - master

github.com

まとめ

というわけで、CircleCIで自動デプロイまで仕掛けました。今回テストは仕掛けてませんが、ここまでできて入れば後は細かいつらみとの戦いになります。ここからしばらくはServerlessとLambdaの使い方を深めていく方向に試していこうかと思います。KMSとか使ってないですし、Lambdaに合ったデータの永続化のあり方とか。キリが良くなったら続けます。