最近はAPI Gateway+Lambdaによるサーバレス構成を選択することも増えてきています。 その時、インフラ構築はTerraformをよく利用していますが、APIの開発はServerlessFrameworkが使われたりします。
どこまでTerraformで構築し、どこからServerlessFrameworkで構築するか? API Gatewayにどのような設定が必要か? これらの設計をするためには、TerraformやCloudFormationでどのようにAPI Gatewayを設定するか知っている必要があります。 (ServerlessFrameworkのデプロイは、裏でCloudFormationのスタックを作成してAWS環境へ反映しています)
今回は、API Gatewayを構築するためのリソースにどのようなものがあるかご紹介します。
REST APIを設定するリソース一覧
API Gateway全体やREST APIの設定に関わるリソースをTerraformの設定をベースに一覧化しました。横にも長い表なのでご注意ください。
| Terraformリソース | 必須参照先リソース | 任意参照先リソース | CloudFormationリソース |
|---|---|---|---|
| aws_api_gateway_account | (IAM Role) | AWS::ApiGateway::Account | |
| aws_api_gateway_domain_name | (ACM証明書) | AWS::ApiGateway::DomainName | |
| aws_api_gateway_base_path_mapping | domain_name rest_api |
stage | AWS::ApiGateway::BasePathMapping |
| aws_api_gateway_client_certificate | AWS::ApiGateway::ClientCertificate | ||
| aws_api_gateway_vpc_link | (ELB) | AWS::ApiGateway::VpcLink | |
| aws_api_gateway_rest_api | (VPCEndpoint) | AWS::ApiGateway::RestApi | |
| aws_api_gateway_rest_api_policy | rest_api | -(RestApi内のプロパティ) |
|
| aws_api_gateway_resource | rest_api (resource) |
AWS::ApiGateway::Resource | |
| aws_api_gateway_method | rest_api (resource) |
authorizer request_validator |
AWS::ApiGateway::Method |
| aws_api_gateway_integration | rest_api (resource) method |
(Lambda) vpc_link |
-(Method内のプロパティ) |
| aws_api_gateway_method_response | rest_api (resource) method |
-(Method内のプロパティ) |
|
| aws_api_gateway_integration_response | rest_api (resource) method |
-(Method内のプロパティ) |
|
| aws_api_gateway_deployment | rest_api | AWS::ApiGateway::Deployment | |
| aws_api_gateway_stage | rest_api deployment |
client_certificate documentation_version (Logs) |
AWS::ApiGateway::Stage |
| aws_api_gateway_method_settings | rest_api stage |
-(Stage内のプロパティ) |
|
| aws_api_gateway_model | rest_api | AWS::ApiGateway::Model | |
| aws_api_gateway_documentation_part | rest_api | AWS::ApiGateway::DocumentationPart | |
| aws_api_gateway_documentation_version | rest_api | AWS::ApiGateway::DocumentationVersion | |
| aws_api_gateway_authorizer | rest_api | (Lambda) (CognitoUserPool) |
AWS::ApiGateway::Authorizer |
| aws_api_gateway_gateway_response | rest_api | AWS::ApiGateway::GatewayResponse | |
| aws_api_gateway_request_validator | rest_api | AWS::ApiGateway::RequestValidator | |
| aws_api_gateway_usage_plan | rest_api stage |
AWS::ApiGateway::UsagePlan | |
| aws_api_gateway_api_key | AWS::ApiGateway::ApiKey | ||
| aws_api_gateway_usage_plan_key | usage_plan,api_key | AWS::ApiGateway::UsagePlanKey |
CloudFormationのリソースはリソースタイプの名前から対応するものを推測したものになります。
ここからはTerraformのリソースを例に説明してますが、CloudFormationも同じような構成になります。詳細は公式ドキュメントをご確認ください。
上記で、必須参照先リソースは他のリソースを参照する必須項目です。先にそのリソースを定義しておく必要があります。
これを見ると、どの設定がREST APIに紐づき、どの設定が単一のREST APIから切り離されているのかが分かります。
たとえば、aws_api_gateway_authorizerはREST APIごとに作成しますが、aws_api_gateway_domain_nameはREST APIとは独立して作成します。
任意参照先リソースは他のリソースを参照する必須でない設定項目です。
たとえば、aws_api_gateway_methodはaws_api_gateway_authorizerとaws_api_gateway_request_validatorを設定可能なことが分かります。
REST APIの作成とデプロイ
概要
ユーザがAPIを呼び出せるするようにするためには、REST APIを作成してデプロイする必要があります。
AWSコンソールやAWS CLIから構築する場合はAWSの以下ページが参考になるかと思います。
ここでは、以下の作業を行うためにどのリソースを利用するか説明します。
- REST APIを作成する(REST API定義)
- APIのパスと動作を定義する(リソース定義)
- 呼び出し可能な状態にする(ステージへデプロイ)
これらの設定をIaCで行うための主なリソースは以下になります。

一覧にすると以下の通りです。
| No | Terraformリソース | 必須参照先リソース | 任意参照先リソース |
|---|---|---|---|
| ① | aws_api_gateway_rest_api | (VPCEndpoint) | |
| ② | aws_api_gateway_resource | rest_api (resource) |
|
| ② | aws_api_gateway_method | rest_api (resource) |
authorizer request_validator |
| ③ | aws_api_gateway_deployment | rest_api | |
| ③ | aws_api_gateway_stage | rest_api deployment |
client_certificate documentation_version (Logs) |
ここで(resource)と括弧が付いているのは、場合によってaws_api_gateway_resourceではないリソースを参照するためです(後述)。
次から詳しく見ていきます。
① REST APIを作成
まず始めにREST APIを作成します。これはaws_api_gateway_rest_apiリソースになります。
多くのリソースがaws_api_gateway_rest_apiリソースの下に付きます。
resource "aws_api_gateway_rest_api" "test_api" { name = "test-api" }
② リソース定義(APIのパスと動作を定義)
実際にどのようなリクエストに対してどのような動作をするか、REST APIに定義します。
これにはaws_api_gateway_resourceとaws_api_gateway_methodを中心に使います。
aws_api_gateway_resourceでURLパスを定義し、そのURLの各HTTPメソッドに対してどのような動作をするかはaws_api_gateway_methodで定義します。
たとえば、/test/apitest1へのGETリクエストはTerraformで以下のように定義します。
# /testの定義 resource "aws_api_gateway_resource" "test" { path_part = "test" rest_api_id = aws_api_gateway_rest_api.test_api.id parent_id = aws_api_gateway_rest_api.test_api.root_resource_id } # /test/apitest1の定義 resource "aws_api_gateway_resource" "test_apitest1" { path_part = "apitest1" rest_api_id = aws_api_gateway_rest_api.test_api.id parent_id = aws_api_gateway_resource.test.id } # /test/apitest1へのGETリクエスト resource "aws_api_gateway_method" "test_apitest1_get" { rest_api_id = aws_api_gateway_rest_api.test_api.id resource_id = aws_api_gateway_resource.test_apitest1.id http_method = "GET" authorization = "NONE" } # /test/apitest1のGETリクエストへの実際の動作 resource "aws_api_gateway_integration" "test_apitest1_get" { rest_api_id = aws_api_gateway_method.test_apitest1_get.rest_api_id resource_id = aws_api_gateway_method.test_apitest1_get.resource_id http_method = aws_api_gateway_method.test_apitest1_get.http_method type = "MOCK" .... 実際の各種設定 .... }
最後のaws_api_gateway_integrationリソースは先の一覧には記載しませんでしたが、APIメソッドの実際の動作に関する設定です。
リソース(URIパス)を定義するaws_api_gateway_resourceはparent_idで親のリソースを指定するのが必須になります。
ルート(/)のリソースはREST APIを作成した時に定義され、aws_api_gateway_rest_apiのroot_resource_id属性として取得できます。
この時点ではAPIの設計書ができただけのような状態で、実際にアクセス可能なエンドポイントは作成されていません。
③ ステージへデプロイ
実際にステージへデプロイすることで、②で定義したAPIはアクセス可能な状態になります。
AWSコンソール上でAPIのデプロイをしようとすると『API がデプロイされるステージを選択します。』と表示されてステージの選択または新しいステージ名の入力が必須となっています。
しかし、本当はステージを選択しなくてもデプロイメントを作成できます。(ユーザからアクセス可能な状態にするという意味ではステージ選択は必須です)
新規のデプロイに関するAPIを見ると、CreateDeploymentとCreateStageがあります。
ここで、CreateDeploymentにはstageNameという項目がありますが必須ではありません。
CreateDeploymentでstageNameを指定してステージを作成・紐づけすることも、ステージを選択せずに後から別にステージを作成・紐づけることもできます。
(CreateStageはdeploymentIdが必須なので、デプロイメントより先にステージを作成することはできません)

これらの操作を、Terraformではaws_api_gateway_deploymentリソースとaws_api_gateway_stageリソースで実施できます。
CloudFormationだとAWS::ApiGateway::DeploymentとAWS::ApiGateway::Stageのはずです。
(AWS::ApiGateway::Stageのドキュメントを見るとStageNameやDeploymentIdが何でRequired: Noなのか分かりませんが)
Terraformではaws_api_gateway_deploymentリソースのstage_nameを使わずaws_api_gateway_stageリソースを使うことが推奨されています。
更新時にaws_api_gateway_deploymentリソースを作り直す過程で、一時的にステージが消えてしまうことを避けるためのようです。
以下はTerraformでの設定例です。
# 非推奨(stage_name利用) resource "aws_api_gateway_deployment" "test_api_dev1" { rest_api_id = aws_api_gateway_rest_api.test_api.id stage_name = "dev1" # デプロイメントだけでステージを作成する triggers = { deploy_trigger = var.deploy_trigger test_apitest1_get = aws_api_gateway_integration.test_apitest1_get.id } } # 通常設定方法 resource "aws_api_gateway_deployment" "test_api_dev2" { rest_api_id = aws_api_gateway_rest_api.test_api.id triggers = { deploy_trigger = var.deploy_trigger test_apitest1_get = aws_api_gateway_integration.test_apitest1_get.id } lifecycle { create_before_destroy = true } } resource "aws_api_gateway_stage" "test_api_dev2" { deployment_id = aws_api_gateway_deployment.test_api_dev2.id rest_api_id = aws_api_gateway_rest_api.test_api.id stage_name = "dev2" }
aws_api_gateway_deploymentリソースのtriggersはTerraform固有の項目です。
ここの値を更新することで、デプロイメントを更新させることができます。
また、URLはinvoke_urlで取得可能です。ステージを作ったリソースのinvoke_urlを参照します。
output "apigw_test_api_dev1_url" { value = aws_api_gateway_deployment.test_api_dev1.invoke_url } output "apigw_test_api_dev2_url" { value = aws_api_gateway_stage.test_api_dev2.invoke_url }
カスタムドメインの設定
カスタムドメインは、Terraformでは以下のリソースで設定可能です。
| Terraformリソース | 必須参照先リソース | 任意参照先リソース |
|---|---|---|
| aws_api_gateway_domain_name | (ACM証明書) | |
| aws_api_gateway_base_path_mapping | domain_name rest_api |
stage |
aws_api_gateway_domain_nameでドメイン名やサーバ証明書の設定を行います。
このリソース自体はREST APIとは独立して存在しています。
カスタムドメインと各APIの関連付けはaws_api_gateway_base_path_mappingで行います。
カスタムドメインに対して、どのAPIまたはAPIのステージに接続するかを設定可能です。
これにはbase_pathという設定項目があり、1つのカスタムドメインに対して複数のAPIやステージを設定できます。
たとえば、以下のように1つのカスタムドメインでURLごとに違うAPIのバックエンドを設定可能です。
https://<カスタムドメイン>/api2⇒REST_API_2のステージProductionhttps://<カスタムドメイン>/dev⇒REST_API_1のステージDevelophttps://<カスタムドメイン>/⇒REST_API_1のステージProduction
ログ出力設定
API Gatewayには以下の2種類のログがあります。
- アクセスログ
- 実行ログ
これらは、以下のリソースに設定項目があります。
| Terraformリソース | 必須参照先リソース | CloudFormationリソース |
|---|---|---|
| aws_api_gateway_account | AWS::ApiGateway::Account | |
| aws_api_gateway_stage | rest_api deployment |
AWS::ApiGateway::Stage |
| aws_api_gateway_method_settings | rest_api stage |
-(Stage内のプロパティ) |
アクセスログの設定はaws_api_gateway_stageで行います。(aws_api_gateway_deploymentのstage_nameでステージを作成していると設定できません)
アクセスログは出力先とログ形式をステージごとに設定するだけです。
AWSコンソール上では、ステージのステージ名を選択した状態でログ/トレースタブにあるカスタムアクセスログの記録という項目になります。
少し分かりにくいのは、実行ログの設定です。
AWSコンソール上で、実行ログの設定はステージのステージ名を選択した状態でログ/トレースタブにあるCloudWatch ログです。
また、ステージの下にあるメソッドを選択した時の選択でこのメソッドの上書きを選ぶとメソッドごとに設定できます。
Terraformでの実行ログの設定はaws_api_gateway_method_settingsで行いますが、CloudFormationではAWS::ApiGateway::Stage内のプロパティになります。
実行ログはログレベルとデータトレースログを出力するかどうかの設定になります。
TerraformやCloudFormationでも、実行ログはメソッドごとに設定できます。逆に、ステージ全体の設定という特別な項目はありません。
全体の設定をする時は、Terraformではmethod_pathを*/*とし、CloudFormationではResourcePathに/*、HttpMethodには*を設定します。
また、このメソッドの設定はログだけでなくキャッシュやスロットリングの設定も同時に行えます。
最後に、aws_api_gateway_account(CloudFormationではAWS::ApiGateway::Account)についてです。
これはAWSアカウント+リージョンごとに1つしか作成しないリソースで、CloudWatch等への出力を行うためのIAMロールを設定します。
すべてのAPI Gatewayは、同じリージョンに設定された同じロールを使ってログ出力等を行います。
終わりに
API GatewayをTerraformとCloudFormationで設定するためのリソースをいくつか紹介しました。
冒頭に書いたように、実際にはIaCツールでAPI Gatewayをすべて構築することは少ないかと思います。
IaCの設定項目を通してAPI Gatewayへの理解を深めるとともに、何をIaCツールで定義して何を開発フレームワークで定義するのか、考えるきっかけになればと思います。