読者です 読者をやめる 読者になる 読者になる

Timers Tech Blog

カップル専用アプリ「Pairy」, 子育て夫婦アプリ「Famm」を運営している Timers inc. の公式Tech Blogです。

Amazon Lambda開発環境のススメ

AWS Lambda Timers Advent Calendar 2016

CTOの椎名です。 先日AWS Re:Invent(ラスベガス)から帰国しました!
今年の Keynote ではかなりの量の新サービスが発表されましたね。自分が聴講したセッションもほとんどが口を揃えてサーバーレスや Lambda などの話をしており、AWSは一気にサーバーレスを推していってるんだなーと肌身に染みました。

本日はLambdaの開発環境についてお話です。
Lambdaでの開発環境の整備についてはまだ業界的なベストプラクティスが整ってないのが実情だと思いますが、そんな中弊社で活用している/導入しようとしている技術について紹介させて頂きます。

Lambda での環境管理

Lambdaを使っているとまず考えるのが、開発環境(dev)と本番環境(prod)の環境分けについてです。

環境ごとにfunctionを作る

現在では現在、単純にfunctionごと分けてしまっています。<関数名>_dev <関数名>_prod のように、サフィックス等で管理すると良いです。こうすると、 _dev_prod のfunctionで別々のイベントソースを設定することができ、開発が容易になります。
さらに、開発環境からは _dev のfunctionにしかデプロイできないようになどの設定をIAM Policyで行えばうっかり開発環境から開発中のコードを本番アップしてしまった、みたいな事を防げます。

{
    "Effect": "Allow",
    "Action": [
        "lambda:CreateFunction",
        "lambda:CreateAlias",
        "lambda:ListVersionsByFunction",
        "lambda:GetFunction",
        "lambda:InvokeFunction",
        "lambda:UpdateFunctionCode"
    ],
    "Resource": [
        "arn:aws:lambda:<region>:<id>:function:*dev*"
    ]
}

しかし、この方法だと、devとprodで同じコードがデプロイされているかを担保することができません。
そこで、エイリアスを使った方法がAWSのドキュメント上で紹介されています。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/versioning-aliases-permissions.html

エイリアスごとにイベントソースマッピングを変更することもできるため、「DEVエイリアスは開発環境のイベントソースをトリガーにする」といったことも容易です。何よりこの方法だと、いざDEVエイリアスでのテストが完了したらエイリアスの向き先変更だけで本番デプロイが完了できてしまいます。
この方が安心したデプロイを行えますね。

複数の開発環境が同じdev functionを向いている時の対応

上記は dev-prod という比較的シンプルな環境でしたが、複数人で開発していると下記のようなケースが発生します:

  • S3バケットへの putObject をトリガーに実行されるLambda functionがある
  • そのfunctionの中で自社APIに向けたリクエストを投げている
  • ある開発者が、個人環境での開発のために、自分の環境向けにリクエストを投げてもらうように設定したい

弊社ではこういったケースでは、S3にputされるファイルのMetadataにAPIリクエストを投げるホスト名を入れてしまい、Lambda functionの中でMetadataを読み取ってそのホスト名にリクエストを投げる、という処理を行なっています。これにより各々の開発者が自分たちの開発環境でリクエストを受けることができ、開発効率が上がります。

...

// Lambda function内

var hostname;

// S3ファイルを取得
s3.getObject(param, function(err, data){
  if (data.Metadata.hostname) {
    hostname = data.Metadata.hostname;
  } else {
    // デフォルトのホスト名
  }
});

...

lambda-local で気軽にローカル実行

書いたLambdaをテストするには毎度アップロードして invoke しなければいけません。そこで、手前味噌ですが以前から開発運用している、軽量のローカルでのLambdaのエミュレータがあります。

https://github.com/ashiina/lambda-local

これを使えば簡単にローカルでの実行テストを行うことができます。

lambda-local -l index.js -h handler -e event-samples/s3-put.js

タイムアウト設定や、AWS APIを呼ぶためのクレデンシャル設定なども引数でできるので、色々と利便性高く使うことができます。

Lambda function のセットアップからデプロイまで

Lambda functionのセットアップは、function設定やロールの設定などを行わないといけないし、いざローカルで開発したコードをAWSにアップロードしたい時も自分でzipを作ってアップロードするのは手間です。
そこで Apex というツールがおすすめです。

http://apex.run/

Apexは複数functionをまとめてプロジェクトという単位で表現しており、そこでfunctionの管理を行うことができます。デプロイもfunction単位やプロジェクト単位で簡単に行うことができ、ロールバックも簡単なコマンドで出来ます。

# プロジェクトのセットアップ
apex init

# プロジェクトのデプロイ
apex deploy

# hello function のみデプロイ
apex deploy hello

# hello functionをinvoke (ローカルのものではなく、デプロイされたコードのinvokeです)
apex invoke hello

# functionを指定のバージョンにロールバック
apex rollback hello 2

まとめ

まだ弊社ではLambdaは少しずつしか使っておらず、これからも複数人で効率的にLambdaを開発していく際の環境はよりよくしていきたいと思っています。Apexのようなツールも出てきて、他にもツールやフレームワークはどんどん出ていると思うので、新しいものに乗り遅れないようにしていきたいですね。


また、弊社では、子育て家族アプリFamm、カップル専用アプリPairyを運営しており、現在エンジニアを積極採用中です! 急成長中のサービスの技術の話を少しでも聞いてみたい方、スタートアップで働きたい方など、是非お気軽にご連絡ください! 採用HP : http://timers-inc.com/engineerings