最近仕事で必要になり,CircleCI + Apex を使って,Lambda を複数環境 (prd / stg / dev など) にデプロイできる仕組みを作ったので,実現したかったこと,工夫したことなどを紹介したいと思う.ちなみに,以前も似たような事例で CloudWatch Events + Lambda + CircleCI + Apex を使ったアーキテクチャを紹介したが,これはあくまで開発ツールの位置付けなので,複数環境の考慮が必要なく,単純に apex deploy
を実行するだけの非常にシンプルな構成になっていた点が異なる.
エイリアスは採用しなかった
「実践 AWS Lambda」にも書いてある通り,Lambda にはエイリアスという機能があり,特定のバージョンに prd / stg / dev など,任意のエイリアスを付けて識別することができる.単純にバージョンと環境を紐付けるだけなら便利だと思うが,今回は以下の要件を満たしたいと考えていて,エイリアスで環境を識別するアプローチは採用しなかった.プロダクションで Lambda を使う場合,基本的には以下の要件はあると思う.
- 環境ごとに異なる環境変数を設定する
- 環境ごとに制御した IAM ロールを設定する
- 環境ごとに異なるコンピューティングリソースを設定する
複数環境デプロイ
公式ドキュメントにも記載がある通り,Apex は複数環境 (Multiple Environments) のデプロイに対応している.特に難しいことはなく,環境ごとの設定ファイルを用意して --env
オプションを指定することで,環境別にデプロイを行うことができる.なお,環境ごとの設定ファイルには大きく2種類あり,粒度によって使い分けることができる.
project.json
… 複数の Lambda 関数で共通して参照する設定ファイルfunction.json
… Lambda 関数ごとに参照する設定ファイル
今回作ったデプロイフローはザッと以下のようになる.
事前作業
環境ごとに IAM ロールが必要になるため,事前に作成しておく.今回サンプルとして prd / stg / dev を作成した.
arn:aws:iam::00000000000:role/prd-myfunc_lambda_function
arn:aws:iam::00000000000:role/stg-myfunc_lambda_function
arn:aws:iam::00000000000:role/dev-myfunc_lambda_function
IAM ポリシーの設定は割愛するが,公式ドキュメントに Lambda のポリシーテンプレートが公開されていて,様々なユースケースを網羅しているため,非常に便利!
Apex ディレクトリ構造
Apex ディレクトリ構造は以下のようになる.project.*.json
はルートディレクトリに配置して,function.*.json
は Lambda 関数のメイン処理と同じディレクトリに配置している.なお,今回は2個の Lambda 関数をデプロイできるようにした(ランタイムは Python).
├── circle.yml ├── functions │ ├── myfunc1 │ │ ├── function.dev.json │ │ ├── function.prd.json │ │ ├── function.stg.json │ │ ├── main.py │ │ └── requirements.txt │ └── myfunc2 │ ├── function.dev.json │ ├── function.prd.json │ ├── function.stg.json │ ├── main.py │ └── requirements.txt ├── project.dev.json ├── project.prd.json └── project.stg.json
project.*.json
と function.*.json
設定項目としては同じで,粒度が異なるだけなので,今回は project.dev.json
を例に載せる.
{ "name": "dev-myfunc", "description": "dev-myfunc", "memory": 128, "timeout": 5, "role": "arn:aws:iam::00000000000:role/dev-myfunc_lambda_function", "environment": { "XXX": "xxx", "YYY": "yyy", "ZZZ": "zzz" } }
このように設定することで,今回の要件を全て満たすことができた.
- 環境ごとに異なる環境変数を設定する
- 環境ごとに制御した IAM ロールを設定する
- 環境ごとに異なるコンピューティングリソースを設定する
デプロイする
残るはデプロイするだけとなる.
$ apex deploy --env prd $ apex deploy --env stg $ apex deploy --env dev
CircleCI で自動デプロイ
今回も CircleCI で自動デプロイをできるようにした.以下にサンプルの circle.yml
を載せておく.これで,プルリクを出すと dev / stg 環境にデプロイされて,master にマージをすると dev / stg / prd 環境にデプロイされる.便利!なお,テストを書かないと CircleCI でエラーになるため,今回は echo
を設定して回避している.
machine: timezone: Asia/Tokyo dependencies: post: - curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sudo sh - apex version deployment: prd: branch: master commands: - pip install --requirement functions/myfunc1/requirements.txt --target functions/myfunc1 - pip install --requirement functions/myfunc2/requirements.txt --target functions/myfunc2 - apex deploy --env dev - apex deploy --env stg - apex deploy --env prd stg_dev: branch: /^(?!master$).*$/ commands: - pip install --requirement functions/myfunc1/requirements.txt --target functions/myfunc1 - pip install --requirement functions/myfunc2/requirements.txt --target functions/myfunc2 - apex deploy --env dev - apex deploy --env stg test: override: - echo 'ok'
まとめ
- Apex 本当に便利!
- API Gateway / DynamoDB なども必要なら Serverless Framework や AWS SAM なども候補になる
- Apex の
--env
オプションを使うと Lambda を複数環境にデプロイすることができる - 環境変数,IAM ロール,コンピューティングリソースを環境ごとに設定ファイルで変えることもできる
コントリビュート
公式ドキュメントを見ていたら --env
の部分が -env
になっていて,検索できずハマったので,修正のプルリクを投げたらすぐにマージしてもらえた!やった!