Amazon Web Services ブログ

AWS SAM Accelerateによるサーバーレス開発の加速

サーバーレスアプリケーションの構築は、開発者のコードテストの考え方を変えます。以前は、開発者はローカルで完全なインフラストラクチャをエミュレートし、テストの準備ができたコードのみをコミットしていました。しかしながら、サーバーレスでは、ローカルでのエミューレートがより複雑になる可能性があります

本ブログでは、 AWS SAM Accelerateを利用して本番環境のサービスに対して、クラウド上でサーバーレスアプリケーションをテストすることで、ほとんどのローカルエミュレーションをバイパスする方法を紹介します。AWS SAM Accelerateの目的は、 sam sync、インクリメンタルビルド、開発者向けの集約されたフィードバックにより、テストのためのインフラの精度を高めることです。AWS SAM Accelerateは、クラウドを開発者に誘うのではなく、開発者をクラウドに誘います。

AWS SAM Accelerate

AWS SAMのチームは、ローカルマシンでクラウドをエミュレートするより良い方法を求める開発者の声に耳を傾け、クラウドに対してテストする事が最善の道だと信じています。これを念頭に置いてAWS SAM Accelerateのベータ版リリースを発表できたことを嬉しく思います。

以前は、変更のたびに発生するデプロイまでのレイテンシーにより、開発者は他の選択肢を探していました。AWS SAM Accelerateはレイテンシーを削減し、開発者がクラウド上にある本番環境のAWSサービスに対して素早くコードテストが可能な一連の機能です。

様々なオプションを説明するために、本ブログでは“Blog”と呼ばれるサンプルアプリケーションを利用します。 デモプロジェクトをダウンロードして、自分のバージョンのアプリケーションを作成してみてください。AWS SAMの最新バージョンと Python 3.9が インストールされている必要があるので注意してください。AWS SAM Accelerateは他のランタイムでも動作しますが、このサンプルではPython3.9を利用します。

前提条件の設定後、以下のコマンドでデモプロジェクトを立ち上げます:

  1. blogというプロジェクトフォルダを作成
    mkdir blog && cd blog
  2. 新しいAWS SAM プロジェクトを初期化:
    sam init
  3. Custom Template Locationでオプション2を選択
  4. 場所にhttps://github.com/aws-samples/aws-sam-accelerate-demoを入力

AWS SAMはサンプルプロジェクトを現在のフォルダにダウンロードします。blogアプリケーションが配置できたら、AWS SAM Accelerateを試す事ができます。

AWS SAM sync

AWS SAM Accelerateの最初の機能はsam syncと呼ばれる新しいコマンドです。このコマンドはAWS SAMテンプレートで宣言されたプロジェクトをAWSクラウドに同期します。しかし、sam syncはコードと設定を区別しています。

AWS SAMはコードを次のように定義しています:

それ以外は設定とみなされます。以下のsam syncオプションの説明では、sam syncがどのように設定の同期とコードの同期を区別しているかを表しています。出来上がったパターンはAWS SAMを利用してクラウドでコードをテストする最速の方法です。

SAM syncの利用 (オプション無し)

オプション無しのsam syncコマンドは、sam deployコマンドと同様に全てのインフラストラクチャとコードをデプロイまたは、アップデートします。ただし、sam deployとは異なり、sam syncAWS CloudFormation変更セットプロセスをバイパスします。これを確認するには、次のコマンドを実行します::

sam sync --stack-name blog

AWS SAM sync with no options

オプション無しのAWS SAM sync

最初に、sam syncsam buildコマンドを利用してコードをビルドし、アプリケーションがクラウド上に同期されます。

Successful sync

同期の成功

code, resource, resource-idフラグを付けたSAM syncの利用

sam syncコマンドはインフラストラクチャのアップデートなしに、コードの変更をクラウドに同期させることもできます。このコード同期はサービスのAPIを利用して、CloudFormationをバイパスする事で、AWS SAMは数分ではなく数秒でコードを更新する事ができます。

コードを同期するには、--codeフラグを利用します。これはAWS SAMにスタック内の全てのコードリソースを同期するように指示します:

sam sync --stack-name blog --code

AWS SAM sync --code

codeフラグを付けたAWS SAM sync

sam syncコマンドは存在する各コードタイプを検証し、ソースをクラウドに同期します。この例では、API GatewayのREST APIと2つのLambda関数を利用しています。このプロジェクトには外部のOpenAPIファイルが存在しないため、AWS SAMはREST APIをスキップします。ただし、Lambda関数とその依存関係は同期されます。

同期されるリソースを制限するには、--resourceフラグと --codeフラグを利用します:

sam sync --stack-name blog --code --resource AWS::Serverless::Function

SAM sync specific resource types

特定リソースタイプのSAM sync

このコマンドは同期の対象をLambda関数に限定します。他に利用可能なリソースは、AWS::Serverless::Api、AWS::Serverless::HttpApiAWS::Serverless::StateMachineです。

より限定的にするには、--resource-idフラグを利用する事で、ある特定リソースをターゲットにする事ができます:

sam sync --stack-name blog --code --resource-id HelloWorldFunction

SAM sync specific resource

特定リソースのSAM sync

今回のsam syncGreetingFunctionを無視して、コマンドの--resource-idフラグで宣言されたHelloWorldFunctionのみをアップデートします。

watchフラグを付けたSAM syncの利用

sam sync --watchオプションは、AWS SAMにファイルの変更を監視させ、変更が検出されると自動的に同期するように指示します。変更内容に設定の変更が含まれる場合は、AWS SAMはsam syncコマンドと同等の標準的な同期を行います。変更内容がコードのみの場合は、AWS SAMはsam sync --codeコマンドと同等のコードの同期を行います。

初めて--watchフラグ付きでsam syncコマンドを実行した場合、AWS SAMは最新のコードとインフラストラクチャがクラウド上にあるかを確認します。その後、コマンドを終了するまで、ファイルの変更を監視します:

sam sync --stack-name blog --watch

Initial sync

初回の同期

変更を確認するには、HelloWorldFunction (hello_world/app.py) のコードを修正し、レスポンスを以下のようにアップデートします:

return {
  "statusCode": 200,
  "body": json.dumps({
    "message": "hello world, how are you",
    # "location": ip.text.replace("\n", "")
  }),
}

ファイルを保存すると、sam syncがその変更を検知し、HelloWorldFunctionのコードをクラウドに同期します。

AWS SAM detects changes

AWS SAMが変更を検知

Auto dependency layer nested stack

最初の同期の際に、AwsSamAutoDependencyLayerNestedStackという論理リソース名があります。この機能は、コードをより効率的に同期するのに役立ちます。

Lambda関数を扱う場合、開発者はLambda関数のコードと、Lambda関数に必要な依存関係を管理します。AWS SAM Accelerateが発表される以前は、依存関係のためのLambdaレイヤーを開発者が作成しないと、更新のたびに依存関係が関数のコードと一緒に再アップロードされていました。しかし、sam syncを利用すると、依存関係が自動的に一時的なレイヤーに移動されるので、レイテンシーが軽減されます。

Auto dependency layer in change set

変更セットのAuto dependency layer

最初の同期の際に、sam syncはスタック内の各Lambda関数のLambdaレイヤーを維持する単一のネストされたスタックを作成します。

Auto dependency layer in console

コンソールのAuto dependency layer

これらのレイヤーは、いずれかのLambda関数の依存関係がアップデートされた時のみアップデートされます。デモのために、GreetingFunctionrequirements.txtファイル (greeting/requirements.txt) を以下のように変更します :

Requests
boto3

AWS SAMは変更を検知して、GreetingFunctionとその一時的なレイヤーをアップデートします:

Auto layer synchronized

Auto dependency layer の同期

Lambdaレイヤーのバージョンを更新する必要があるため、Lambda関数が変更されます。

sam buildを利用したインクリメンタルビルド

AWS SAM Accelerateの2つ目の機能は、SAM buildコマンドのアップデートです。この変更により、依存関係のキャッシュとコードのキャッシュが分離されました。ビルドコマンドはこれらを別々に評価し、変更のあったアーティファクトのみビルドします。

これを試すには、cachedフラグを付けてプロジェクトをビルドします:

sam build --cached

The first build establishes cache

初回のビルドでキャッシュを確立

最初のビルドでは、キャッシュがないことを認識し、依存関係をダウンロードして、コードをビルドします。しかし、コマンドを再実行すると次のようになります:

The second build uses existing cached artifacts

2回目のビルドでは存在するキャッシュアーティファクトを利用

sam build コマンドは依存関係が変更されていないことを確認します。再度ダウンロードをする必要がないので、アプリケーションコードのみビルドします。

最後に、以下のようにHelloWorldFunctionrequirementsファイル(hello_world/requirements.txt)をアップデートします:

Requests
boto3

ビルドコマンドを再実行します:

AWS SAM build detects dependency changes

AWS SAM buildが依存関係の変更を検知

sam buildコマンドは依存関係の要件の変更を検知し、依存関係とコードをリビルドします。

開発者向けの集約されたフィードバック

AWS SAM Accelerateのベータ版の機能の最後は、開発者のフィードバックのためのログ集約機能です。これは、既にあるsam logsコマンドを強化した機能です。Amazon CloudWatch LogsやLambda関数をから収集するだけではなく、API GatewayのログやAWS X-Rayからのトレースを取り出す事が可能になりました。

この機能を試すには、sam logsを実行します:

sam logs --stack-name blog --include-traces --tail

同期の際に出力されるHelloWorldApiのエンドポイントを呼び出します:

curl https://112233445566.execute-api.us-west-2.amazonaws.com/Prod/hello

sam logsコマンドはAWS Lambda関数のログ、Amazon API Gateway RESTの実行ログ、AWS X-Rayのトレースを返します。

AWS Lambda logs from Amazon CloudWatch

Amazon CloudWatchからのAWS Lambdaのログ

Amazon API Gateway execution logs from Amazon CloudWatch

Amazon CloudWatchからのAmazon API Gatewayの実行ログ

Traces from AWS X-Ray

AWS X-Rayからのトレース

全体像

Development diagram for AWS SAM Accelerate

AWS SAM Accelerateの開発フロー

AWS SAM Accelerateを利用すると、アプリケーションの作成とテストがより簡単かつ迅速に行えます。開始するには以下の通りです:

  1. 新しいプロジェクトを開始:
    sam init
  2. 初期のプロジェクトと開発環境を同期:
    sam sync --stack-name <project name> --watch
  3. ログ監視を開始:
    sam logs --stack-name <project name> --include-traces --tail
  4. レスポンスデータやログを使ってテスト
  5. 反復
  6. 同じ手順の繰り返し

注意点

AWS SAM Accelerateは、本日からベータ版提供となります。チームはコミュニティからのフィードバックを得るために、しっかりした実用最小限の製品(MVP)を実装するよう努力してきました。しかし、いくつかの注意点があります。

  1. Step FunctionsによるAmazon State Language (ASL) コードの更新は、現時点ではDefinitionSubstitutionsをサポートしていません。
  2. API Gateway OpenAPI テンプレートは、DefiitionUriパラメータで定義する必要があり、現時点ではpseudo parametersintrinsic functionsをサポートしていません。
  3. sam logsコマンドは、REST APIの実行ログとHTTP APIのアクセスログのみサポートしています。
  4. 関数のコードはインラインではなく、CodeUriパラメータとして別ファイルに定義する必要があります。

Clean up

本例を実行して作成したAWSリソースが不要であれば、デプロイしたAWS CloudFormationスタックを削除する事で、リソースを削除できます。

AWS CloudFormationスタックを削除するには、sam deleteコマンドを使用します。:

sam delete --stack-name blog

まとめ

サーバーレスアプリケーションをテストする場合、開発者はできるだけ早くクラウド上で実施する必要があります。AWS SAM Accelerateは開発者がローカルでクラウドをエミュレートすることから逃れ、クラウド上でのテストの忠実さに移行することを手助けします。

本ブログでは、AWS SAMチームがなぜAWS SAM Accelerateを構築したかの哲学を説明しました。アプリケーション例を示し、クラウドでのテストから障壁を取り除くために設計された様々な機能を紹介しました。

サーバーレスコミュニティを招待して、サーバーレスアプリケーションを構築するためのAWS SAMの改善に協力頂きたいと思います。AWS SAMやAWS SAM CLI(AWS SAM Accelerateを含む)と同様に、このプロジェクトはオープンソースであり、このリポジトリに貢献できます。

サーバーレスコンテンツの詳細については、Serverless Landをご覧ください。

翻訳はPublic Sector Prototyping SA 小泉が担当しました。原文はこちらです。