🐬

AWS SAMをはじめる

2024/03/13に公開

久しぶりにSAMを触ったらやっぱり忘れていたので、AWS SAM最初の一歩をまとめておきます。

AWS SAMとは

AWS Serverless Application Model (AWS SAM) は、AWS 上でサーバーレスアプリケーションを構築および実行するデベロッパーのエクスペリエンスを改善するツールキットです。AWS SAM は次の 2 つの主要な部分で構成されます。
AWS Serverless Application Model (AWS SAM) とは

AWS SAMは「 AWS SAMテンプレート」と「 AWS SAM CLI」で構成されています。
AWS SAMテンプレートはAWS CloudFormationをベースに構築される、サーバーレスアプリケーションのインフラストラクチャコードを定義・管理するためのオープンソースフレームワークです。
AWS SAMはテンプレート変換によりAWS CloudFormationを通じてインフラストラクチャのリソースをデプロイできます。
またAWS SAMCLIとは、AWS SAMテンプレートを利用してサーバーレスアプリケーションを構築・実行できるコマンドラインツールです。

AWS SAMでプロビジョニングできるリソース

  • AWS::Serverless::Api
    HTTPSエンドポイント経由で呼び出し可能なAPIGatewayリソース
  • AWS::Serverless::Application
    AWS Serverless Application RepositoryまたはS3バケットからのサーバーレスアプリケーションをCloudFormationのStackリソースとしてデプロイ
  • AWS::Serverless::Connector
    2リソース間の権限を設定
  • AWS::Serverless::Function
    Lambda関数、実行ロール、トリガーとなるイベントソースのマッピング
  • AWS::Serverless::GraphQLApi
    AppSync GraphQLAPIを作成
  • AWS::Serverless::HttpApi
    APIGateway HTTP APIの作成
  • AWS::Serverless::LayerVersion
    Lambda関数に必要なライブラリ、ランタイムコード
  • AWS::Serverless::SimpleTable
    単一属性のPKでDynamoDBを作成。より高度な設定が必要な場合はAWS::DynamoDB::Tableを使用する。
  • AWS::Serverless::StateMachine
    AWS Step Functionステートマシンを作成

参考:AWS SAMリソースとプロパティのリファレンス

SAMをはじめる

前提条件

  • 利用できるAWSアカウントがあること
  • AWS CLIのインストール・AWS認証情報の設定が完了していること
    詳しくはこちら→AWS SAMの前提条件

AWS SAM CLIのインストール

開発者ガイドのAWS SAM CLIのインストールに手順が掲載されています。
こちらには載っていませんが、私はasdfを使用して導入しました。(公式には非掲載のサードパーティツールなので使用は自己責任です)

asdfを使用したAWS SAM CLIのインストール

  1. プラグインを追加する
asdf plugin add aws-sam-cli
  1. インストール可能なバージョンを確認
asdf list-all aws-sam-cli
  1. 対象のバージョンをインストールする
asdf install aws-sam-cli {バージョン}
  1. グローバル環境もしくはプロジェクトのディレクトリで利用するバージョンを指定する
    asdfではインストールしただけでは使えるようにならないので、設定します。
    今インストールできるバージョンの一覧を見る。
asdf list aws-sam-cli

グローバル環境で使うバージョンを指定するには、

asdf global aws-sam-cli {バージョン}

もしくはプロジェクトのルートディレクトリで、

asdf local aws-sam-cli {バージョン}

AWS SAMプロジェクトを開始する

以下のコマンドを実行すると新しいAWS SAMアプリケーションを初期化するためガイドが開始します。

sam init

ガイドに沿って進めるとSAM CLIによって新しいディレクトリが作成されます。
今回はひとまず、hello worldのテンプレートを使用。
作成されたディレクトリに移動して簡単にデプロイしてみます!

ビルドする

以下のコマンドを実行し、デプロイの準備を行います。

sam build

デプロイする

以下のコマンドを実行することでAWS上にリソースをデプロイ。

sam deploy --guided

このオプションでデプロイを実行するとSAM CLIによってアプリケーションの設定構成の入力が求められます。

Stack Name [hello-world]:
AWS Region [us-east-1]:
Confirm changes before deploy [Y/n]:
Allow SAM CLI IAM role creation [Y/n]:
Disable rollback [y/N]:
HelloWorldFunction has no authentication. Is this okay? [y/N]:
Save arguments to configuration file [Y/n]:
SAM configuration file [samconfig.toml]:
SAM configuration environment [default]:

【改めて】SAMで{'Hello': 'World'}を返すAPIをデプロイする

sam initで生成したものとほぼ変わりませんが、HelloWorldを返すLambda関数とAPIGatewayをデプロイする実装を見てみます。

簡単な構成をデプロイ
ランタイムはNode.js v20、TypeScriptを使います。

template.yamlの中身

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 
  hello-world

Resources:
  HelloWorldFunction: # ここでLambda関数を定義
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: hello-world/
      Handler: app.lambdaHandler
      Runtime: nodejs20.x
      Architectures:
        - x86_64
      Events:
        HelloWorld:
          Type: Api # Lambda関数をトリガーするイベントとしてAPIGatewayを定義
          Properties:
            Path: /hello
            Method: get
    Metadata:
      BuildMethod: esbuild
      BuildProperties:
        Minify: true
        Target: "es2020"
        Sourcemap: true
        EntryPoints: 
        - app.ts # hello-world/app.tsにLambda関数のソースコードを書きます

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

hello-world/app.tsの中身

import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';

export const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
    try {
        return {
            statusCode: 200,
            body: JSON.stringify({
                'hello': 'world',
            }),
        };
    } catch (err) {
        console.log(err);
        return {
            statusCode: 500,
            body: JSON.stringify({
                message: 'some error happened',
            }),
        };
    }
};

APIを叩いてみる

sam list endpoints --output json --profile {プロファイル名}

このコマンドを実行するとtemplate.yamlのOutputsセクションで指定した情報を出力することができます。この中でAPIエンドポイントの情報が得られるので、curlコマンドでGETリクエストを送信してみます。
実行結果

$ sam list endpoints --output json --profile dev-cli --region ap-northeast-1
[
  {
    "LogicalResourceId": "HelloWorldFunction",
    "PhysicalResourceId": "hello-world-HelloWorldFunction-XXXXXXXXXXXX",
    "CloudEndpoint": "-",
    "Methods": "-"
  },
  {
    "LogicalResourceId": "ServerlessRestApi",
    "PhysicalResourceId": "XXXXXXXXXX",
    "CloudEndpoint": [
      "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod",
      "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Stage"
    ],
    "Methods": [
      "/hello['get']"
    ]
  }
]

GETリクストを送信

$ curl https://xxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello
{"hello": "world"}

まとめ

AWS SAMを利用することで簡単にAPIをデプロイできます。
基本はインフラストラクチャ定義をtemplate.yamlに記述、必要なソースコードを記述。必要な設定を行い、AWS SAM CLIでコマンド実行によりプロビジョニングやアプリケーションの実行が可能になります。
プロファイル指定など環境設定やローカルでのテスト、変更の同期などその他様々な使い方がありますが、またの機会に!

GitHubで編集を提案
Fusic 技術ブログ

Discussion