Amazon Web Services ブログ

AWS Serverless Application Model (SAM) コマンドラインインターフェイス。サーバレスアプリケーションをローカルで構築、テスト、デバッグする

数十年前、6502 アセンブリ言語でコードを何ページも記述しました。コードをアセンブルしてリンクしたら、それをメモリにロードし、戦略的なロケーションでブレークポイントを設定し、すべてが意図どおりに機能することを順に確認することをしていました。最近は、もう非自明なコードを書いたりデバッグしたりする機会がなくなってきたので、このブログ記事をいざ書くとなったときは少し心配しました (実は、数週間先延ばしにしていました)。

SAM CLI
新しい Serverless Application Model (SAM) コマンドラインインターフェイスについて説明したいと思います。説明しながら、AWS Lambda を使用して何かを構築する能力にいくらか自信が持てるようになっていければと思います。 はじめに、用語について見ていきましょう。

AWS SAM は、Serverless Application Model の略称で、AWS 上でサーバーレスアプリケーションを構築するために使用できるオープンソースのフレームワークのことです。単純な YAML テンプレートを使用して、アプリケーション (Lambda 関数、API エンドポイント、DynamoDB テーブル、およびその他のリソース) を記述するための略式構文を提供します。デプロイメント中、SAM は短縮形 SAM 構文を AWS CloudFormation テンプレートに変換して展開します。その後、CloudFormation は信頼性と再現性の高い方法でリソースをプロビジョニングします。

以前は SAM Local として知られていた AWS SAM CLI は、SAM ベースのアプリケーションの構築をサポートするコマンドラインインターフェイスです。また、ローカルでの開発とテストをサポートしており、アクティブなオープンソースプロジェクトでもあります。CLI を使用すると、Python、Node、Java、Go、.NET の中から選択することができ、すぐに始めるのに役立つ健全なテンプレートのコレクションが含まれています。

SAM CLI の sam local コマンドは、Lambda のような実行環境でローカルに関数コードを実行しながら、Lambda 関数と SAM ベースのサーバーレスアプリケーションのローカル呼び出しとテストをサポートします。また、sam local コマンドを使用して、ローカルでサンプルペイロードを生成したり、API をテストするローカルエンドポイントを開始したり、Lambda 関数のテストを自動化することもできます。

インストールと設定
SAM CLI の使い方を示す前に、いくつかのパッケージをインストールする必要があります。sam local で提供されている関数は Docker を利用しているので、仮想化されていない環境で変更を行う必要があります。 設定プロセスの概要を以下に示します。

DockerDocker for Windows の Community Edition をインストールし (512 MB のダウンロード)、docker ps を実行して動作していることを確認します。

PythonPython 3.6 をインストールし、Windows PATH にあることを確認します。

Visual Studio CodeVS Code とそれに伴う Python Extension をインストールします。

AWS CLI – AWS CLI をインストールします。

そして認証情報を設定します。

SAMpip を使用して AWS SAM CLI をインストールします。

変動する部分がすべてインストールされたので、SAM を探索することができます。

SAM CLI の使用
プロジェクト用のディレクトリ (sam_apps) を作成し、最初のプロジェクトを作成するために sam init を実行します。

これにより、内部に必要なすべてのソースファイルと設定ファイルを含むサブディレクトリ (sam-app) を作成します。

hello_world の中に build ディレクトリを作成し、次に requirements で定義されたパッケージをインストールします。build ディレクトリには、SAM Local によってロードされるソースコードと Python パッケージが含まれています。

そして最後の一歩! ソースファイルを build ディレクトリにコピーして、それらをデプロイする必要があります。

アプリ (app.py と空の __init__.py) はすぐに使えるので、ローカルエンドポイントを起動します。

この時点で、エンドポイントはポート 3000 で HTTP 接続を待機しており、接続が確立されると Docker コンテナが起動します。build ディレクトリは、Python パッケージをロードし、app.py のコードを実行できるように、コンテナに利用できます。

ブラウザで 「http://127.0.0.1:3000/hello」を開くと、必要に応じてコンテナイメージがダウンロードされ、コードが実行され、ブラウザに出力が表示されます。

その裏側で起こっていることについて説明します。ここでは、コードの呼び出し、イメージのダウンロード、コンテナ内の build ディレクトリのマウント、およびリクエストログなど、すべての重要な手順を確認できます。

コードを変更したり、ブラウザのタブを更新したりすることができ、新しいバージョンが実行されます。

編集/デプロイ/テストサイクルは非常に高速で、これまで以上に生産性が向上します!

ここで覚えておくべき重要なことが一つあります。最初の app.py ファイルは hello_world ディレクトリに作成され、数ステップ前にそれを build ディレクトリにコピーしました。このデプロイメントステップは毎回繰り返したり、build ディレクトリ内のコードが実際に使うものであると判断し、それを直接編集したりすることができます。これは、コードを構築してバージョンを作成すると、ソースコード管理計画に影響します。

現在行われていること
サンプルコードが実行されているので、SAM テンプレート (想像力を働かせて、template.yamlと呼びます) を見てみましょう。ブログ記事のスペースの関係上、Resources のセクションに飛びます。

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/build/
            Handler: app.lambda_handler
            Runtime: python3.6
            Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
                Variables:
                    PARAM1: VALUE
            Events:
                HelloWorld:
                    Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
                    Properties:
                        Path: /hello
                        Method: get

このセクションでは、HelloWorldFunction を定義し、それが見つかる場所 (hello_world/build/)、それを実行する方法 (python3.6) を示し、環境変数を定義および設定できるようにします。次に、関数が指定されたパス (/hello) 上の GET によって生成された HelloWorld イベントを処理できることを示します。

このテンプレートは自動的にリロードされないため、変更すると、SAM Local を再起動する必要があります。ここである程度時間を使って名前とパスを変更し、発生したエラーを観察することをお勧めします。これにより、舞台裏で何が起こっているのかをよく理解し、後の段階で生産性が向上します。

残りのテンプレートには、テンプレート (API ゲートウェイエンドポイント、関数の ARN、関数の IAM ロール) からの出力が記述されます。これらの値はローカル実行には影響しませんが、クラウドの展開には重要です。

Outputs:

    HelloWorldApi:
      Description: "API Gateway endpoint URL for Prod stage for Hello World function"
      Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"

    HelloWorldFunction:
      Description: "Hello World Lambda Function ARN"
      Value: !GetAtt HelloWorldFunction.Arn

    HelloWorldFunctionIamRole:
      Description: "Implicit IAM Role created for Hello World function"
      Value: !GetAtt HelloWorldFunctionRole.Arn

何が起こっているのかをよく理解するまで、これらすべてをそのままにしておいても良いでしょう。

SAM CLI と VS Code によるデバッグ
では、いくつかのインタラクティブなデバッグをする準備をしましょう。 理解するのに多少時間がかかりましたが、この経験が活かされることを願っています。最初のステップは ptvsd パッケージをインストールすることです。

次に、requirements.txt を編集して、アプリが ptvsd を必要としていることを示します (上記のパッケージ名からバージョン番号をコピーしました)。

requests==2.18.4
ptvsd==4.1.4

次に、pip を再実行して、この新しい要件を build ディレクトリにインストールします。

そしてデバッグできるようにコードを修正する必要があります。このコードを既存のインポートの後に追加します。

import ptvsd
ptvsd.enable_attach(address=('0.0.0.0', 5858), redirect_output=True)
ptvsd.wait_for_attach()

最初のステートメントは、デバッガがポート 5858 にアタッチすることをアプリに伝えます。2 番目のコードは、デバッガがアタッチされるまでコードを一時停止します (これを条件付きにすることもできます)。

次に、VS Code を起動し、アプリケーションのルートフォルダを選択します。

今度は、デバッグのために VS Code を設定する必要があります。デバッグアイコンを選択し、DEBUG の横にある白い三角形をクリックし、[設定の追加] を選択します。

Pythonの設定を選択し、ファイルの内容全体 (launch.json) を次のテキストに置き換えてファイルを保存します (File:Save) 。

 {
    // 可能性のある属性については、IntelliSense を活用してください。
    // 既存の属性の説明を表示するには、ホバーします。
    // 詳細については、次の URL を参照してください。https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [

        {
            "name": "Debug with SAM CLI (Remote Debug)",
            "type": "python",
            "request": "attach",
            "port": 5858,
            "host":  "localhost",
            "pathMappings": [
                {
                "localRoot": "${workspaceFolder}/hello_world/build",
                "remoteRoot" : "/var/task"
                }
            ]
        }
    ]
}

今度は、DEBUG メニューからこのデバッグ設定を選択します。

ここまでついてこられてますか? あと少しです!

再び SAM Local を起動し、デバッグポートで待機するように指示します。

VS Code に戻り、コードにブレークポイント (馴染みの F9) を設定します。

一つ覚えておいてください。app.pybuild ディレクトリで開き、そこにブレークポイントを設定するようにしてください。

次にウェブブラウザに戻り、ローカルアドレス (http://127.0.0.1:3000/hello) に再度アクセスします。コンテナがリクエストを処理するために起動し、app.pyを実行します。コードは、wait_for_attach のコールが行われるまで実行され、今度は VS Code の F5 をクリックしてデバッグを開始します。

ブレークポイントがヒットしたので、requests.get コールを 1 ステップ実行し、ip 変数を調べます。

そして F5 を押して続行すると、ウェブリクエストが完了します。ご覧のとおり、VS Code デバッガのフルパワーを使って Lambda 関数を構築してデバッグすることができました。ここでは表面をほとんど傷つけませんでした。これにならい、中断したところから進められることをお勧めします。詳細については、「SAM CLI を使用してサーバーレスアプリケーションをローカルでテストする」を参照してください。

クラウドのデプロイメント
SAM CLI は、完成したコードをパッケージ化し、S3 にアップロードして実行するのにも役立ちます。S3 バケット (jbarr-sam) から始め、sam package を実行します。これによりデプロイメントパッケージが作成され、S3 にアップロードされます。

これには数秒かかります。次に sam デプロイを実行して CloudFormation スタックを作成します。

スタックが既に存在する場合、SAM CLI は Change Setを作成し、それを使用してスタックを更新します。スタックは 1~2 分で準備が完了し、Lambda 関数、API ゲートウェイ、およびすべてのサポートリソースが含まれます。

スタック出力に API ゲートウェイエンドポイントを配置できます。

コードをローカルで実行していたときと同じように、ブラウザでアクセスできます。

sam logs を使用して、スタックと関数の CloudWatch Logs にアクセスすることもできます。

SAM アプリが Lambda コンソールに表示されるようになりました (これは比較的新しい機能です)。

テンプレートとアプリのリソースを一目で見ることができます。

そして、リソース間の関係を見ることができます。

監視ダッシュボードもあります。

Amazon CloudWatch ダッシュボードをテンプレートに追加することで、ダッシュボードをカスタマイズできます (詳しくは、「AWS Lambda Console のアプリケーションの管理」を参照してください)。

それだけではありません
信じられないかもしれませんが、これは SAM、SAM CLI、sam local コマンドを使ってできることのほんの一例に過ぎません。他にも知っておくべきヒントがいくつかあります。

Local Function Invocation – 直接 Lambda 関数を呼び出すことができます。

Sample Event Source Generation – 他の AWS サービス (S3 PUT など) からのトリガーに応答する Lambda 関数を記述している場合、サンプルイベントを生成してそれらを使用して関数を呼び出すことができます。

実際の状況では、出力をファイルにリダイレクトし、必要に応じて追加のカスタマイズを行い、それを使用して関数を呼び出します。

Cookiecutter Templates – SAM CLI は Cookiecutter テンプレートを使用してプロジェクトを作成できます。すぐに始められるように、いくつかの例を作成しておきました。詳細については、「Cookiecutter AWS Sam S3 Rekognition Dynamodb PythonAWS SAM and .NET の Cookiecutter」をご覧ください。

CloudFormation Extensions – AWS SAM はCloudFormation を拡張し、コードとしてインフラストラクチャの恩恵を受けることができます。CloudFormation のresource typesintrinsic functions、およびその他のテンプレート関数のフルスイートを使用するための信頼性と再現性の高いデプロイメントとパワーが得られます。

Built-In Best Practices – コードモデルとしてのインフラストラクチャに付随する利点に加えて、コードレビュー、AWS CodePipeline を通じた安全なデプロイメント、および AWS X-Ray を使用したトレースといったその他のベストプラクティスを容易に活用できます。

Deep Integration with Development Tools – サーバーレスアプリケーションを構築するため、AWS SAM を AWS ツールスイートと併せて使用できます。新しいアプリケーションは、AWS Serverless Application Repository で発見できます。SAM ベースのサーバーレスアプリケーションのオーサリング、テスト、およびデバッグには、AWS Cloud9 IDE を使用できます。サーバーレスアプリケーションの展開パイプラインを構築するには、AWS CodeBuildAWS CodeDeploy および AWS CodePipeline を使用できます。また、AWS CodeStar を使用して、自動的に設定されたプロジェクト構造、コードリポジトリ、および CI/CD パイプラインを開始することができます。サーバーレスアプリケーションをデプロイするには、AWS SAM Jenkins plugin を使用し、また Stackery.io’s toolkit を使用して本番実稼働環境のアプリケーションを構築できます。

どうぞお試しください
このツアーを楽しんでいただけたでしょうか。次のサーバーレスプロジェクトで SAM をうまくご活用されることを祈っています。

Jeff;