TerraformとSAMでCloudFront + API Gateway + Lambdaの環境を作る

はじめに

こんにちは。2021年度新入社員の碇川です。

本記事では、業務においてTerraformとSAMを使ってCloudFront + API Gateway + Lambdaの環境を作成した時の知見を紹介させていただきます。
私は主に@niftyトップページの運用を行っています。本記事の構成を作成した時は「ほかのAPIからデータを中継し、@niftyトップページに受け渡す」というAPIを作りました。

概要

Terraform

Terraformは、HashiCorpによって作成されたIaC (Infrastructure as Code)です。HashiCorp構成言語 (HCL)もしくはJSONを使用してAWSやGCPのリソースを管理することができます。

SAM

AWS サーバーレスアプリケーションモデル (SAM、Serverless Application Model) は、サーバーレスアプリケーション構築用のオープンソースフレームワークです。迅速に記述可能な構文で関数、API、データベース、イベントソースマッピングを表現できます。

どんなものを作るか

以下のような構成のものを作っていきます。

ディレクトリ構造は以下のようになります。

hello-samディレクトリの中はSAMから自動生成されるものになります。その中でも今回はtemplate.yamlを修正していきます。
このtemplate.yamlからSAMの機能を用いてCloudFormationのテンプレートファイルを生成します。

生成されたテンプレートファイルをTerraformを用いてデプロイします。

今回はTerraformではなくSAMを使って、LambdaとAPI Gatewayを作成します。

このような構成にする理由としては以下が挙げられます。

  • Terraformはあくまでインフラリソース管理なのでソースコードは一緒に管理したくない
  • TerraformでLambdaを管理する場合、zipでアーカイブ後デプロイする流れで、環境によってアーカイブする際に意図しない差分が発生する可能性がある
  • CloudFrontには今回作成するAPIとは独立したAPIを紐づける可能性があり、API単体でのテストが容易であるため

以上の理由から部分的にSAMを使用することにします。

手順

1. Terraformのセットアップ

以下のようにterraformのバージョン指定や必要なproviderの設定を行います。

設定できたら以下のコマンドでTerraformの初期化を行います。

 

これでTerraformのセットアップは完了です。

2. SAMのセットアップ

次にSAMのセットアップを行います。SAMは対話形式でサンプルアプリケーションをセットアップできます。

今回は以下のように設定します。

この設定により、hello-appディレクトリが作成されます。

3. S3バケット作成

以下のコマンドを入力し、Lambdaのソースコードを保持しておくためのS3バケットを作成します。

バケット名は好きな名前で大丈夫です。XXXXXXXを書き換えてください。

 

4. Lambdaのソースコードの用意

SAMから作られたファイルをそのまま用います。

 

5. テンプレートの修正

こちらのテンプレートをもとにCloudFormationのテンプレートが生成されます。

template.yamlを以下のように修正してください。

CloudFrontの設定をする際に作成するAPIのドメインが必要になってくるので、ドメインをOutputsとして出力しています。
今回はAPI Gatewayのリソース(HelloWorldApi)を作成し、HelloWorldFunctionリソースに紐づけている形になっています。
API Gatewayのリソースを作成しない場合、「Stage」というステージが勝手に作成されてしまいますが、
上記のようにAPI Gatewayのリソースを紐づける形にすることで勝手に作成されることがなくなります。

参考:AWS SAMで「Stage」ステージが作られるバグを回避する

これでSAMの準備はOKです。

6. CloudFormationをTerraformから利用できるようにする

SAMによって生成されるCloudFormationのスタックをTerraformから利用できるようにしていきます。
ここでのtemplate.yamlhello-sam/template.yaml ではなく、後にSAMによって生成されるCloudFormationのテンプレートです。

 

7. CloudFrontの用意

次にCloudFrontの設定を行います。カスタムオリジンにAPI Gatewayを指定しています。

domain_nameにCloudFormationからのOutputsであるHelloWorldApiDomainを指定します。

 

8. デプロイ

まずはSAMをビルドします。

作業ディレクトリはそのままで、以下のコマンドを実行します。 これはCloudFormationのテンプレートを生成し、指定したS3にLambdaのソースコードをアップロードしてくれます。

ディレクトリを一階層上に移動し、lsコマンドで見てみると生成されたCloudFormationのテンプレートファイルが確認できます。

 

テンプレートファイルが作成できたので以下のコマンドでデプロイします。

途中で本当に実行していいか確認のメッセージが表示され入力を促されるので出力を確認し、yesと入力しましょう。

しばらく待ち、Apply complete!と表示されたらデプロイ成功です。

以下は出力結果の例です。

9. 動作確認

AWSのコンソールへアクセスし、作成したCloudFrontのURLを確認します。

CloudFrontのリンクを以下に当てはめて、作成したAPIにリクエストを送信します。

以下のような出力が返ってくれば成功です!

10. お片付け

以下のコマンドを入力することで今回作成した全てのリソースを削除することができます。

LambdaとAPI GatewayはCloudFormationによって作成されていますが、CloudFormation自身はTerraform管理下なのでLambdaとAPI Gatewayも削除されます。

おわりに

今回はTerraformとSAMを使ってCloudFront + API Gateway + Lambdaの環境を作りました。

AWSやTerraform、SAMといった技術は入社してから学んだ技術なのですが、アウトプットの機会を得られて、より知識が深まったと思います。

また、今回紹介した内容と同じような構成を実装する際に是非参考にしてみてください。

参考資料

AM+TerraformでLambdaの管理を楽にする

Terraform+SAMでLambda+APIGatewayの環境構築

AWS SAMで「Stage」ステージが作られるバグを回避する