こんにちは。
AI 事業本部 AI クリエイティブディビジョンのエンジニアの佐藤 (@Rintarooo) です。
ミッション・インポッシブル 2 の、イーサン・ハントが断崖絶壁でロッククライミングをしているシーンで流れている陽気でリズミカルな曲がとても好きです。

はじめに

Lambda の開発は、ローカルテスト環境の構築やデプロイの方法など、エンジニアを悩ませるさまざまな課題が存在します。
本記事では、AWS Lambda Runtime Interface Emulator (以下、RIE)と lambroll を用いた CI/CD パイプラインの構築方法や、他のツールと比較した上での RIE と lambroll を選定する利点などを紹介します。
RIE と lambroll の導入により、開発体験の向上を図ることができると考えています。

背景

Lambda 開発上の課題

Lambda は、素早くアプリケーション開発に着手でき、AWS の他のサービスとのシームレスな連携も容易にできることから、広く採用されているサーバーレスサービスの一つです。一方、Lambda の開発におけるバグ修正や機能開発が増えていくにつれて、主に以下の二つの課題に直面することがあります。
  1. ローカルテストの困難さ
    • Lambda 固有のランタイム環境の再現が難しい
    • 他の AWS サービスとの連携を含むテストが複雑
  2. 最適なデプロイ方法の選択の難しさ
    • アプリケーションコードは頻繁な更新がなされるのに対して、インフラリソースとしての Lambda の設定値は変更頻度が低く、異なるライフサイクルが混在している
    • 環境別(開発・ステージング・本番)の設定管理が必要

RIE と lambroll について

これらの課題に対して、以下の二つのツールを紹介します。

RIE

一つ目のツールは、RIE (AWS Lambda Runtime Interface Emulator) です。RIE は、AWS が提供する、コンテナイメージとして作成した Lambda 関数をローカル環境で実行するためのエミュレータです。以下のような特徴があります。
  • コンテナ内で RIE を実行することで、ローカル環境で 実際の Lambda 実行環境と同様の動作を提供
  • curlDocker CLI などの慣れ親しんだツールを使用して、手元で動作確認ができる
RIE は普段使い慣れたツールでテストができるため、非常に導入しやすいです。個々の Lambda 関数を一つのマイクロサービスとして扱い、デプロイする前にローカル環境でテストするなど、効率的な開発を可能にします。

lambroll

二つ目のツールは、lambrollです。lambroll は、Lambda のデプロイに特化したシンプルなツールです。ECS のデプロイツールである ecspresso と同じ開発者が開発しており、共通の設計思想で作られているため、導入コストが低いです。また、他にも以下のような特徴が挙げられます。
  • 軽量で高速なデプロイ機能
  • 宣言的な設定による簡潔な管理とシンプルな CLI
  • 既存のデプロイされている Lambda から設定ファイルを自動生成
  • 動的な変数を取得できるため、CI/CD との相性が良い
コマンド一つで、既にデプロイされている Lambda から設定ファイルを生成できるため、lambroll でのデプロイをすぐに始めることができます
また、lambroll 用の設定ファイルは、直感的でシンプルな記法のため、把握しやすいです。
lambroll は、 AWS Systems Manager (SSM) Parameter Store で管理されている値や Terraform の tfstate の値から動的に値を参照することができるため、CI/CD パイプラインに組み込みやすい点も大きな強みです。

RIE と lambroll を用いた CI/CD

以下に、RIE と lambroll を用いて構築した CI/CD パイプラインの例を示します。

lambda_cicd_overview

  • GitHub Actions: CI/CD 基盤
  • RIE: Lambda のテスト
  • lambroll: Lambda のデプロイ
  • Terraform Cloud: tfstate の管理
  • ECR: コンテナイメージの管理
  • Systems Manager (SSM) Parameter Store: 動的に更新されるコンテナイメージのタグの値の管理
Terraform で作成した AWS のリソースに対して、RIE と lambroll を用いて Lambda におけるテストとデプロイを自動化しています。
また、実装例を以下のリポジトリに公開しています。より詳細な実装コードやディレクトリの構成を確認したい方は、ぜひご覧ください。

他の手法との比較

次に、RIE と lambroll を導入する際に、検討した手法やツールと比較してみます。

AWS CLI を用いたスクリプト

AWS CLI を Makefile やシェルスクリプトに記述して手動でデプロイする方法があります。これは宣言的ではなく命令的なアプローチのため、以下のようなデメリットがあります。
  • デプロイの手順が属人化しやすく、コマンドの実行順序や実行のし忘れなど、人的ミスが発生しやすい
  • 異なる環境(開発・ステージング・本番)ごとの設定管理が煩雑になる
  • デプロイの履歴や変更内容の追跡が難しく、ロールバックのための追加の仕組みが必要となる
一方で、小規模なプロジェクトや開発初期段階では、この方法でも十分かもしれません。しかし、継続的に開発を行うにつれて、特にチーム開発においては開発体験が悪化しやすいです。

AWS SAM

AWS SAM (Serverless Application Model) は、AWS が提供する、サーバーレスに特化した多機能な IaC ツールです。Lambda に加えて、DynamoDB や API Gateway など広範囲に扱えますが、以下の理由から、単に Lambda をテストしたい、デプロイしたい場合には、RIE や lambroll の方が適していると考えます。
  • IaC ツールとの競合:
    • AWS SAM は CloudFormation ベースのため、Terraform を始めとする他の IaC ツールと併用すると、IAM ロールなどのリソース管理が重複してしまう
  • 複雑性と学習コスト:
    • YAML 形式の SAM テンプレート固有の記法は、CloudFormation の記法に慣れていないと直感的に理解しにくい
    • 多機能である分、理解すべき CLI コマンドや記法が多く、学習コストがやや高い
特に、IaC ツールとの競合の点に関して、SAM テンプレート は tfstate で管理されている値を直接参照することができません。これに対して、lambroll では tfstate から動的に値を参照することができます。

Lambda リソースの粒度分割によるモジュール管理

上述した通り、Lambda はアプリケーションコードとインフラ設定で更新の頻度が異なります。
そこで、Terraform のような IaC ツールで Lambda をデプロイする場合、Terraform の単一のモジュールで全てのリソースを管理するのではなく、モジュールを細かく分割して、Lambda のリソースのみを独立して管理する方法が考えられます。しかし、この方法のようにモジュールを細かい粒度で過度に分割しすぎることで、以下のような課題が生じます。
  • モジュール間の値の受け渡しやデプロイ順序制御が煩雑になる
  • リソース間の依存関係の把握が困難になる
以上の比較から、Lambda の開発フローにおいて、RIE と lambroll を使用することは、より効率的なアプローチであると考えました。

実装上の注意点

実装する上での注意点を以下で説明します。

Terraform による Lambda の変更制御

Lambda リソースの作成・削除は Terraform で管理し、関数の更新は lambroll でのデプロイのみとしたい場合、ignore_changes を指定します。これにより、.tf コードと tfstate との差分チェックをスキップし、Terraform による意図しない Lambda の更新を防ぐことができます。
resource "aws_lambda_function" "example" {
  # ...

  lifecycle {
    # ignore_changes を指定することで、Terraform による Lambda の更新を無視
    ignore_changes = all
  }
}

ビルド時の provenance オプションを無効にする

Provenance とは、Docker のコンテナイメージをビルドする際に生成される、ビルドプロセスに関する情報を含むメタデータです。本稿執筆時点では、このオプションを有効にしてビルドすると、Lambda が ECR からコンテナイメージを正常に起動できず、エラーが発生してしまいます。そのため、provenance オプションは無効にすることをお勧めします。
    name: Build and push to ECR
    uses: docker/build-push-action@v6
    with:
      # provenance オプションを無効
      provenance: false

おわりに

本記事では、RIE と lambroll による CI/CD パイプラインの構築による Lambda のテスト・デプロイの自動化や、RIE と lambroll を他のツールと比較した際の利点を紹介しました。
いきなり工数をかけて CI/CD パイプラインを構築しなくても、まずは lambroll を導入して手動でのデプロイを簡略化してみるなど、仕様や開発フェーズ、チームの状況に合わせて、開発フローを漸進的に改良していくのが良いかと思います。
本記事で紹介したアプローチが、より効率的な Lambda の構築から開発、運用の参考になれば幸いです。