🐙

Hono + AWS Lambda を Terraform でデプロイする

に公開

Hono + AWS Lambda を Terraform でデプロイする

Honoで作成したアプリケーションを、AWS SAMやCDKを使わずにTerraformのみでAWS Lambdaにデプロイする構成を紹介します。
会社のサーバーレス基盤を再構築するにあたり、個人的にHonoで実現できないかと考えたのがきっかけです。

対象

  • AWS Lambdaで外部連携用のAPIを構築したい方
  • モノレポで管理している既存のTypeScriptコンポーネント資産を活用できるサーバーレス基盤に興味がある方
  • PHPerからTypeScriptに転向し、TypeScript、Terraformの経験が浅い方(筆者と同じような境遇の方)

事前準備

  • AWS CLIがインストール済みであること
  • Terraformがインストール済みであること

プロジェクトのセットアップ

まず、Honoプロジェクトを作成します。

npm create hono@latest

プロンプトが表示されたら aws-lambda を選択してください。

次に、TypeScript関連のパッケージをインストールします。

npm i typescript @types/node

今回はテンプレートを選択したので、ビルドしてLambdaにデプロイすれば、そのまま使える想定です。

TerraformによるIaC管理

npm run build でビルドしたJavaScriptファイルを、ローカルからTerraformを使ってLambdaにアップロードします。
API GatewayとLambdaの統合もTerraformで記述していきます。

ルーティングはHono側に全て任せるため、API GatewayのRoute Keyは ANY /{proxy+} を指定します。これにより、すべてのリクエストが一つのLambda関数に集約され、Honoのルーターが後続の処理を振り分けます。

Terraformの実行フロー

Terraformの基本的なワークフローは init -> plan -> apply の3ステップです。

  1. terraform init

    Terraformの作業ディレクトリを初期化します。
    .tf ファイルに記述されたプロバイダ(今回はAWS)をダウンロードし、TerraformがAWS APIと通信できるように準備を整えます。

    terraform init
    
  2. terraform plan

    コードの変更内容を元に、インフラストラクチャの実行計画を作成します。
    どのリソースが「作成・変更・削除」されるのかを事前に確認できるため、意図しない変更を防ぐことができます。

    terraform plan
    
  3. terraform apply

    planで作成した実行計画を、実際のリソースに適用します。
    このコマンドを実行すると、AWS上でAPI GatewayやLambda関数が作成・構成され、ローカルでビルドしたアプリケーションコードがデプロイされます。

    terraform apply
    

動作確認

デプロイが完了したら、API Gatewayのエンドポイントにアクセスしてみましょう。

おお!動いた!!

次に、index.tsに下記を記載して、POSTリクエストを送信してみます。

src/index.ts
app.post('/hono-lambda', async (c) => {
  const request = await c.req.json()

  return c.json({
    message: 'Hello from Hono Lambda!',
    request: request,
  })
})

リクエストの内容も問題なく取得できていますね!

最後に、設定していないルーティングにアクセスしてみます。

Honoのルーティングが効いており、Not Foundが返却されました。

モノリスLambdaというアンチパターンではある

この構成は、すべてのリクエストを単一のLambda関数で処理する「モノリスLambda」パターンです。開発初期においてはシンプルで管理しやすいという大きなメリットがあります。

一方で、アプリケーションが大規模化すると、機能ごとにLambdaを分割するマイクロサービス的なアプローチが有効になる場合があります。

Honoは、ルーティングのグループ化機能を使うことで、コードベースを機能ごとに整理しやすいという特徴があります。

src/index.ts
const users = new Hono()
const orders = new Hono()
const app = new Hono()
app.route('/users', users)
app.route('/orders', orders)

このようにコンポーネント化しておくことで、将来的に機能単位でLambdaを分割する際のリファクタリングが容易になるんじゃないかと思いますが、それでも肥大化した際に分割していくのは難しいので肥大化する前に適切なアプローチ方法を検討する必要がありますね。

まとめ

今回は、Honoで構築したアプリケーションをTerraformでAWS Lambdaにデプロイする方法を紹介しました。
Terraformで安全なワークフローに沿ってインフラを構築し、Honoのルーティング機能を活用することで、シンプルかつスケーラブルなサーバーレスAPIを実現できます。
ソースコードはGitHubにアップしているので気になる方は見てみてください!

今後は、CI/CDパイプラインの構築などにも挑戦していきたいです。

Discussion