APIGatewayの統合リクエストとLambdaの組み合わせでバックエンドを構成することが多いのですが、最近になってバージョニングが出来ることを知り、いろいろと調べてみた結果を書き連ねていきたいと思います!
やりたいこと
今回書く記事は以下のようなことをやりたい場合に有効です。
- APIGateway+Lambdaで構成されたサーバをバージョニングしたい
- バージョニングされたサーバにはそれぞれ異なるエンドポイントを持たせたい
構成
Browser(Chrome)
APIGatewayを直接呼ぶために使います。 実運用では巷に溢れるフロントエンドフレームワークがこの役割を担当するかと思います。 今回はフロントについては主題ではないので、ブラウザと呼称して説明をします。
APIGateway
フロントからのリクエストを受けたら、それをLambdaへ横流しするプロキシサーバとして使います。
APIGatewayは2つのステージを用意します。
- Devステージ:最新バージョンのLambdaを参照します。
- Prodステージ:旧バージョンのLambdaを参照します。
Lambda
ビジネスロジックを担当します。 今回は単純な文字列をレスポンスするだけのサーバとして作ります。
Lambdaは2つのバージョンを用意します。
- バージョン$LATEST: 最新バージョン。呼び出すと「"See you, world!"」とレスポンスしてくれます。APIGatewayのDevステージと紐づけます。
- バージョン1: 旧バージョン。呼び出すと「"Hello, world!"」とレスポンスしてくれます。APIGatewayのProdステージと紐づけます。
下準備
Lambdaを作成
まずはざくざくとLambda関数を新規作成していきます。
- 関数名: HelloWorld
- ランタイム: Node.js 12.x
exports.handler = async (event, context, callback) => { const responseBody = "Hello, world!"; var response = { "statusCode": 200, "body": JSON.stringify(responseBody), "isBase64Encoded": false }; callback(null, response); };
「Hello, world!」を返すだけの単純なLambda関数を作ります。 この関数をAPIGatewayごしに実行できるようにしていきます。
APIGatewayの準備
続いてAPIGatewayを作成します。
- API名: HelloWorld
- 統合タイプ: Lambda関数
- Lambda プロキシ統合の使用: 有効
- デプロイするステージ: Prod, Dev
APIGatewayが作成できたら、Lambdaプロキシ統合の設定をしたAPIGatewayをステージProd
とステージDev
に対してデプロイします。
デプロイができたらAPIのエンドポイントがステージエディター上に公開されますので、そのURLをコピペしてブラウザで開いてみます。
ブラウザの画面に"Hello, world!"
が表示されたら正しく通信できています。
バージョン管理をする
では、ここからバージョニングの為の設定をしていきましょう。
Lambdaのバージョンを分ける
Lambdaの管理ページから「アクション」→「新しいバージョンを発行」を選択します。
既に説明文に書かれている通り、現在のLambdaの最新バージョン($LATEST)のスナップショットを作成しようとしているところです。 $LATESTというバージョンは最初からデフォルトで用意されており、直近にデプロイしたLambdaのソースコードは自動的に$LATESTというバージョンに適用されます。
「バージョンの説明」にはLambdaのバージョンを明確に区別する為に、開発者が分かりやすいようなラベルを付けておくことをお勧めします。
今回はAPIGatewayのProdステージのバージョンであることを示す為、Prod
と入力しました。
バージョンが作成されると自動的に作成されたバージョンの情報が表示されます。
ARNの末尾に:1
が付きます。
1
という数字はLambdaが自動的に連番で割り振られるバージョンの番号です。
次回発行時は2
、その次は3
…といった具合に発行されます。
バージョン:1
というボタンを押すと、現在のバージョン一覧が確認できます。
各バージョンをクリックするとそのバージョンの詳細ページへ遷移します。
先ほど付けた「バージョンの説明」もセットで表示されていますね。
なお、発行したバージョンのソースコードは一切編集ができません。
編集できるのは最新バージョンである$LATEST
のソースコードのみです。
Lambdaのエイリアスを作成する
APIGatewayが特定バージョンを呼び出す為には、Lambdaのエイリアスを作成する必要があります。
「アクション」→「エイリアスを作成」を選択します。
「名前」には先ほどのバージョン同様に分かりやすい名前を付けてあげましょう。
今回はLambdaのバージョンの説明と同様にProd
と名付けました。
「バージョン」にはエイリアスと紐づけたいLambdaバージョンを指定します。
先ほど作成した1
を指定したら、「保存」を押しエイリアスを作成します。
エイリアスを作成すると作成したエイリアスの詳細ページが表示されます。 「エイリアス」ボタンからエイリアスとバージョンが紐づいたことが確認できます。
また、ARNは末尾に:Prod
が付与されたものが発行されました。
このARNを利用し、APIGatewayから特定のLambdaのバージョンを呼び出すように設定していきます。
最新バージョンのLambdaのソースを更新
バージョン:$LATESTの詳細ページへ移動し、関数コードを以下のように修正してデプロイしておきます。
console.log('Loading function'); exports.handler = async (event, context, callback) => { const responseBody = "See you, world!"; var response = { "statusCode": 200, "body": JSON.stringify(responseBody), "isBase64Encoded": false }; callback(null, response); };
レスポンスする文字列がSee you, world!
に変わっただけです😑
今回はこのレスポンスを返すLambdaが最新バージョンということになります。
APIGatewayからLambdaのエイリアスを呼び出す
APIGatewayの「リソース」→「ANY」→「統合リクエスト」の画面へ移動し
Lambda関数の末尾に${stageVariables.alias}
と追記してチェックボタンを押します。
この${stageVariables.alias}
は各ステージに定義されたalias
という名前のステージ変数の値を指します。
設定が保存されるとウィンドウが表示され、Lambdaに権限を付与するAWS CLIコマンドを実行しろと指示されますので表示されているコマンドをコピーします。
ただし、--function-name
で指定した値の末尾の${stageVariables.alias}
は紐づけたいLambdaのエイリアスを直接記述する必要があります。
今回は${stageVariables.alias}
をLambdaエイリアスのProd
に置き換えておきましょう。
AWS CLIを使う場合、ローカル環境から利用するのも良いですが、最近AWS CloudShell
というブラウザ上からAWS CLIを実行できる環境が用意されましたので、せっかくなので使っていきます。
AWSコンソールの右上のターミナルのアイコンをクリックするとAWS CloudShellが起動します。
先ほどコピーしたコマンドをペーストして実行すればLambdaに権限が付与されます。 なお、この権限付与はLambdaのエイリアス毎に毎回指定が必要です。ちょっと面倒ですね…🤤
APIGatewayのProdステージにデプロイ
Lambdaエイリアスを参照するようリソースを修正しましたので、Prodステージにデプロイします。
デプロイできたら、Prodステージの「ステージ変数」に
alias
という名前のステージ変数を追加し、値をProd
と指定します。
このalias
は統合リクエストのLambda関数で指定した${stageVariables.alias}
の参照先です。
Prod
を指定しましたので統合リクエストのLambda関数はHelloWorld:Prod
を指定したことになり、バージョン:1のLambda関数が呼び出されるようになります。
動作確認してみる
では、APIGatewayのProdステージのURL(https://***.execute-api.***.amazonaws.com/Prod)をブラウザから叩いてみます。
Hello, world!
が出ました。つまりLambdaのバージョン:1(エイリアス: Prod)が呼ばれています。
一方で、APIGatewayのDevステージのURL(https://***.execute-api.***.amazonaws.com/Dev)をブラウザから叩いてみるとどうでしょうか。
See you, world!
が出ました。ということはLambdaのバージョン: $LATESTが呼ばれています。
DevステージはLambdaのエイリアスを指定していないので、自動的に$LATESTが呼ばれました。
長かったですが、これでLambdaのバージョンごとにAPIGatewayのエンドポイントを分けることができました。
最後に改めて構成図を置いておきます。
あとがき
最初はエイリアス、バージョンの概念や関係性で混乱しましたが、手を動かして構成するうちに理解が深まってきました。 やはりまずは手を動かすのが理解の早道ですね!😆