AWS Lambdaで運用した実績から得られた、serverless frameworkのオススメ設定とプラグインの知見

はじめまして。株式会社GA technologies のService Development Division (開発部門) エンジニアの永冶といいます。 今後、この技術ブログを通して様々なことをアウトプットし、記事を閲覧する方の力に少しでもなれたらと思います。よろしくお願いします。

この記事を書いた経緯

弊社ではAWS Lambdaを

  • 画像の圧縮
  • Slackへの通知
  • 外部サービスとの連携

などで幅広く使用しています。数多くのLambda関数を管理する上で、設定の可視化とデプロイの自動化は避けては通れません。設定の可視化とデプロイの自動化を達成するために、弊社のいくつかのプロジェクトではserverless frameworkを使用しています。

社内で運用を続けていく上で、serverless frameworkを使用する時のオススメの設定やプラグインが洗練されてきました。 この記事を読むことで、frameworkを運用する際の参考にしていただければと思います。

対象読者

  • AWS Lambdaを使用している
  • serverless frameworkの使用を検討している
  • serverless frameworkを使い始めた

動作確認環境

バージョン

Node.js v10.10.0
Python 3.6.6
serverless 1.32.0

オススメ設定

ログの有効期間を設定しよう

serverlessのデフォルトの設定では、Lambda関数のCloudWatch Logsの有効期間は無期限です。 簡単な通知など、永久にログを保持する必要がないものなら、課金対象にもなるので有効期間を設定しておく方が良いでしょう。

設定方法

serverless.ymlにてlogRetentionInDaysを設定します。

provider:
  logRetentionInDays: 30

この場合、ログは30日間保持されます。

デプロイするバケットを指定しよう

serverlessのデフォルトの設定では、デプロイするステージに応じてS3バケットを作成します。
20個のアプリケーションを検証と本番のステージごとにデプロイしようものなら、40もバケットが作成されてしまい、アカウントごとのバケット数の上限緩和申請が必要になる場合があります(経験談)。
特別な理由がなければ、あらかじめS3バケットを作成しデプロイ用のバケットを設定することで、不用意にS3バケットが作成されることがなくなります。

設定方法

serverless.ymlにてdeploymentBucketを設定します。

provider:
  deploymentBucket:
    name: serverless-deployment

これでデプロイするバケットをserverless-deploymentにできます。

同時にデプロイしておくlambdaの旧バージョン数を指定しよう

これは大きな失敗の経験から得た教訓になります。

失敗

ある日同僚から不穏な問い合わせを受けました。「AWSコンソールであなたのアカウントはコードストレージの上限 75.0 GB を超えています。と表示され、関数パッケージのアップロードができない状態になっています。。」と。
確認すると、デプロイパッケージの容量が多いLambda関数が数100バージョン分デプロイされ、容量の上限に達していました。

f:id:t_nagaya:20181129225347p:plain
Lambdaのコードストレージを使い果たしてしまい、新たにLambda関数をデプロイできない状態に。。

原因

serverless frameworkではデフォルトで、デプロイした全てのバージョンを保持するようになっています。 過去にデプロイした大量のバージョンがLambdaのコードストレージを圧迫していました。

対策

serverless frameworkでは、バージョン管理をしないという設定を、下記のようにserverless.ymlに書くことができます。

provider:
  versionFunctions: false

しかし、エラーがあった際のロールバックなどを考えると、最新から何世代かのバージョンを残しておくようにしておく方がいいでしょう。 プラグインserverless-prune-pluginを使用すれば、最新からいくつかのバージョンのみ保持するようにしておき、他はデプロイ時に破棄することができます。

プラグインserverless-prune-pluginをインストールし、serverless.ymlに設定を書くだけです。

plugins:
  - serverless-prune-plugin

こうすることでsls pruneというコマンドを使用して、指定したバージョンのみを保持し、その他は削除することができます。 削除処理も自動化しておきたい場合はさらに、

custom:
  prune:
    automatic: true
    number: 3

とすれば良いです。こうすれば最新から3つのバージョンのみ保持し、残りは削除してくれます。

他にも有用な設定がないか知りたい場合は、serverless.ymlのドキュメントを見てください。 serverless.yml

オススメプラグイン

serverless-plugin-aws-alerts エラー検知

Lambda関数を作成する度に、CloudWatchアラームの設定をするのは面倒です。 プラグインserverless-plugin-aws-alertsは、serverlessでデプロイした時に同時にアラームの設定してくれたらとても便利です。

実行エラーなどのメトリクスが閾値を超えたらSNSに通知し、SNSをサブスクライブするLambda関数でSlackに通知して、開発者に知らせるということをよくやっています。

f:id:t_nagaya:20181129233329j:plain
Slackの通知

設定方法

例としてserverless.ymlに下記のように記載します。

plugins:
  - serverless-plugin-aws-alerts

custom:
  alerts:
    stages: # Optionally - select which stages to deploy alarms to
      - dev
      - prod
    topics:
      alarm: hoge-alerts-alarm
    definitions: # these defaults are merged with your definitions
      functionErrors:
        treatMissingData: notBreaching
        period: 300 # override period
        description: Lambda関数の実行に失敗しました。CloudWatchのログを確認してください。
    alarms:
      - functionErrors

これは、

  • devとprodステージで
  • 300秒の期間内に
  • 関数実行エラーが発生したら
  • SNSトピックhoge-alerts-alarmに通知する

という設定になります。

serverless-python-requirements Pythonライブラリをデプロイ時に自動でパッケージ化

PythonでLambda関数のコードを書いている際は重宝します。requirements.txtに必要なライブラリを記載しておきさえすれば、
このプラグインによって、自動的にライブラリがパッケージに取り込まれます。

設定方法

serverless.ymlに下記のように記載します。

plugins:
  - serverless-python-requirements

あとは必要なライブラリをrequirements.txtに記載するだけです。

$ pip install requests
$ pip freeze > requirements.txt

まとめ

最後にこれまで列挙した内容をserverless.ymlにまとめました。

service: hoge # NOTE: update this with your service name

provider:
  name: aws
  runtime: python3.6

  stage: dev
  region: ap-northeast-1
  logRetentionInDays: 7
  deploymentBucket:
    name: serverless-deployment # NOTE: update this with your deployment bucket name

plugins:
  - serverless-plugin-aws-alerts
  - serverless-python-requirements
  - serverless-prune-plugin

functions:
  hello:
    handler: handler.hello

custom:
  alerts:
    stages: # Optionally - select which stages to deploy alarms to
      - dev
    topics:
      alarm: hoge-alerts-alarm  # NOTE: update this with your topic name
    definitions:
      functionErrors:
        treatMissingData: notBreaching
        period: 300 # override period
        description: Lambda関数の実行に失敗しました。CloudWatchのログを確認してください。
    alarms:
      - functionErrors
  prune:
    automatic: true
    # $LATESTから5バージョンのみ保持する
    number: 5

serverless frameworkとプラグインをうまく使用することで、より良い環境が用意できます。 これからもserverless frameworkをキャッチアップしていき、バージョンアップ情報や良いプラグイン情報を得たら積極的にシェアしていきたいと思います。