プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

SAM で Lambda 関数のみのアプリケーションをデプロイ

AWS Toolkit または SAM CLI を使って、Lambda 関数をデプロイできるようになりました。

次は、 API Gateway + Lambda の Hello World のサンプルから一歩進めて、 Lambda 関数のみの構成をデプロイしてみます(進んでんのか?)。

  • WSL, Ubuntu 24.04.1
  • SAM CLI 1.131
  • AWS CLI 2.2.42

SAM CLI でのアプリケーション作成

VSCode の SAM アプリケーションの新規作成では、 Lambda 関数のみのテンプレートがないので、コマンドラインから実行します。

mor@DESKTOP-DE7IL4F:~/tmp/sam_samples$ sam init

You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.

Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1

Choose an AWS Quick Start application template
        1 - Hello World Example
        2 - Data processing
        3 - Hello World Example with Powertools for AWS Lambda
        4 - Multi-step workflow
        5 - Scheduled task
        6 - Standalone function
        7 - Serverless API
        8 - Infrastructure event management
        9 - Lambda Response Streaming
        10 - Serverless Connector Hello World Example
        11 - Multi-step workflow with Connectors
        12 - GraphQLApi Hello World Example
        13 - Full Stack
        14 - Lambda EFS example
        15 - DynamoDB Example
        16 - Machine Learning
Template: 6

SAM CLI であれば、『Standalone function』が選択できます。しかし、

Which runtime would you like to use?
        1 - dotnet8
        2 - dotnet6
        3 - nodejs22.x
        4 - nodejs20.x
        5 - nodejs18.x
        6 - nodejs16.x
Runtime: ^CAborted!

mor@DESKTOP-DE7IL4F:~/tmp/sam_samples$

なんとこの場合、ランタイムは dotnet と Node.js のみです。Python がない。なんとまあ。

Hello World サンプルからの作成

そこで、世の中の人はどうしているのか調べてみると、

などの記事が見つかります。

要は、 Hello World のテンプレートで新規アプリケーションを作成して、 API Gateway に関する記述を削除する、というやり方ですね。

ということで、やってみます。

まずは、 Hello World アプリケーションを作成します。VSCode でもコマンドラインでもお好きなほうで OK です。ランタイムは Python を選んでおきます。アプリケーションができたら、 template.yaml を編集します。

変更前

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-lambda-only

  Sample SAM Template for sam-lambda-only

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

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: python3.13
      Architectures:
        - x86_64
      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

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  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

変更後

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-lambda-only

  Sample SAM Template for sam-lambda-only

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  LambdaOnlyFunction:
    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:
      FunctionName: "lamuda-only"
      Description: "sample lambda function only application created by SAM"
      CodeUri: lambda-src/
      Handler: app.lambda_handler
      Runtime: python3.13
      Architectures:
        - x86_64
#      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

#Outputs:
#  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
#  # Find out more about other implicit resources you can reference within SAM
#  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
#  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

のようにしました。主な変更点としては、

  • Resources の 論理名を HelloWorldFunction から LambdaOnlyFunction に変更
  • Resources の LambdaOnlyFunction 定義の Properties に FunctionName と Description を追加
  • Resources の LambdaOnlyFunction 定義の Properties の CodeUri を適切な名前に変更
  • Resources の LambdaOnlyFunction 定義の Events 以下を削除
  • Outputs を無くす

としました。

1つ目の Resources の HelloWorldFunction の部分は、論理名として扱われるとのことなので、わかりやすい名前に変えてみました。

また、3つ目の CodeUri ですが、SAMで扱う分には、関数本体のファイルがあるフォルダを指せばよさそうです。

この変更に伴い、ローカルのフォルダ名も lambda-src に変更しました。

4つ目の Events の記述があることで API Gateway のリソースが作成されるので、ここを削除しています。

あと、デプロイは VSCode でやるつもりなんですが、この場合デフォルトだと S3 バケットにフォルダが作られないので、 samconfig.toml に s3_prefix を追加しておきます。

アプリケーション作成直後

[default.deploy.parameters]
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
resolve_s3 = true

s3_prefix を追加

[default.deploy.parameters]
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
resolve_s3 = true
s3_prefix = "lambda_only_sample"

デプロイ

これで一度デプロイしてみます。デプロイは、 VSCode からやってみました。

こんな感じで問題なくデプロイできますね。なお、 Outputs がないため、画面に ARN 等が表示されていないことがわかります。こちらの記事だと、 Outputs を無くせなかったとあったのですが、 SAM CLI のバージョンアップに伴い仕様が変わったんですかね?今はなくしても問題ないようです。

aws 側も確認してみます。

CloudFormation の sam-lambda-only スタックを表示すると

こんな感じになり、 Lambda と IAM Role のみが作成された形になっています。また、この論理ID(論理名)が、先ほど template.yaml で変更した LambdaOnlyFunction に対応するものになっていることもわかります。

Lambda を見てみると、

関数名が FunctionName で指定した lamuda-only になっていることがわかります(間違えたつづりにしています)。API Gateway がないこともわかります。また、追加した Description も反映されています。

ただ、残念ながら、 samconfig.toml に設定した s3_prefix は消えてました。デプロイ時に samconfig.toml を書き換えるためなんでしょうね、きっと。このため、 S3 バケットの直下にファイルがアップロードされたようです。

なお、一度デプロイに成功したら、 s3_prefix を追加してデプロイしても『Use default values from samconfig』を選べば反映されました。

テスト

大丈夫だと思いますが、テストしておきます。

VSCode のサイドパネルから aws を選び、 Explorer で Lambda 関数を表示させます。

ここで、実行ボタン(横向き△のボタン)にマウスをホバーさせると『Invoke in the cloud』とあるので、これをクリックすることで、 aws 側の関数を呼び出すことができそうです。

やってみます。実行ボタンを押すと、

のような画面が表示されます。今回は payload に何も指定せず、そのまま『Remote Invoke』ボタンを押します。

するとこんな感じで応答が出力されました。CloudWatch ログにも実行したログが残ってますし、大丈夫そうですね。