- クラウド技術
API GatewayとLambdaの環境構築
- #AWS

目次
構築手順
【エンジニア募集中】フルリモート可◎、売上/従業員数9年連続UP、平均残業8時間、有給取得率90%、年休124日以上 etc. 詳細はこちらから>
大まかな流れ
以下のような流れで説明します。
-
Lambdaの作成
-
途中でIAM Roleの作成
-
-
API Gatewayの作成
-
リソースの追加
-
Lambdaとの連係
-
APIキー認証の追加
-
デプロイ
-
ステージング
-
Lambdaの作成
API Gatewayを作成する場合、API Gatewayのバックエンドを指定する必要があります。
その為、バックエンドをLambdaとする場合にはまずAPI Gatewayからのリクエストを受けるLambdaが必要になります。
今回はとりあえずAPI Gatewayからのデータを受け取り、そのまま返すLambdaをPython3で用意します。
マネジメントコンソールからLambdaのページにアクセスし、「関数の作成」を押します。

今回は予めAWS側で用意されているblueprint(テンプレート)を利用します。
フィルターに「hello」と入力してEnterして、「hello-world-python3」を選択します。

「基本的な情報」では、名前を適当に入力し、ロールは「テンプレートから新しいロールを作成」を選択します。
ロール名も適当に選択した後、今回はポリシーテンプレートを空欄とします。
こちらは空欄でも、最低限Lambdaに必要なアクセス権限は自動的に作成されます。
なお、この後SQSやAWS Batch等別のサービスとの連係を行う予定があれば、ポリシーテンプレートでそれらを選択してもいいです。

下にスクロールし、「関数の作成」を押します。

Lambdaが作成されたら関数のコードを確認します。
eventがリクエスト元から受け取る内容ですが、「hello-world-python3」では3つの値をprint(CloudWatchに記録される)してkey1をreturnするようになっています。

今回はとりあえず入力値をそのまま出力すればいいので下記のように変更します。
1 2 3 4 5 6 |
import json def lambda_handler(event, context): print("Received event: " + json.dumps(event, indent=2)) return event |
すっきりしました。
eventを全てprintし、eventをそのままreturnします。
変更したら、上方にある「保存してテスト」を押します。

イベント名を適当に入力し、下にスクロールして「作成」を押します。


テストを実行します。

テストが成功しました。
実行結果の「詳細」をクリックすると内容が確認できます。
最初にあるのがreturnの内容で、右下のログ出力に含まれるのがprintにてCloudWatchログに出力された内容になります。

以上で、Lambdaの作成と付随するIAM Roleの作成は完了です。
API Gatewayの作成
続けてAPI Gatewayも作成します。
API Gatewayのページへ移動し、「今すぐ始める」を押します。

「新しいAPI」を選択し、API名を適当に入力して「APIの作成」を押します。

APIが作成されました。
初期状態では何もない状態になります。

ここで少し、「リソース」と「メソッド」について説明します。
リソースとは
簡単に説明するとAPIのパスです。
デフォルトでは「/」のみなので、APIのエンドポイントがhttps://api.example.com
だったとすると、この直下へのアクセスとなります。
ここからusers
リソースを追加し、例えばhttps://api.example.com/users
のようにすることが可能です。
リソース配下にリソースを配置してパスを深くすることもできます。
リソースの中にメソッドを定義していきます。
メソッドとは
リソースに対するアクションで、HTTPのメソッド「GET, POST」等と連携します。
例えばusers
リソースのPOSTメソッドを作成すると、https://api.example.com/users
に対するPOSTリクエストがあった際の処理を定義できます。
処理はLambdaへのリクエストはもちろんのこと、API Gatewayでの認証やリクエストbodyの加工などを挟んで、Lambda以外にも別のHTTPエンドポイント等への転送も定義できます。
メソッドは一つのリソースに対して複数定義することができ、例えばusers
リソースのGETメソッドを追加してユーザの追加と参照を一つのリソースで実装することもできます。
この際、API Gatewayでメソッドの設定を分けているので別々のLambdaで処理することもできます。
リソースとメソッドの作成
それでは、リソースとメソッドを作成していきます。
デフォルトのリソース「/」を選択した状態で「アクション -> リソースの作成」を押します。

リソース名を適当に入力し、「リソースの作成」を押します。自動でリソースパスも入力されます。

リソースが作成されたので、続けてメソッドも作成します。
作成したリソースを選択して「アクション -> メソッドの作成」を押します。

HTTPメソッドの選択となるので、POST
を選択してチェックボタンを押します。

セットアップが出てくるので統合タイプ「Lambda関数」とし、LambdaリージョンとLambda関数を適切に入力して「保存」を押します。
関数名は、補完してくれるのでそれをクリックすれば大丈夫です。

API GatewayにLambdaを呼び出す権限を自動で追加してくれるので「OK」を押します。

これでリソースとメソッドが作成できました。
API Gateway内部でのテストを行うため「テスト」を押してテストしてみます。

ページ下方のリクエスト本文に適当なjson(今回は{"test":1}
)を入力して「テスト」を押します。

レスポンスとして、リクエストした内容がそのまま返ってきていることが確認できれば、先ほど作成したLambdaで実行されていることが確認できています。

これでAPI Gateway内部でのテストが完了しました。
しかし、現状ではこのAPI Gatewayは外部からアクセス出来る状態ではありません。
APIのデプロイ
作成したAPIをデプロイして、外部からアクセスできるようにしていきます。
ここでまた少し用語の解説を行います。
デプロイ
APIを外部に公開する作業。
初回デプロイ時にはそのAPIのエンドポイント(URL)が生成されます。
デプロイ時にはその段階のリソース・メソッド等の設定を反映したバージョンが作成され、以後デプロイするたびにバージョンが増えます。デプロイされたバージョンの内容を変更することはできません。
エンドポイントに来るリクエストをどのバージョンで処理するかはステージで関連付けます。
ステージ
エンドポイントとデプロイバージョンを紐付けるエイリアスです。
例えば、dev
とprod
という2つのステージを用意しておき、dev
に最新バージョンのデプロイを行い、prod
は安定したバージョンのままにしておき、開発用とエンドユーザに提示するエンドポイントを分けることができます。
エンドポイントはそれぞれ、https://api.example.com/dev
, https://api.example.com/prod
となります。
リソースは実質ステージの下のリンクとなります。例えばdev
ステージのusers
リソースへのアクセスはhttps://api.example.com/dev/users
となります。
ステージで利用するデプロイバージョンは任意のタイミングで変更が可能なので、ロールバックも簡単に可能です。
それではデプロイに移りたいのですが、API GatewayでAPIをデプロイするとパブリックに公開されます。そのままでは誰でもアクセスできてしまいあまり好ましい状態ではありません。
先にAPIキーを作成し、APIリクエスト時に認証を行うようにします。
メニューから「APIキー」へ移動し「アクション -> APIキーの作成」を押します。

名前を適当に入力し「保存」します。APIキーは「自動生成」で問題ありません。

作成されるとAPIキーが隠れているので「表示」を押してAPIキーを控えます。

続いて作成したAPIキーをメソッドに割り当てます。
先ほど作成したメソッドを開いて「メソッドリクエスト」を選択します。

「APIキーの必要性」で鉛筆アイコンを押して編集します。デフォルトのfalse
からtrue
に変更してチェックボタンをクリックします。

忘れずにチェックボタンを押してtrueに変更されたことを確認したら、「アクション -> APIのデプロイ」でデプロイします。

デプロイされるステージに「新しいステージ」を選択してステージ名を入力し、「デプロイ」を押します。説明は任意で問題ありません。

完了するとステージが作成されるとともに、エンドポイントも作成されています。

さて、この状態でAPIにアクセスできるようになったかと思いきや、APIキーを利用した認証にはもうワンステップ必要です。
使用量プランの設定
ステージで利用できるAPIキーを紐付ける必要があり、これは使用量プランで設定できます。
使用量プラン
使用量プランは個々のAPIキーに対してスロットリングやクォータ制限等を行うことができます。
合わせて、APIキーを利用した認証も行います。
APIキー毎にリクエスト数の上限設定等を行えることから、ユーザ毎契約状況に合わせてプランを変更する、等の利用方法が有ります。
それでは使用量プランのページへ移動し「作成」を押します。

名前を適当に入力します。今回は認証のみのため、「スロットリング」「クォータ」についてはチェックを外して「次へ」を押します。

使用量プランとステージを紐付けます。「APIステージの追加」からAPIとステージを選択してチェックボタンを押し、「次へ」を押します。

続いてAPIキーを紐付けます。「APIキーを使用量プランに追加」からAPIキーを選択してチェックボタンを押し、「完了」を押します。

これでAPIキーも紐付き、利用できる状態となりました。
APIの動作確認
それでは外部からのアクセスを確認してみます。
curl
で確認する場合には、-d
オプションでPOSTのデータを指定でき、-H
でヘッダーを追加できます。
APIキーを送るフォーマットはx-api-key:<api_key>
となります。
APIキーの有無でそれぞれ下記のような実行結果となります。
1 |
# APIキーがない場合
$ curl -d ‘{“test”:1}’ https://api.example.com/dev/test
{“message”:”Forbidden”}
1 |
# APIキーを指定した場合
$ curl -d ‘{“test”:1}’ -H ‘x-api-key:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx’ https://api.example.com/dev/test
{“test”: 1}
1 2 3 4 5 6 7 |
1# APIキーがない場合 2$ curl -d '{"test":1}' https://api.example.com/dev/test 3{"message":"Forbidden"} 4 5# APIキーを指定した場合 6$ curl -d '{"test":1}' -H 'x-api-key:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' https://api.example.com/dev/test 7{"test": 1} |
以上で、実環境に必要な認証の設定も含む手順が確認できたかと思います。
この後やること
さて、一通りの手順を説明しましたが、今後実際に開発を行っていく場合には下記のような内容も行なっていく必要があります。
-
prodステージの追加
-
Lambdaの処理の追加
-
リソースの追加
-
リクエスト・レスポンスのマッピング
-
カスタムドメインの利用
-
などなど
冒頭でも貼りましたが、下記のまとめ等も参考によい開発ライフを!
URL:https://dev.classmethod.jp/articles/getting-start-api-gateway/
【エンジニア募集中】フルリモートも◎(リモート率85.7%)、平均残業8時間、年休124日以上、有給取得率90% etc. 詳細はこちらから>