serverless-domain-manager プラグインを利用して独自ドメインで API Gateway にアクセスする
概要
記事一覧はこちらです。
API Gateway にアクセスする時には deploy 時に表示される ServiceEndpoint(https://~.execute-api.ap-northeast-1.amazonaws.com/dev/... の URL)を使用していましたが、独自ドメインでアクセスする方法を試してみます。
Lambda を deploy する時に独自ドメインを定義できる serverless-domain-manager プラグインというものがあるので、今回はこれを利用します。
構成は以下のようになるようです(ELB と API Gateway のどちらが先にアクセスされるのかが分からない。。。)。
- SSL証明書は東京リージョン(ap-northeast-1)の ACM で発行します。
- 独自ドメインは rest.ksbyzero.com にします。Route 53 に登録します。
- Lambda は Serverless Framework でプロジェクトを作成した時にできる hello をそのまま使い、https://rest.ksbyzero.com/hello でアクセスできるようにします。独自ドメインを使用する方式にすると stage 名を URL からなくせます。
- 独自ドメインでアクセスできるようにする場合、ELB が作成されて ACM で発行した SSL証明書が ELB に関連付けられます。ACM で作成した SSL証明書を削除しようとすると ELB で使用されているので削除できないというメッセージが表示されて気づきました(API Gateway を削除してから 20~30分程度経過しないと削除できませんでした)。
参照したサイト・書籍
REST API のカスタムドメイン名の設定
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-custom-domains.htmlHow to set up a custom domain name for API Gateway in your Serverless app
https://seed.run/blog/how-to-set-up-a-custom-domain-name-for-api-gateway-in-your-serverless-app.htmlamplify-education / serverless-domain-manager
https://www.npmjs.com/package/serverless-domain-manager
https://github.com/amplify-education/serverless-domain-managerアプリケーションロードバランサー(ALB)のターゲットにAWS Lambdaが選択可能になりました
https://aws.amazon.com/jp/blogs/news/lambda-functions-as-targets-for-application-load-balancers/
目次
- custom-domain-api-project プロジェクトを作成する
- serverless-domain-manager プラグインをインストールする
- hello_service サブプロジェクト作成し serverless.yml を変更する
- Terraform を使用して ACM で SSL証明書を作成する
sls create_domain
を実行して独自ドメインを利用できるようにする- deploy する
- 動作確認する
- ACM の SSL証明書は関連リソースがなくならないと削除できない
手順
custom-domain-api-project プロジェクトを作成する
以下の手順で custom-domain-api-project プロジェクトを作成します。具体的な手順は IntelliJ IDEA+Node.js+npm+serverless framework+Python の組み合わせで開発環境を構築して AWS Lambda を作成してみる 参照。
- custom-domain-api-project の Empty Project を作成する。
- Python の仮想環境を作成する。
- Serverless Framework をローカルインストールする。
- .envrc を作成する。
serverless-domain-manager プラグインをインストールする
npm install --save-dev serverless-domain-manager
を実行してプラグインをインストールします。
hello_service サブプロジェクト作成し serverless.yml を変更する
プロジェクトのルートディレクトリの下で npx sls create --template aws-python3 --path hello_service
を実行して hello_service サブプロジェクトを作成します。
hello_service/severless.yml を以下の内容に変更します。
service: hello-service plugins: - serverless-domain-manager custom: customDomain: domainName: rest.ksbyzero.com # stage を書かなければ provider.stage の設定が使用される # stage: dev # basePath を書くと https://<domainName>/<basePath>/hello がアクセスする URL になる # basePath: base certificateName: ksbyzero.com createRoute53Record: true # endpointType に edge を指定すると CloudFront ディストリビューションを設定する # 今回は東京リージョンで設定するので regional を指定する endpointType: regional securityPolicy: tls_1_2 apiType: rest provider: name: aws runtime: python3.8 stage: dev region: ap-northeast-1 functions: hello: handler: handler.hello events: - http: path: hello method: get cors: true
- plugins を追加して serverless-domain-manager を記述します。
- custom.customDomain を追加し、serverless-domain-manager の設定を記述します。
- provider.stage、provider.region を追加します。
- functions.hello.events.http を追加し、API Gateway にリクエストが来たら Lambda が実行されるよう設定します。
Terraform を使用して ACM で SSL証明書を作成する
Terraform は tfenv+aws-vault+direnv を組み合わせて Windows 上に Terraform の実行環境を構築する で構築した環境を使用します。バージョンは 0.12.26 を使用します。
プロジェクトのルートディレクトリ直下に .terraform-version というファイルを作成し、以下の内容を記述します。
0.12.26
プロジェクトのルートディレクトリ直下に terraform というディレクトリを作成し、その下に acm.tf というファイルを作成して以下の内容を記述します。
terraform { required_version = "0.12.26" } provider "aws" { region = "ap-northeast-1" } /////////////////////////////////////////////////////////////////////////////// // Route53 の Public Zone // ※Route53 でドメインを取得したので作成済、resource ではなく data で定義する // data "aws_route53_zone" "dns_zone_apex" { name = "ksbyzero.com" } /////////////////////////////////////////////////////////////////////////////// // ACM で SSL証明書を作成する // resource "aws_acm_certificate" "dns_zone_apex" { domain_name = data.aws_route53_zone.dns_zone_apex.name subject_alternative_names = ["*.${data.aws_route53_zone.dns_zone_apex.name}"] validation_method = "DNS" tags = { Name = data.aws_route53_zone.dns_zone_apex.name } lifecycle { create_before_destroy = true } } resource "aws_route53_record" "cert_validation_0" { name = aws_acm_certificate.dns_zone_apex.domain_validation_options.0.resource_record_name type = aws_acm_certificate.dns_zone_apex.domain_validation_options.0.resource_record_type records = [aws_acm_certificate.dns_zone_apex.domain_validation_options.0.resource_record_value] zone_id = data.aws_route53_zone.dns_zone_apex.id ttl = 60 } resource "aws_acm_certificate_validation" "cert" { certificate_arn = aws_acm_certificate.dns_zone_apex.arn validation_record_fqdns = [ aws_route53_record.cert_validation_0.fqdn, ] }
以上で設定は完了です。ACM で SSL証明書を作成します。
tf init
を実行してから、
tf plan
、tf apply
を実行します(画面キャプチャは tf apply
のみ)。
マネジメントコンソールで ACM を見ると ksbyzero.com の証明書が追加されており、「状況」が「発行済み」になっています。
Route 53 には DNS検証用の CNAME のレコードが1件追加されています。
sls create_domain
を実行して独自ドメインを利用できるようにする
deploy の前に sls create_domain
を実行して serverless.yml の custom.customDomain.domainName に定義した rest.ksbyzero.com を設定します。
New domains may take up to 40 minutes to be initialized.
というメッセージが表示されており、使用可能になるまで最大 40分かかるようです。ただし、今回試していた時は結構すぐに使えるようになりました。
マネジメントコンソールから Route 53 を見ると rest.ksbyzero.com の A、AAAA レコードの2件が追加されています。
deploy する
hello_service を deploy します。
動作確認する
Postman で GET メソッドにしてから https://rest.ksbyzero.com/hello にアクセスすると 200 OK が返ってきます。
sls logs -f hello
コマンドでログを確認すると1回しか実行していないのに7件ログが出力されていました。ELB のヘルスチェックでしょうか?
以下のコマンドを実行して作成したリソースを削除します。
npx sls remove -v
npx sls delete_domain
- terraform ディレクトリに移動してから
tf destroy
ACM の SSL証明書は関連リソースがなくならないと削除できない
tf destroy
コマンドで ACM の SSL証明書を削除しようとしてもすぐには削除できません。API Gateway を削除してもしばらくの間 ELB がSSL証明書に関連付けられているためです。20~30分程度経つと関連リソースはなくなります。
履歴
2020/06/24
初版発行。