Serverless Framework による AWS Lambda 関数の管理1

Serverless Framework による AWS Lambda 関数の管理1

はじめに

Lambda 関数を簡単に管理したい

AWS Lambda の適用分野は色々考えられますが、AWS 上の複数のサービスを、各種イベントをトリガーとして連携する、というのが割とポピュラーな使用例かと思います。

AWS Lambda は、サーバーのプロビジョニングや管理などが不要で、プログラムも AWS Management Console 上のオンラインエディタでも編集できるため、手軽に導入できますが、その反面、適切に管理しないと様々な問題が起きることは簡単に予期できます。

本記事では、Serverless Framework というものを使い、AWS Lambda 関数の定義・設定をコード化することにより(所謂 Infrastructure as Code)、煩雑になりがちな Lambda 関数を比較的簡単に管理する方法について説明します。

それ以外の方法

(本題に進みたい方は、ここは読み飛ばして OK です。)

もちろん、Lambda は AWS のサービスですので、全て AWS CLI から操作できますし、原始的な方法であれば、シェルスクリプトから AWS CLI 経由で管理するという方法があります。

AWS Way で本格的にやろうとすると、こちらのページで紹介されているように AWS CodePipeline、AWS CodeBuild、AWS CloudFormation を使う事になります。

ただ、このドキュメントを読んで、「お、管理が簡単になりそうだな。やってみるか」と思う人は、殆どいないのではないでしょうか。

こうしたプロセスを簡単にするツールはいくつかあり、ググったところ Lamvery というツールがありました。

また、Lamvery の作者が対抗心を燃やしていた(ものの、結局対抗するのを諦めた)Apex というのもありました。

これらの2つも試したのですが、イマイチ柔軟性に欠けたり、その他の問題があったので、使うのはやめました。詳細については省略します。

Serverless Framework とは

Serverless Framework (以下 Serverless と書きます)は、AWS Lambda や Azure、GCP などの同種サービスを、CLI から簡単に管理できるツールです。

私の場合、AWS を使うことが多いのですが、お客様によっては Azure を使っていることも結構多いため、1つのツールで複数のインフラに対応しているというのは有り難いです。

以下、特に断りが無い限りは、AWS に限定した話です。

出来ること

設定ファイル(YAML)を書くことで、以下のものを管理できます。

  • Lambda 関数の設定(関数の中身は、通常通りプログラムを書きます)
  • Lambda 関数のトリガー
  • Lambda 関数が使う各種リソース
    • S3
    • DynamoDB
    • SNS Topic
    • その他
  • IAM ロール

また、裏側では CloudFormation を使っているのですが、Stack の作成・更新などは透過的に行われるため、通常は意識する必要がありません。

Serverless の導入

インストール

npm を使用します。npm が入っていない人は、以下からインストールしてください。

npm を使って、以下のようにインストールします。

npm install -g serverless

IAM グループの作成

Serverless を使って、Lambda 関数をデプロイしたり、必要なリソースを作成・管理するためには、権限が必要です。

今回は、専用の IAM グループを作成し、そこに必要な権限を入れていくことにしました。必要な権限は、Serverless のこちらの issue で色々議論されているので、細かく管理したい方はそれを参照して下さい。

参考までに、今回の我々の要件で必要だったものを以下に示します。

以下の既存のポリシーと、

  • AWSLambdaFullAccess
  • AmazonS3FullAccess
  • AWSCloudFormationReadOnlyAccess

それに加え、以下のアクションの許可を与えました。

  • cloudformation:ValidateTemplate
  • cloudformation:Describe*
  • cloudformation:List*
  • cloudformation:Get*
  • cloudformation:PreviewStackUpdate
  • cloudformation:CreateStack
  • cloudformation:DeleteStack
  • cloudformation:UpdateStack

その後、この IAM グループに、使用する IAM ユーザーを追加して下さい。

AWS CLI のインストール・設定

その他、ローカルの作業用マシンで、AWS CLI のインストールと設定を行う必要があります。詳しくはこちらのページを参照して下さい。

Service の定義

“Service” とは

Serverless のドキュメントによれば、「プロジェクト」のようなものだそうです。最初はあまり細かいことは考えずに1つの Service を作っていき、慣れてきた段階で必要に応じて複数のサービスに分割するのが良いかなと思います。

Service の構成

最小構成としては

  • myService/ ディレクトリ
  • serverless.yml
  • Lambda 関数のプログラム

という形になります。serverless.yml に、必要な設定を色々書いていくことになります。

Service の作成

作成には、以下のコマンドを使用します。

sls create --template <テンプレート> --path myService

今回は、テンプレートに “aws-python3” を使用しました。それ以外に使用可能なテンプレートは、こちらのページをご参照下さい。

各種設定

ここからは、serverless.yml に書いていく各種設定について書いていきます。

最初の方で、Serverless で管理できるものは以下のようなもの、と書きましたが、それぞれについてと Service 全体の設定に分けて説明します。

  • Lambda 関数の設定
  • Lambda 関数のトリガー
  • Lambda 関数が使う各種リソース
  • (IAM ロール)

serverless.yml に記載できる設定項目は、こちらのページに網羅されていますので、こちらを参照しつつ読んでもらえると分かりやすいと思います。

全般設定

service と provider の2つのセクションに、サービスの全般的な事を記載します。

service:
  name: myService

provider:
  name: aws
  runtime: python3.6
  region: ap-northeast-1
  role: arn:aws:iam::nnnnnnnnnnnn:role/Foo_role
  stage: ${opt:stage, 'dev'}

  deploymentBucket:
    # Serverless が作成したパッケージなどがこちらのバケットに置かれる
    # 指定しないと、ランダムな名前で勝手にバケットが生成されるはず(未確認)
    name: my-project-lambda-deployment
    serverSideEncryption: AES256 # when using server-side encryption

stage は、開発、ステージング、本番、のような区分ですが、詳しくは後述します。

Function: Lambda 関数の設定

Lambda 関数の設定は functions セクションに記載します。ここでは、関数の名前や各種設定のみを定義し、実際のプログラムコードは別のファイルに記載します。

functions:
  my_awesome_function: # キー
    handler: handler.my_awesome_function
    name: my_awesome_function # 名前
    events:
      - xxx

ここで何点か説明します。

まず、handler なのですが、先程、実際のプログラムコードは別のファイルに記載すると書きましたが、handler に指定したものが実際に使われます。

例えば、この例だと handler.my_awesome_function を指定していますが、この場合は、handler.py というファイルを作成し、その中で my_awesome_function という関数を定義する必要があります。なお、ファイル名は “handler.拡張子” である必要はありません。

次に、name ですが、省略も可能で、その場合はキーの値が使われますし、そうしておいた方が無難だと思います。

先程の serverless.yaml のリファレンスページでは、name の例として「${self:provider.stage}-lambdaName」というように、ステージ名を関数名に含めていますが、私達のプロジェクトでもそうしようとしたところ、問題があったため、キーと同じ名前を使うようにしています。これも後述します。

events に関しては次の項で説明します。

Event: Lambda 関数のトリガー

Lambda 関数のトリガーは、functions セクションの中の events サブセクションで定義します。Serverless では、様々な AWS サービスからのイベントをトリガーとして、Lambda 関数を起動することが可能です。

具体的にどのようなものが使えるかは、先程の serverless.yml のリファレンスページを参照して下さい。

なお、今回のプロジェクトでは S3 へのファイル出力がトリガーとしているのですが、ここで1点注意が必要です。ここの events で “s3” を指定した場合、その S3 バケットは Serverless によって作成・管理されます。言い換えると、既存の S3 バケットを使うことは出来ません。

設計思想としてそうなっているようなのですが(詳細はこちらの issue を参照)、実際問題それだと色々不便なので、既存の S3 バケットを使用できるようにするプラグインもあります。これについても後述します。

Resource: Lambda 関数が使う各種リソース

Lambda 関数が使う各種リソースは “resources” セクションに記載します。例えば、使用する S3 バケットだったり、DynamoDB のテーブルなどが相当します。ここには、CloudFormation テンプレートの文法をそのまま記載するようなので、詳細は AWS のリファレンスを参照して下さい。

AWS Resource Types Reference – AWS CloudFormation

Lambda 関数を書く

後は、実際の処理をプログラムで書けば、大体完了です。

# handler.py

# import するだけで使えるもの
import boto3
# pip install が必要なものがある
import requests

# Lambda 関数
def my_awesome_function(event, context):
    greet("hello world!")

# 別の Lambda 関数を同じファイルに定義する事も出来る
def my_great_function(event, context):
    greet("hello world!!!")

# 共通で使うものを関数としておくと良い
def greet(str)
    print(str)

コメントに記載しましたが、注意点としては、外部のライブラリ等は、import を書くだけで使えるものと、pip install しないとだめなものがあります。

パッケージングとデプロイ

必要な Python パッケージをインストール

少し前に書いたとおり、デフォルトで使えるようになっている Python パッケージ以外は、 pip install でインストールする必要があります。この時、普通に pip install するのではなく、Serverless の Service のディレクトリ配下に配置する必要があります。一番簡単なのは handler.py と同じディレクトリに配置する事でしょう。

具体的には、以下のようにします。

cd /path/to/myService
pip install パッケージ名 -t .

追記。もっと良い方法がありますので、別エントリーにしました。

Serverless で Python のパッケージを使った Lambda 関数をデプロイ | もばらぶエンジニアブログ

デプロイ

ここまで来たら、以下のようにデプロイします。

sls deploy

このコマンドで、Python のプログラムや設定などをパッケージにして、S3 バケットにアップロードし、CloudFormation を使ってデプロイしてくれます。

それ以外のトピック

ちょっと長くなってきたので、以下のトピックは別の記事として投稿します。

  • serverless.yml での変数の扱い
  • stage について
  • serverless-external-s3-event プラグイン
  • その他、tips 等

追記。第2回の記事を書きました。

Serverless Framework による AWS Lambda 関数の管理2 | もばらぶエンジニアブログ

まとめ

Serverless Framework を使うと、AWS Lambda 関数や、それらが使うリソースを、比較的簡単な設定ファイルとプログラムコードに落とし込んで管理することが出来ます。AWS 公式(?)の方法に比べると圧倒的に簡単なので、ぜひ活用してみて下さい。

トップの画像について。

The image on the top of the page is licensed under the MIT license.