【AWS】AWS SAMで「API Gateway + Lambda」構成をテンプレート化する
はじめに
ご覧いただきありがとうございます。阿河です。
最近「サーバレスな構成を複数のアカウントにデプロイする」機会があり、設定ミス/労力の軽減をするためにテンプレート化することは大切だなと改めて実感しました。
以前の記事でCloudFormationで基本的なシングル構成を構築するをテーマとして書きましたが、今回はサーバレス版ということでAWS SAMをテーマに記事を書こうと思います。
対象者
- AWSを運用中
- 構築管理の手間を省きたい
- サーバレス構成に興味がある
概要
- 手作業で「API Gateway + Lambda」構成を作成
- AWS SAMで「API Gateway + Lambda」構成を自動構築する
- リソース確認/動作検証
各種ドキュメントを参考に進めていきます。
1. 手作業で「API Gateway + Lambda」構成を作成
事前準備
- S3バケットの作成
- Cloud9環境の準備
Lambda用のIAMロールを作成
- 信頼されたエンティティタイプ: AWSのサービス
- 一般的なユースケース: Lambda
- ポリシー: AWSLambdaBasicExecutionRole/TranslateFullAccess
- ロール名: ※任意の名前をつけてください
Lambda関数の作成
まずは手動でリソースを作成します。
Lambda関数の中身は、Amazon Translateを利用して「日本語⇒英語」に翻訳するものです。
AWSマネジメントコンソールで、Lambdaのページに移動してください。
関数を作成します。
- オプション: 一から作成
- 関数名: ※任意の名前
- ランタイム: Python3.8
- アーキテクチャ: x86_64
- アクセス制限: ※先程作成したLambda用のロールを付与
関数作成後、設定タブからタイムアウトの秒数を10秒に変更。
続いてコードを作成します。
import json
import boto3
def lambda_handler(event, context):
test_input_text = event['queryStringParameters']['user_input']
trans_client = boto3.client('translate')
res = trans_client.translate_text(
Text=test_input_text,
SourceLanguageCode='ja',
TargetLanguageCode='en'
)
out_text = res['TranslatedText']
return {
'statusCode': 200,
'body': json.dumps({
'trans_text': out_text
}),
'headers': {},
'isBase64Encoded': False
}
クエリパラメータの値を、翻訳対象のテキストとして受け取ります。
受け取ったテキストをAmazon Translateのtranslate_textで翻訳を行います。
API Gatewayの設定
API Gatewayの各機能/詳細については、Black Beltの説明が分かりやすいので、別途参照ください。
- APIタイプ: REST API
- 新しいAPIの作成: 新しいAPI
- 名前: ※任意の名前
- エンドポイントタイプ: リージョン
APIを作成したら、アクションから「リソース」と「メソッド」を追加します。
REST APIは、「/」を最上位としたツリー構造にて、「リソース」を定義します。
各リソースに受け付けるHTTPメソッドを指定します。
今回は「/」配下に「test」というリソースを定義し、メソッドとして「GET」を指定しました。
GETの右横にあるチェックボックスをクリックします。
- 統合タイプ: Lambda関数
- Lambdaプロキシ統合の使用: 有効
- Lambda関数: ※作成したLambda関数を指定
自動で権限設定が行われます。
メソッドリクエストの設定で、URLクエリ文字列パラメータの設定を追加します。
APIをデプロイする
アクションから「APIのデプロイ」を選択します。
ステージを新規作成して、デプロイを実行します。
URLが発行されました。
ステージ作成後に一番初めに表示されるURLでなく、/testの階層に表示されているURLにアクセスを行います。
https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/prod/test?user_input=これはテストです
実際にURLにアクセスしてみます。
URLの指定の際に「?input_text=※渡したい日本語文字列」を追加します。
クエリ文字列パラメータで渡した値が、翻訳されて表示されました。
手動での「API Gateway + Lambda」の構築は完了です。
同様の構成をAWS SAMでテンプレート化していきます。
2. AWS SAMで「API Gateway + Lambda」構成を自動構築する
Cloud9上でディレクトリ構成をつくる
まず作業用のディレクトリと、pythonコードを格納するディレクトリを作成します。
$ cd ~/environment
$ mkdir -p sam-test/sam-test-function
$ cd sam-test/sam-test-function/
pythonファイルを作成
次にsam-test-function配下に、pythonファイルを作成します。
$ vi sam-test-function.py
ファイルの内容は下記の通りです。
import json
import boto3
def lambda_handler(event, context):
test_input_text = event['queryStringParameters']['user_input']
trans_client = boto3.client('translate')
res = trans_client.translate_text(
Text=test_input_text,
SourceLanguageCode='ja',
TargetLanguageCode='en'
)
out_text = res['TranslatedText']
return {
'statusCode': 200,
'body': json.dumps({
'trans_text': out_text
}),
'headers': {},
'isBase64Encoded': False
}
前セクションで手作業で作成したLambdaコードと変わらないので、説明は割愛します。
yamlファイルの作成
次にyamlファイルを作成します。
$ cd ../
$ vi template.yaml
ファイルの中身は以下の通りです。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
Lambda:
Type: AWS::Serverless::Function
Properties:
FunctionName: sam-test-function
Handler: sam-test-function.lambda_handler
Runtime: python3.8
Timeout: 10
CodeUri: ./sam-test-function
MemorySize: 128
Policies:
- TranslateFullAccess
Events:
GetApi:
Type: Api
Properties:
Path: /sam-test
Method: get
RestApiId: !Ref API
API:
Type: AWS::Serverless::Api
Properties:
Name: sam-test-get-api
EndpointConfiguration: REGIONAL
StageName: dev
こちらはAWS SAMのDeveloper Guideを参照します。
AWS SAMはサーバーレスアプリケーション構築用のオープンソースフレームワークで、Lambda関数、API Gateway、DynamoDBなどのリソースを、迅速に記述可能な構文で定義することができます。
AWS SAMはCloudFormationの拡張であるため、CloudFormationのデプロイ機能を利用できます。
テンプレートの構成についてこちらで確認します。
- Transform (必須)
この宣言は、CloudFormationテンプレートファイルをSAMテンプレートファイルとして識別します。 - Globals (オプション)
サーバーレス関数とAPIに共通のプロパティを定義。 - Description (オプション)
テンプレートについての説明。 - Metadata (オプション)
テンプレートに関する追加情報を提供するオブジェクト。 - Parameters (オプション)
実行時に(スタックを作成または更新するときに)テンプレートに渡す値。 - Mappings (オプション)
条件付きパラメーター値を指定するために使用できるキーと関連する値のマッピング。 - Conditions (オプション)
制御する条件 - Resources (必須)
スタックリソースとそのプロパティ。SAMテンプレートでは、 Resourcesセクションに「CloudFormationリソース」と「SAMリソース」の組み合わせを含めることができます。 - Outputs (オプション)
スタックのプロパティを表示するたびに返される値。
今回は「Transform」と「Resources」を記述しています。
合わせて「Resources」部分を個別に見ていきます。
まずAPIの部分です。
API:
Type: AWS::Serverless::Api
Properties:
Name: sam-test-get-api
EndpointConfiguration: REGIONAL
StageName: dev
AWS::Serverless:Apiは、HTTPSエンドポイントを介して呼び出すことができる「AmazonAPIGatewayリソースとメソッドのコレクション」を作成します。
-
Name(オプション)
APIGatewayのRestApiリソースの名前 -
EndpointConfiguration
RESTAPIのエンドポイントタイプ。手作業で作成したときと同様に、リージョンタイプを選択します。 -
StageName(必須)
APIGatewayがURIの呼び出しの最初のパスセグメントとして使用するステージの名前。
次にLambdaの設定を見ていきます。
Lambda:
Type: AWS::Serverless::Function
Properties:
FunctionName: sam-test-function
Handler: sam-test-function.lambda_handler
Runtime: python3.8
Timeout: 10
CodeUri: ./sam-test-function
MemorySize: 128
Policies:
- TranslateFullAccess
Events:
GetApi:
Type: Api
Properties:
Path: /sam-test
Method: get
RestApiId: !Ref API
AWS::Serverless::Functionは、Lambda関数、IAMロール、関数をトリガーするイベントソースマッピングを作成します。
-
FunctionName(オプション)
関数の名前。 -
Handler(条件付き)
実行を開始するために呼び出されるコード内の関数。 -
Runtime(条件付き)
関数のランタイムの識別子。 -
Timeout(オプション)
関数が停止するまでに実行できる最大時間(秒単位) -
CodeUri(条件付き)
関数コードのAmazonS3URI、ローカルフォルダへのパス、またはFunctionCodeオブジェクト。PackageTypeプロパティがZip(デフォルト)に設定されている場合は、CodeUriまたはInlineCode(インラインコード)が必要です。今回はインラインコードではなく、CodeUriを指定。「sam-test-function」のパスを指定しています。 -
MemorySize(オプション)
関数の呼び出しごとに割り当てられたメモリのサイズ(MB単位) -
Policies(オプション)
この関数に必要な1つ以上のポリシーで、関数のデフォルトの役割に追加されます。
今回はAWSマネージドポリシーである「TranslateFullAccess」を追加しています。 -
Events(オプション)
この関数をトリガーするイベントを指定します。こちらを参照します。「同じテンプレート内で作成しているRestApiリソースの識別子」「関数が呼び出されるURIパス」「関数が呼び出されるHTTPメソッド」を指定しています。
以上がテンプレートの説明です。
パッケージング
$ aws cloudformation package \
--template-file template.yaml \
--s3-bucket [※S3バケット名] \
--output-template-file pack_template.yaml
Cloud9でCLIコマンドを入力します。
aws cloudformation packageで、テンプレートが参照するローカルアーティファクト(ローカルパス)をパッケージ化します。ローカルアーティファクトをS3バケットにアップロードします。このコマンドはテンプレートのコピーを返し、ローカルアーティファクトへの参照をアーティファクトがアップロードされたS3 URIに置き換えます。
コマンドの実行結果として、パッケージ化されたyamlファイルが生成されました。
デプロイ
$ aws cloudformation deploy \
--template-file ./pack_template.yaml \
--stack-name sam-test-stack \
--capabilities CAPABILITY_IAM
aws cloudformation deployは、指定されたAWSCloudFormationテンプレートをデプロイします。
コマンドを実行します。
CloudFormationのスタック作成が始まりました。
しばらくするとリソースが作成されます。
3. リソース確認/動作検証
それぞれのリソースを見てみましょう。
- IAMロール
TranslateFullAccessが追加されています。
- Lambda
コードが反映されています。
- API Gateway
API Gatewayもしっかり設定されています。
URLにアクセスしてみます。
無事翻訳されています。
さいごに
以上 手で作成した「API Gateway + Lambda」をテンプレート化できました。
御覧いただき ありがとうございました!!
Discussion