✏️ 👤

サーバーレス・アプリケーションの開発ツールチェーンとして AWS SAM まわりがいい感じに成長してきているのであらためて紹介します

Serverless Advent Calendar 2017 の 15 日目です.

本記事ではサーバーレス・アプリケーションの開発ツールチェーンとして最近なかなかいい感じになりつつある AWS SAM (AWS Serverless Application Model) とその周辺を紹介しようと思います.

本記事は

  • AWS 上でサーバーレスなアプリケーションを動かしたい
  • オープンソースとしての公開も考えてたりする
  • サーバーレスなアプリケーションも CI/CD に組み込んで継続的に開発・デプロイしていきたい
  • 過去に CloudFormation で Lambda をデプロイしようとして血を吐きかけた
  • というわけで CloudFormation は生理的にちょっとムリ
  • それでも俺たちは CI/CD したいんだ…!

な方たちを対象としています.

そして例の AWS SAM のリスが気になる方や、いま電車に乗っていて他にやることがないヒマな方も対象としています.

目次

AWS SAM とは

AWS SAM は CloudFormation(以下 CFn) テンプレート仕様のサブセットです. CFn と同じく YAMLor JSONで AWS リソースを記述しますが、普通の CFn より圧倒的に人に優しい仕様になっています.

なぜ AWS SAM は優しい仕様にできた(逆に言うとなぜ CFn はあんなにも人に厳しい)のでしょうか. これは CFn と AWS SAM のそもそもの目的が異なっていることに起因します. CFn は全ての AWS リソースを正確に記述しつつそれらの関係性を表現することができるテンプレート仕様です. マネコンなどでは 1 つに見える AWS リソースも実際には複数の AWS リソースが組み合わさって出来上がっているようなことが多いため、それらをすべて記述しきることを求められるのが CFn テンプレート仕様です. 一方、AWS SAM はそのゴールを「サーバーレス・アプリケーションを定義するためのもの」という文脈に絞ったことで、記述量を減らしつつもリソース間の関係性をより直感的に記述できるようになっています. (デカめの ERP パッケージのマスタ設定で血を吐くような思いをしたことがある方は、あのイメージで CFn を捉えてもらえると伝わりやすいかもしれません. 高い汎用性を目指した結果、ちゃんと使おうとするユーザーに死相が出るパターンです. AWS SAM は同じ ERP でもユースケースや機能範囲を一定の領域に特化させることで使いやすさを実現している最近のおしゃれ SaaS のような感じと表現してもいいかもしれません.)

(余談ですが同僚に混乱している人がいたので念のため書きます. AWS SAM は実行可能なツールやコマンドの類ではなく、AWS のマネジメント・コンソールのサービス一覧に載っているようなものでもありません. 我々利用者の立場においてはあくまでもサーバーレス・アプリケーションを定義するためのモデルに過ぎず、テンプレートを書くための仕様です.)

たとえば API Gateway の GET /hello を叩くと Lambda 関数が実行されるようなアプリケーションを AWS SAM で記述すると以下のようになります.

すごくシンプルです. Events のところで Api 以外にも S3 や SNS、Kinesis、DynamoDB などが指定できたりします1. 便利.

では、生の CFn でまったく同じ AWS リソースを記述するとどうなるか見てみましょう.

読まずに一気にスクロールしましたね?

ですよね.

AWS SAM が

  1. Lambda 作る
  2. その Lambda は GET /hello で呼ばれる

だけを書けばいいのに対して、CFn では

  1. Lambda 関数用の実行時権限を作る (ログを出力したりとか)
  2. Lambda 関数を作る (実行時権限として上で作ったやつを付与する)
  3. /hello が呼び出されたら Lambda 関数を実行するリソースを持った API Gateway 作る
  4. Lambda 関数をテスト用に呼び出すことを API Gateway に許可する権限を作って API Gateway に付与する
  5. ステージングされた環境で Lambda 関数をテスト用に呼び出すことを API Gateway に許可する権限を作って API Gateway に付与する
  6. API Gateway をステージングするためのデプロイメントを作る(スナップショットみたいな)
  7. API Gateway をステージングする (外から呼び出せるようにする)

となります.「GET /hello で Lambda」がやりたいだけなのにあぁxあっっxあっぁぁぁっぁぁぁぁぁあああああぁぁぁx

ここで再び先ほどの AWS SAM テンプレートです.

今度はこのテンプレートが AWS 環境上にデプロイされるまでの流れを見ていきましょう.

この例に分かる通り、テンプレートでは Lambda 関数の実装については一切触れません. sam.yaml から見て実装ファイルが(ローカルで)どこに存在するか、Lambda 起動時に呼び出す関数名が何か、だけを書きます. 実装は sam.yaml で指定した実装ファイルの中に書きますので、例えば今回のテンプレートだと以下のようなディレクトリ構成でしょうか.

├── src
│   ├── index.js # この中に handler という関数が実装されている
│   └── node_modules # index.js が利用する依存ライブラリ群
│       └── ...
└── sam.yaml

このテンプレートを実際に動くものとして AWS 上にデプロイするには、デプロイの準備を行う aws cloudformation package [options] コマンドと、実際にデプロイを行う aws cloudformation deploy [options] コマンドという 2 つの AWS CLI コマンドを利用します.

aws cloudformation package

具体的なコマンドは以下のような感じになります.

# 折り返して記述してますが 1 行のコマンドです

$ aws cloudformation package \
    --template-file ./sam.yaml \
    --s3-bucket ${YOUR_BUCKET_NAME} \
    --output-template-file ./packaged.yaml

このコマンドを sam.yaml と同じディレクトリで実行すると

  1. –template-file オプションで指定したテンプレートを読み込んで、
  2. テンプレート内で Lambda 関数実装置き場として記述されている src ディレクトリ以下をまるっと zip 圧縮して、
  3. –s3-bucket オプションで指定した S3 バケット(これは事前に自分で作っておく必要アリ)に zip ファイルをアップロードし、
  4. sam.yaml の中の CodeUri を前手順でアップロードされた zip の S3 バケット上のパスに書き換えて
  5. –output-template-file オプションで指定した packaged.yaml として出力

という処理が走ります.

sam.yaml の CodeUri は src/ でしたが、コマンドによって出力される packaged.yaml の CodeUri は s3://YOUR_BUCKET_NAME/2a32fe99ed081c4bc95433eeabc76bce のような値になります.

aws cloudformation deploy

package コマンドでデプロイの準備が整ったら、deploy コマンドでデプロイします.

# 折り返して記述してますが 1 行のコマンドです

$ aws cloudformation deploy \
    --template-file ./packaged.yaml \
    --stack-name ${YOUR_STACK_NAME} \
    --region ap-northeast-1 # たとえば東京リージョン

–stack-name は Stack という CFn のデプロイ単位のようなものを指定するためのもので、任意の名前を設定します. まだ AWS 上に作成していないスタック名の場合は新規でデプロイ、AWS 上に作成済みのスタック名の場合は既存リソースが更新されるような挙動になります. 例えばテンプレートや Lambda のコードを変更した場合もこの package/deploy コマンドを再度実行すれば良いだけなので楽ですね.

また、deploy コマンドは AWS リソースの作成が完了するまで自動で待ってくれるので、例えば deploy が完了した後にインテグレーション・テストを流すような CI/CD パイプラインが作りやすいと思います.

(この package/deploy コマンド、AWS SAM ではない普通の CFn テンプレートのデプロイにも使えます. 僕は最近では普通の CFn テンプレートもこちらのコマンド群を使ってデプロイしています. 昔ながらの create-stack/update-stack コマンドに慣れきっていた同僚はこれに混乱してたので AWS さんこの辺もちょっとうまいこと整理できn)

(しかも AWS SAM テンプレートの中に普通の CloudFormation テンプレート仕様のリソースも書けるんですよ. これがまた同僚の混乱を招いていたので AWS さんこの辺もいい感じに整理でk)

AWS SAM Local というツール

AWS SAM Local

簡単にデプロイできるのは分かりましたが、開発中はどうしましょう. デプロイしないと API Gateway と Lambda の連携はテストできないのでしょうか. そこで登場したのが AWS SAM Local というツール(現時点では Public Beta)です.

このツールでできることの例としていくつかコマンドを挙げてみます.

sam local start-api
AWS SAM テンプレートを読み込んで擬似的な API Gateway をローカルにたてることができます
sam local invoke “Func” -e event.json
任意のイベントをインジェクトしてローカルで Lambda 関数を走らせることができます

他にも Lambda 関数をステップ実行できたり、AWS CLI がわりに package/deploy コマンドを使えたりと様々な機能があるので、ぜひ GitHub のドキュメンテーションも読んでみてください. このドキュメンテーション、アニメーション GIF が載ってたりするので機能イメージ掴みやすいと思います. 他にも AWS SAM Local リリース時の AWS 公式ブログ紹介記事2や AWS ドキュメント3なども一読すると良いかもです. 公式ブログの紹介記事ではローカル環境で動かせる DynamoDB である DynamoDB Local とあわせて使う話にも触れられていたのでチュートリアル的に読むのにも最適です.

また、一時期話題になった LocalStack なんかもあわせて使うと、より良いローカル開発/テスト環境が手に入りますね.

Serverless Application Repository という新サービス

年次の AWS 公式テック・カンファレンスである re:Invent 2017 で発表された4新しい AWS サービスの 1 つで、現在 Public Preview というステータスです.

AWS SAM で定義されたサーバーレス・アプリケーションを公開したり、公開されているサーバーレス・アプリケーションをマネコン数クリックで自身の AWS アカウント上にインストールしたりということができるようになるそうです.

ユースケースとしてパッと思いつくのは以下のようなパターンでしょうか.

1. オープンソースで公開した自分のツールを使ってもらいやすく

僕にとってはこれが一番嬉しいです.

これまでサーバーレス・アプリケーションはオープンソースとして公開したとしても、実際にユーザーがそれぞれの AWS 環境上にインストールするにはわりと高いハードルがありました. この辺は Serverless Framework とかを使ってても同じですね. 慣れている人にとってはすぐですが、それがサーバーレスかどうかには興味なく単にアプリケーションを使いたいだけのような人にとってはインストールすらできずに諦めるということがそれなりにある気がします.

AWS 上で動作することを前提としたサーバーレス・アプリケーションを開発/公開している人にとっては、ユーザーに使ってもらうための最初の大きな障壁を取り除ける可能性があるのでとってもありがたい話ですね.

2. SaaS ベンダーが自社プラットフォームとお客の AWS 環境をつなぐ何かを配る

ちょっとわかりにくいですね.

例えば SaaS ベンダーが Lambda 関数をお客に配ってそれをソリューションの一部として提供しているとします. 配った Lambda 関数をお客側 AWS 環境にインストール/セットアップしてもらうことで、お客の AWS 環境から情報を吸い出して SaaS プラットフォーム側に送ったり、逆に SaaS プラットフォーム側から Webhook でお客の AWS 環境上で何かを動かしたり、というような感じです.

要はお客の AWS 環境と自社の SaaS プラットフォームの Glue としてサーバーレス・アプリケーションを配布しているような形です.

他にも SaaS ではなくサーバーレス・アプリケーションそのものをパッケージ製品として販売しているような会社もあるかもしれません.

これを実現するためには、お客にドキュメントを読みながらセットアップしてもらったり、お客から IAM ユーザーを提供してもらって代わりにベンダー側でセットアップを行ったり、ということが必要になります. しかし Serverless Application Repository が公開されればお客はボタン数クリックでベンダーの提供するサーバーレス・アプリケーションをインストールできるようになるので、お客もベンダーもハッピーになれます.

また、Serverless Application Repository はインストール済みのアプリケーションを更新していくことにも対応しているらしいので、継続的に最新のアプリケーションを提供できそうです.

AWS 公式ブログによると Serverless Application Repository でのアプリケーションの公開はグローバルとプライベートが選べるらしいので、契約しているお客にだけ公開する、ということもできるようになるんでしょうか. この辺まだあんまり情報ないので全然違ったらごめんなさい.

追記: AWS Serverless Application Repository のウォークスルー記事も書きました

例のあのリスはなんなのか

例のリス

例のリス

『AWS サーバーレス・コンピュート(Lambda, API Gateway, IoT…)チームの GM、Tim Wagner さんがリスを好きだから』このキャラクターだそうで、他に理由はないそうです.

ちなみに Tim Wagner さんと言えば Serverlessconf NYC 2016 においてサーバーを破壊するパフォーマンスを行ったことでも有名な方ですが、そんな彼のご自宅には 9 匹ものリスがいるそうです. すごいですね.


まとめ

AWS SAM 使ってるお友達を募集中です. みんな Serverless Framework なんだもん


  1. AWS SAM の詳細な仕様は GitHub のこちらのドキュメントを見るのがオススメです. ↩︎

  2. 日本語訳版はこちら. 日本語版は DynamoDB Local のとこのコマンドがなんか変なのでオリジナルの記事がいい気がします. ↩︎

  3. Test Your Serverless Applications Locally Using SAM Local (Public Beta) - AWS Lambda ↩︎

  4. Get Ready for the AWS Serverless Application Repository | AWS News Blog ↩︎