最近は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
のステージProduction
https://<カスタムドメイン>/dev
⇒REST_API_1
のステージDevelop
https://<カスタムドメイン>/
⇒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ツールで定義して何を開発フレームワークで定義するのか、考えるきっかけになればと思います。