Serverless Framework で API Gateway のカスタムドメインを設定する

Serverless Framework を用いて、API Gateway の カスタムドメインを設定する方法を調査しました。

目次

背景

AWS APIGatewayのエンドポイントは次のような形式になっています。

https://<API-ID>.execute-api.<REGION-ID>.amazonaws.com/<STAGE-NAME>/…

APIGateway + Lambdaで構成されたようなサービスを開発していて、サービスをいったん削除してデプロイし直す、といったことをすると、<API-ID>の部分が変わってしまいます。
外部のサービスと連携したりしている場合、設定していたエンドポイントが変わることになり、再度設定が必要なため不便です。

今回はデプロイし直してもエンドポイントが変わらないようにするための調査を行ったので、一例を紹介します。

環境

Lambda 関数とレイヤーのデプロイに Serverless Framework を使用しています。
Serverless Framework はNode.jsで作られたCLIツールで AWS LambdaAzure FunctionsGoogle Cloud Functions等の Serverless Applicationを構成管理、デプロイするためのツールです。
また、Lambda関数のランタイムとしてGo言語を、goのビルドにmakeを使用しました。
各ツールのインストールや環境構築については割愛します。

serverless-domain-manager

Serverless Framework のプラグイン serverless-domain-manager を使用します。

github.com

READMEに従ってインストールを行います。

$ npm install serverless-domain-manager --save-dev

また、前提条件としてデプロイを行うIAMロールに必要となる権限があるので、その付与を行っておきます。
https://github.com/amplify-education/serverless-domain-manager/blob/master/README.md#prerequisites

独自ドメイン取得と設定

次に独自ドメインの取得と設定を行います。

  1. 独自ドメイン取得
    Freenom というサービスで some-service.cf という無料のドメインを取得しました。
  2. AWS Route53でホストゾーン作成
    ドメイン名と同じ、some-service.cf というホストゾーンを作成しています。
    またホストゾーン作成時に割り当てられる Name Server を Freenom で作成したドメインに設定しておきます。
  3. AWS Certificate ManagerでSSL証明書

手順の詳細は、次の記事が参考になりました。
無料の独自ドメインとAWS Certificate Managerを使ったお手軽SSL対応

プロジェクトの作成

Serverless Framework のコマンドでプロジェクトのテンプレートを作成します。

$ sls create --template aws-go

モジュール名は testendpoint としました。

$ go mod init testendpoint

ディレクトリ構成はテンプレートのままですが、以下のようになります。

./
│  .gitignore/
│  go.mod
│  go.sum
│  Makefile
│  serverless.yml
│
├─.serverless/
│
├─hello/
│      main.go
│
└─world/
        main.go

serverless.yml でリージョンを us-east-2 に設定して、ビルド(make)とデプロイ(sls deploy)を行ってみます。
デプロイした API Gateway のエンドポイントを確認して、ブラウザからアクセスするとLambda関数から返却されたメッセージが確認できます。

サービスを削除(sls remove)して、再度デプロイを行うと画像の API ID の部分が変わるため、毎回エンドポイントの確認が必要になります。

serverless.yml の編集

事前に用意していたドメイン some-service.cf でアクセスできるようにするため、serverless.yml へ以下の内容を追記します。
plugins の項目に serverless-domain-manager を指定して、プラグインの使用を宣言します。
customcustomDomain の各項目で使用するドメインについての設定を行います。

plugins:
  - serverless-domain-manager
 
custom:
  customDomain:
    domainName: 'some-service.cf'
    basePath: ''
    certificateName: 'some-service.cf'
    certificateArn: 'arn:aws:acm:<region>:<account>:certificate/01234567-0123-0123-0123-01234567890'
    endpointType: 'regional'
    stage: ${self:provider.stage}
    createRoute53Record: true

明記している項目以外にも設定できる項目はありますが、記載している項目の内容は次の通りです。

  • domainName
    APIGatewayとRoute53で作成されるドメイン名になり、必ず設定する必要があります。
  • basePath
    エンドポイントに付加するベースパスです。
  • certificateName
    AWS Certificate Manager で作成した証明書の名前です。
    指定しない場合はドメイン名に最も近い名前が選ばれる、と serverless-domain-manager のREADMEにありますが、明示的にsome-service.cfとしています。
  • certificateArn
    AWS Certificate Manager で作成した証明書のARNです。
    AWS マネジメントコンソールのCertificate Managerの画面等から確認することができます。
  • endpointType
    デフォルトは edge となっていますが、今回は us-east-2 へデプロイしているので、regional としています。
    CloudFrontを介して edge で配信する場合は、リージョンを us-east-1 にする必要があるため注意が必要です。
  • stage
    デプロイされるドメインのステージです。
  • createRoute53Record
    Route53 を使用してマッピングされたレコードを作成するため true としています。
    DNS に Route53 を使用しない場合は false とします。

全ての項目のデフォルト値と詳細説明はREADMEの以下のリンクから確認することができます。
https://github.com/amplify-education/serverless-domain-manager/blob/master/README.md#installing

デプロイ

ここまで設定したら、デプロイ(sls deploy)を行う前に、sls create_domain でRoute53レコードを作成します。
sls create_domain 後、デプロイして、エンドポイント https://some-service.cf/hello へアクセスしてみると、先の動作確認と同じメッセージが確認できました。

これで、何度デプロイをし直してもエンドポイントは変わらない状態になりました。
また、sls create_domain で作成したレコードは sls delete_domain で削除することができます。

まとめ

今回、実際に開発を進めているプロジェクトで API Gateway のエンドポイントを固定化したい需要があって調査を行ったのですが、デプロイし直すたびに連携している外部サービスへ登録しているURL(エンドポイント)を設定し直す必要がなくなり、人手による手間とミスを削減できたかと思います。

参考記事