こんにちは。スリーシェイクの小林です。
本日は AWS Serverless Application Model(以下、AWS SAM)と GitHub Actions を用いて サーバーレス API の作成からデプロイの自動化までを触ってみたいと思います。
AWS SAM とは
AWS SAM とは、AWS でサーバーレスアプリケーションを構築および実行する エクスペリエンスを簡素化および改善するオープンソースのデベロッパーツールです。
AWS SAM の利点としては、AWS のサーバーレスサービスを用いたアプリケーションの開発に特化しており、 AWS SAM CLI を使用してサーバーレスアプリケーションを開発、デバッグ、デプロイすることができます。
サーバーレス API の実装
早速 SAM CLI を使ってサーバーレス API を作成してみましょう。 今回はクイックスタートのために用意されているテンプレートから作成します。
SAM CLI のインストールについては こちら を参照してください。
まずは sam init
でプロジェクトを作成します。
~$ 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
1 - AWS Quick Start Templates
を選択すると、いくつかのテンプレートから作成するリソースを選択できます。
今回は Lambda + API Gateway が含まれる 1 - Hello World Example
を選択します。
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 - GraphQLApi Hello World Example
11 - Full Stack
12 - Lambda EFS example
13 - Serverless Connector Hello World Example
14 - Multi-step workflow with Connectors
15 - DynamoDB Example
16 - Machine Learning
Template: 1
テンプレートを選択した後は、ランタイムやモニタリングの選択に移りますが 今回は以下の通りで進めましたが、こちらはお好みで変えてください。 (変更してもこれ以降の手順が変わることはないです)
Use the most popular runtime and package type? (python3.13 and zip) [y/N]: y
Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: N
Would you like to enable monitoring using CloudWatch Application Insights?For more info, please view <https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html> [y/N]: N
Would you like to set Structured Logging in JSON format on your Lambda functions? [y/N]: N
Project name [sam-app]:
全ての入力を完了すると sam-app
というフォルダが作成されていると思います。
SAM プロジェクトのリソースの確認
本記事の本筋とは逸れますが、先ほどの 1 - Hello World Example
で作成された SAM プロジェクトで作成される AWS リソースをみてみましょう。
AWS SAM で管理・デプロイされる AWS リソースは template.yaml
によってコード管理されています。
AWS::Serverless::Function
というタイプのリソースが Lambda に、Events
プロパティに定義されている Api の定義が Lambda と紐づく API Gateway に対応しており、 今回のテンプレートでは /hello
という GET のエンドポイントをひとつデプロイする構成になっています。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sam-app
Sample SAM Template for sam-app
# 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
CodeUri
とHandler
に定義されている通り Lambda 関数のソースコードは sam-app/hello_world/app.py
に記述されておりlambda_handler
メソッドがエントリーポイントになります。
lambda_handler
メソッドは {"message": "hello world"}
という JSON 文字列を返すだけの単純なものになっています。
# hello_world/app.py (一部抜粋)
return {
"statusCode": 200,
"body": json.dumps({
"message": "hello world",
}),
}
デプロイ時の挙動の修正
デフォルトのままだと、デプロイ時に利用する sam deploy
コマンドにおいて ChangeSet の確認を要求されるため GitHub Actions の実行自体が失敗してしまいます。
samconfig.toml
の deploy.parameters
で定義されている confirm_changeset
を false
に変更し、ChangeSet の確認をせず、そのままデプロイできるようにしましょう。
[default.deploy.parameters]
capabilities = "CAPABILITY_IAM"
- confirm_changeset = true
+ confirm_changeset = false
resolve_s3 = true
ID プロバイダの作成
さて、SAM プロジェクトの下準備が整ったので GitHub Actions 側で必要なものを整えていきます。
まずは GitHub が IAM ロールを使えるように ID プロバイダを作成していきます。
GitHub Actions では OpenID Connect (OIDC) がサポートされています。 OIDC を使用することにより長期間有効なアクセスキーなどを用意することなく AWS 認証を行うことができます。
IAM のメニューから ID プロバイダ
を選択し、プロバイダを追加します。

以下の項目を選択・入力し、プロバイダの作成をします。
プロバイダのタイプ | OpenID Connect |
---|---|
プロバイダの URL | https://token.actions.githubusercontent.com |
対象者 | sts.amazonaws.com |

IAM ロールの作成
GitHub Actions で使用する IAM ロールを作成します。 ロールの信頼関係には、先ほど作成した OIDC の ARN を記載します。

また、Condition
には GitHub のリポジトリ・ブランチ名を入力することで、 指定されたリポジトリ・ブランチからのみしか、本ロールに Assume Role できないよう制限します。
{AccountId}
などと仮置きしている箇所については、適宜お使いのアカウントやリポジトリに置き換えてみてください。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::{AccountId}:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:{GitHubUserName}/{GitHubRepositoryName}:ref:refs/heads/{BranchName}"
}
}
}
]
}
GitHub Actions の作成
GitHub Actions を定義するためには、リポジトリ上の.github/workflows
配下にファイルを配置する必要があります。
今回は .github/workflows/deploy-sam-app.yaml
を作成してみましょう。
name: run sam deploy
on:
push:
branches:
- {BranchName}
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Branch
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: {Region}
role-to-assume: arn:aws:iam::{AccountId}:role/GitHubActionsRole
- name: Deploy
run: |
cd ./sam-app
sam deploy
これでサーバーレス API を含む SAM プロジェクトの作成、そのデプロイを担う GitHub Actions の準備ができました!
デプロイの確認
IAM ロールの Condition
および GitHub Actions で指定したブランチに sam-app
および deploy-sam-app.yaml
をプッシュします。
プッシュしたら GitHub リポジトリの Actions タブから実行状況を確認してみましょう。

今までの設定を済ませていれば自動で GitHub Actions が発火し、デプロイジョブが完了していることを確認できるはずです。
動作確認
さて、AWS コンソールでもデプロイの結果を見てみましょう。 CloudFormation のコンソールから sam-app
というスタックが作成されています。

sam-app
スタックの出力タブを確認すると、API Gateway のエンドポイント情報を見ることができます。
実際にエンドポイントにアクセスすると、Hello World とレスポンスが返ってくることが確認できました!

おわりに
いかがでしたでしょうか。
本記事では触れませんでしたが AWS SAM では Lambda や API Gateway だけでなく、 DynamoDB や StepFunctions など、サーバーレスで提供しているそのほかの AWS サービスもサポートされています。
本記事ではデプロイの自動化をメインに説明したため AWS SAM で作成されたソースコードや使い方自体にはあまり触れませんでしたが、 非常に簡単に AWS リソースを作成・コード管理・デプロイができることを感じていただけたかなと思います。
携わっているプロジェクトでサーバーレスソリューションを検討している方で IaC やデプロイの自動化に悩んでいる方の参考になれば嬉しいです。
次回は、AWS SAM のより深い使い方やそのほかの自動化についても触れていきたいと思います。