Ruby
AWS
sam
lambda

AWS samの環境構築 RubyでLambda実行

はじめに

AWS samの環境構築をし基本的にAWSの公式ドキュメントをもとに進め、LambdaはRubyで動かす

Installing the AWS SAM CLI - AWS Serverless Application Model

動作環境

MacOS 10.14.2 Mojave

AWS SAM CLIに必要なものの用意

  • Docker
  • Python 2.7または3.6のPipコマンド
  • AWS CLI: コマンドラインツール

Dockerのインストール
Docker for macはすでにインストール済みだが、参考までにDockerもhomebrewコマンドでHomebrew Caskを利用することでこのようにインストールできる

brew cask install docker

Pipがインストールされているか確認
pythonの2.7系か3系が入っていてpipがインストールされていれば良さそうなので、macのデフォルトでpipが使えるかどうかバージョンを確認してみる

pip --version
pip 18.1 from /usr/local/lib/python2.7/site-packages/pip (python 2.7)

どうやらmacのデフォルトのPython環境にpipがあるので2.7系だがそのまま使うことにする

AWS CLI: コマンドラインツールのインストール
awscliのインストールはこちらの公式のページを参考にする
AWS Command Line Interface をインストールする - AWS Command Line Interface

こちらのコマンド一発でよい

pip install awscli --upgrade --user

# --upgradeオプションはすでにインストール済みのawscliを更新する
# --userオプションは実行ファイルなどシステム領域に置かないようだ。 awsコマンドはここにある /usr/local/bin/aws
# 素の環境のサーバでこのコマンドを入れる場合はこれらのオプションはいらないだろう

aws cliでコンフィギュレーションをする

Quick Start - AWS Serverless Application Model より

Before You Begin
You must have an AWS account with an IAM user that has administrator permissions.

とあるのでアドミン権限のあるIAMユーザを作成ておく。

デプロイする際にはCloudformationの権限のみあればいいようなのだが、ローカル開発で必要な権限は何で、デプロイさせない権限の開発者の場合はCloudformationの権限を付けたくない、このような要件については別途調査する。それにしてもこいう説明はAWSのドキュメントってなんかいまいちなんだよなぁ

cliからコンフィギュレーションを実行する。とりあえずregionはap-northeast-1(東京リージョン)にしておく

aws configure
AWS Access Key ID [****************AAAA]:
AWS Secret Access Key [****************BBBBB]:
Default region name [None]: ap-northeast-1
Default output format [None]:

python環境をvirtualenvを使って構築している場合は仮想環境で AWS Command Line Interface をインストールする - AWS Command Line Interfaceを参考にすれば良さそうだ

AWS SAM CLIをインストールする

インストールする全体条件のものが全て揃ったのでAWS SAM CLIを入れる。
こちらもAWS CLIと同様にpipコマンド一発だ

pip install --user --upgrade aws-sam-cli
# --userや--upgradeのオプションもaws-cliと同様の意味

AWS SAM CLIを使ってローカル環境でLambdaを動かしてみる

こちらの公式ドキュメントをもとにLambda開発環境を構築する
Quick Start - AWS Serverless Application Model

いったんsample用のディレクトリを作って移動する

mkdir sam_sample && cd sam_sample

QuickStartではPythonで書いてるけど、Rubyで構築してみるBuilding Lambda Functions with Ruby - AWS Lambda

初期化

Rubyでsamプロジェクトを初期化するとsam-appというディレクトリが作られてlambdaのテンプレートなるファイルが作られた

sam init --runtime ruby2.5

Gemfileにhttpartyという全然知らないhttp clientがある

cd sam-app
sam_sample/sam-app » sam build --use-container
2019-01-10 20:39:56 Starting Build inside a container
2019-01-10 20:39:56 Found credentials in shared credentials file: ~/.aws/credentials
2019-01-10 20:39:56 Building resource 'HelloWorldFunction'

# aws-cliでアクセストークンやシークレットキー、リージョンの設定を入力していないとエラーになる

ビルドする際に sam build --use-container でコンテナ使うよってやってあげると開発言語をローカルに入れなくて良いみたいだ

ローカル起動

ローカルAPI Gatewayで起動

Running API Gateway Locally - AWS Serverless Application Modelを参考に実行

sam local start-api

ブラウザで下記にアクセス
http://127.0.0.1:3000/hello

{
"message": "Hello World!",
"location": "175.131.178.24\n"
}

単独で起動

Invoking Functions Locally - AWS Serverless Application Modelを参考に実行

sam-app下にあるtemplate.yamlファイルを見ると、
Resourcesの直下のキー 'HelloWorldFunction' が一つ一つのLambdaファンクションの設定となっている

Resources:
    HelloWorldFunction:
        Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
        Properties:
            CodeUri: hello_world/
            Handler: app.lambda_handler
            Runtime: ruby2.5

標準入力からからのオブジェクトを渡して起動してあげる

echo "{}" | sam local invoke "HelloWorldFunction"

START RequestId: 52fdfc07-2182-154f-163f-5f0f9a621d72 Version: $LATEST
END RequestId: 52fdfc07-2182-154f-163f-5f0f9a621d72
REPORT RequestId: 52fdfc07-2182-154f-163f-5f0f9a621d72  Duration: 656.91 ms Billed Duration: 700 ms Memory Size: 128 MB Max Memory Used: 29 MB
{"statusCode":200,"body":"{\"message\":\"Hello World!\",\"location\":\"175.131.178.24\\n\"}"}

timeコマンドで測ってみると6.5秒ほどかかる。結構遅い。
sam buildした際に--use-containerを付けているせいかもしれない。

template.yml にcloudformationみたいな(同じ?)設定がありAPI GatewayでLambdaが呼び出されるようになっている

テスト実行方法

テスト実行で使うgemのインストール

gem install mocha

これ以外にもLambda本体で利用するgemのインストールする必要がある。

gem install httparty

rubyコマンドでテストを実行する

テストの内容は

ruby tests/unit/test_handler.rb

Loaded suite tests/unit/test_handler
Started
.
Finished in 0.001067 seconds.
-------------------------------------------------------------------------------------------------------
1 tests, 4 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
-------------------------------------------------------------------------------------------------------
937.21 tests/s, 3748.83 assertions/s

こちらは爆速である。デフォルトで設定されているテストはlambda_handlerで必要なeventのモックと、lambda内で通信するモックをつくり想定したレスポンスをlambda_handlerで返しているかどうか見ている。フィーチャーテストっぽい。

まとめ

* aws samの環境構築から、ローカル実行、テストの実行までできた
* 最近できたRubyでlambdaを動かせた

今後の課題
* samを使ってローカル開発する場合の最小のIAMユーザの権限はなにか、またAWSにデプロイする際に必要な権限はなにか調査
* sam buildする際にコンテナを利用しなかった場合は、samのリソース?を単独で起動でさせた場合の実行速度はどうなるか検証
* 開発、テスト、デプロイ、運用のライフサイクルを検討する。コマンドでデプロイではなくGithubでマージされたらデプロイするなど実運用を想定して検証
* aws sam環境をDockerでコンテナにしてローカル開発環境を作れないか検討

参考情報

Installing the AWS SAM CLI - AWS Serverless Application Model

AWS Command Line Interface をインストールする - AWS Command Line Interface

AWS SAM で Hello World する - Qiita
ローカルで TypeScript + AWS SAM (Lambda/DynamoDB) の開発環境を構築する - Qiita
aws-sam-localだって!?これは試さざるを得ない! - Qiita
Lambda 関数のビルド - AWS Lambda
デプロイパッケージの作成 - AWS Lambda