Serverless Frameworkをいくつかのプロジェクトで使ってみたので、いくつかTipsをまとめておきます。
同じyaml定義で複数環境にデプロイする
ServerlessFrameworkでは --stage develop
のようにstageを指定してコマンドを実行することで複数環境をデプロイすることが可能になります。
ただ、 stage
- division
- team
のように複数階層でデプロイかける時に少し工夫が必要でした。
stageがただの変数以上の意味を持つので何も考えず、以下のように実行してしまうと、Export名が重複してしまったり不具合が出てきました。
sls deploy --stage prod --division dev101 --team team101
stageの値ですが、いかのような優先順位で定義されます。
${opt:stage, self:provider.stage, "dev"}.
https://www.serverless.com/framework/docs/providers/aws/guide/variables/
https://github.com/serverless/serverless/blob/v2.67.0/lib/configuration/variables/sources/instance-dependent/get-sls.js#L25-L30
つまり極端な方法を採るとすると、以下のように実行すれば上手くいきます。ただ、この方法だと devision
や team
の変数の取り回しが上手くいきません。
sls deploy --stage prod-dev101-team101
そこで以下のように stage
の値をyamlの中で定義する方法で対応することにしました。
custom:
stageName: ${opt:stageName}
division: ${opt:division}
team: ${opt:team}
stage: ${self:custom.stageName}-${self:custom.division}-${self:custom.team}
この場合は --stage
の代わりに --stageName
として引数を渡します。
sls deploy --stageName prod --division dev101 --team team101
不要ファイルはパッケージから除外する
デプロイ速度に関わるので不要ファイルを除外します。
package:
patterns:
- "!node_modules/**"
- "!venv/**"
デフォルトでも以下は除外されているようです。
.git/**
.gitignore
.DS_Store
npm-debug.log
.serverless/**
.serverless_plugins/**
古いLambdaを削除
有名ですがLambdaの過去バージョンパッケージがストレージを圧迫する問題です。知らないと古いバージョンが蓄積されていって、75GB(2021/11/30時点)で時限爆弾のようにエラーを吐いて後で困ることになります。
こちらのserverless-prune-pluginを利用することで、未然に防ぐことが可能です。
plugins:
- serverless-prune-plugin
custom:
prune:
automatic: true
number: 3
CloudWatchログの削除設定
CloudWatch Logも設定しないと永遠と溜まっていくので、適切な期間を設定して削除します。
provider:
logRetentionInDays: 30
タグ付け
後でコスト管理できるようにしっかりタグ付けします。
serverless-plugin-resource-taggingのプラグインを利用すると、関連するもの一通りタグ付けしてくれます。
plugins:
- serverless-plugin-resource-tagging
provider:
stackTags:
division: devA
team: teamA
CloudFormationスタックの説明文修正
何も気にせずデプロイすると全てのスタックが 「The AWS CloudFormation template for this Serverless application
」と説明文に表示されて何がデプロイされているのかわかりにくくなります。
結局はCloudformationなのでresoucesのところにDescriptionを入れることで説明文を変更可能です。
resources:
Description: My API Stack ${self:custom.stage}
外部ファイルとすることも可能です。
resources:
- ${file(./description.yml)}
その場合、外部ファイルはDescriptionだけでもOKです。
Description: My API Stack ${self:custom.stage}
デプロイ環境
以下のようなDockerfileからビルド用のコンテナを作成してデプロイを行っています。
PythonでLambdaを書いて lambci/lambda:build-python3.8
を使っています。
lambciのイメージは少し重いですがCの拡張ライブラリをLambdaで使う場合、このイメージからビルドすると動かしやすいので使っています。
FROM lambci/lambda:build-python3.8
ARG SLS_VERSION=2.67.0
# EC2のIAMロールを利用する場合は通常無効化
# ~/.aws/configを利用する場合は有効化
#ENV AWS_SDK_LOAD_CONFIG 1
RUN curl -sL https://rpm.nodesource.com/setup_17.x | bash -
RUN yum install -y nodejs
RUN npm install -g serverless@${SLS_VERSION}
RUN mkdir /opt/sls
WORKDIR /opt/sls