AWS SAM CLI
zennの記事にあるようなやってみた系の記事を作成して
参考記事
https://zenn.dev/rescuenow/articles/8349deb470470e
zennの記事のタイトル
Terraform で AWS SAM CLIを使って、ローカルでlambdaのテストとデプロイを試してみた
導入
aws sam cliは、lambdaのテストがローカルで簡単にできて便利だったので、terraform + sam cliを使った方法を紹介します。
目次
sam でできること
AWS SAM CLIでLambda関数のプロジェクトを自動生成
Terraform + SAM CLI 構成で作り直す
コード
https://github.com/sandonemaki/aws-sam-cli-for-terraform
SAM 仕組み
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/what-is-sam-overview.html#what-is-sam-cli
AWS SAM CLI とはAWS CloudFormation テンプレートで使用する場合に最適です。Terraform などのサードパーティー製品とも連携します。
新しいアプリケーションプロジェクトを迅速に初期化します。
デプロイ用にアプリケーションを構築します。
ローカルでのデバッグとテストを実行します。
アプリケーションをデプロイします。
CI/CD デプロイパイプラインを設定します。
クラウド内のアプリケーションをモニタリングおよびトラブルシューティングします。
開発中にローカルの変更をクラウドに同期します。
その他にも多くのことを実行できます。
初回導入方法掲載のAWS公式ドキュメントは以下
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/what-is-sam-overview.html#what-is-sam-cli
(中タイトル)AWS SAM CLIでLambda関数のプロジェクトを自動生成
AWS SAM(Serverless Application Model)を使って、Lambda 関数のサンプルプロジェクトを自動生成しました。
テンプレート: Hello World(最もシンプルなもの)
言語: Go / provided.al2023
構造化ログ: JSON 形式で有効化
2. sam build — デプロイ用にパッケージ化
Python のライブラリ(requirements.txt に書かれた依存関係)をダウンロード
成果物は .aws-sam/build/ に格納されます。
3. sam local invoke HelloWorldFunction — ローカルで動作確認
Docker を使って自分の Mac 上に Lambda の実行環境を再現し、実際に関数を動かして確認。
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}
4. sam deploy --guided — AWS に本番反映
実際の AWS 環境に以下のリソース作成
code: sh
aws sam cliをインストール
brew install aws-sam-cli
上記のサイトで下記を体験できる
sam init → sam build → sam local invoke → sam deploy
作成 ビルド ローカルテスト AWSへ本番反映
生成されたファイルの役割:
➜ sam-app tree
.
├── Makefile
├── README.md
├── events
│ └── event.json
├── hello-world
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── main_test.go
├── samconfig.toml
└── template.yaml
サービス リソース名 役割
AWS Lambda
API Gateway ServerlessRestApi HTTP エンドポイントを提供。外部からのリクエストを Lambda に渡す
IAM Role sam-app-HelloWorldFunctionRole-... Lambda が AWS サービスを使う際の権限設定
S3 aws-sam-cli-managed-default-... デプロイ用のコードを一時的に保管するバケット
CloudFormation スタック名: sam-app 上記すべてのリソースをまとめて管理する仕組み
作られた API エンドポイント(外から叩かれないようサンプルにして)
https://mv9wamyn89.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
code:sh
awsのリソースを削除する場合
cd sam-app
sam delete
削除されるもの リソース名
Lambda 関数 sam-app-HelloWorldFunction-...
API Gateway ServerlessRestApi
IAM Role sam-app-HelloWorldFunctionRole-...
CloudFormation スタック sam-app
注意:S3 バケット(aws-sam-cli-managed-default-...)は削除するか聞かれる。
(中タイトル)Terraform + SAM CLI 構成で作り直す
aws公式ドキュメント
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/terraform-support.html
ファイル / ディレクトリ Terraform + SAM CLI 構成では
template.yaml ❌ 不要(Terraform の main.tf が代わり)
samconfig.toml ❌ 不要(sam deploy を使わないため)
初期構成の方針
作るもの(Terraform)
Lambda 関数(Go / provided.al2023)
IAM ロール
ローカルテスト(SAM CLI)
sam local invoke --hook-name terraform で Lambda を直接呼ぶ
後から追加
S3(コードアップロード先)
API Gateway
sam init は SAM 単体(template.yaml ベース)のプロジェクトを生成するためのコマンドなので、今回の構成では使いません。
今回のアプローチ:
Terraform ファイル(.tf)→ 手書き
Go コード(main.go, go.mod)→ 手書き
sam_metadata の null_resource → 手書き
sam init は使わない
step1:構成を考える
code: sh
sam-cli-for-tf/
├── functions/
│ └── hello/
│ ├── main.go
│ └── go.mod
├── events/
│ └── event.json
└── terraform/
├── provider.tf
├── main.tf
└── iam.tf
Step 2:Lambda のコードを書く
code:go
cd functions/hello && go mod init hello && go get github.com/aws/aws-lambda-go
// main.go
package main
import (
"context"
"github.com/aws/aws-lambda-go/lambda"
)
type Response struct {
StatusCode int json:"statusCode"
Body string json:"body"
}
func handler(ctx context.Context) (Response, error) {
return Response{StatusCode: 200, Body: "Hello!"}, nil
}
func main() {
lambda.Start(handler)
}
コードが完成したら
code:sh
# Go の依存解決
# cd functions/hello
go mod tidy
# cd terraform
terraform init
# build
sam build --hook-name terraform --terraform-project-root-path ..
# 「Terraform の設定を読んで、Lambda で動く Go バイナリを作り、ローカルテストできる状態にする」
# 1. Terraform でインフラを解析する — terraform plan を実行して Lambda 関数の情報(ソースの場所・ランタイムなど)を JSON として取得する
# 2. SAM 用の内部テンプレートを生成する — その JSON から template.json を作成し、SAM CLI が Lambda を認識できる形に変換する
# 3. Go バイナリをビルドする — GOOS=linux GOARCH=amd64 go build で Lambda 実行環境(Linux/x86_64)向けにクロスコンパイルする
# 4. バイナリを SAM のビルドディレクトリにコピーする — .aws-sam/build/ に配置することで sam local invoke が使える状態にする
# local test
sam local invoke --hook-name terraform aws_lambda_function.hello -e ../events/event.json
# deploy
terraform apply
ApiGateway
code:sh
sam build --hook-name terraform --terraform-project-root-path ..
cd terraform
terraform plan
terraform apply
# エンドポイント確認
terraform output api_endpoint
# "https://gr4045s3tl.execute-api.ap-northeast-1.amazonaws.com/stg/hello"
curl $(terraform output -raw api_endpoint)
# {"message": "hello world"}%