Amazon Web Services ブログ

AWS SAM による HashiCorp Terraform のサポートが一般利用可能に

本記事は、『AWS SAM support for HashiCorp Terraform now generally available』の翻訳です。

2022 年 11 月、AWS は HashiCorp TerraformAWS Serverless Application Model (AWS SAM) サポートのパブリックプレビューを発表しました。パブリックプレビューでは、Terraform ユーザーがサーバーレスアプリケーションをローカルでテストするのに役立つ機能のサブセットを取り入れました。本日 (2023 年 9 月 5 日)、AWS は AWS SAM における Terraform サポートの一般提供を開始します。この GA リリースでは、サーバーレスアプリケーションのローカル開発を強化するために AWS SAM の機能セットを拡張しています。

Terraform と AWS SAM はどちらも、開発者がインフラをコードとして定義する (IaC) ことを可能にするオープンソースのフレームワークです。開発者は、コードと同じように、インフラの定義をバージョン管理および共有することができます。しかし、AWS SAM はサーバーレスに特化して設計されているため、サーバーレス開発のために設計されたコマンドラインインターフェース (CLI) が含まれています。この CLI によって、開発者はビルドツールやデプロイツールとともに、ローカルエミュレータを使用してサーバーレスアプリケーションを作成、デバッグ、デプロイすることができます。今回のリリースで、AWS SAM はこれらのツールのサブセットを作成し、Terraform ユーザーにも提供します。

Terraform サポート

パブリックプレビューのブログでは、最初の Terraform サポートを紹介しました。このブログでは、ローカル開発のための AWS SAM の拡張された機能セットを紹介します。また、このブログではネイティブの Terraform リソースではなく、AWS Lambda 関数および Lambda レイヤー用の Serverless.tf モジュールを使用することで、実装を簡素化しています。

モジュールは Lambda 関数とレイヤーのデプロイメントアーティファクトを構築できます。さらに、モジュールは Terraform リソースとのインタフェースとして AWS SAM が必要とするメタデータを自動的に生成します。ネイティブの Terraform リソースを使用する場合のメタデータの設定については、プレビューのブログをご覧ください。

コードのダウンロード

AWS SAM の Terraform サポートを試してみるために、aws-sam-terraform-examples リポジトリにアクセスしてください。リポジトリをクローンし、ga ディレクトリに移動して始めましょう:

git clone https://github.com/aws-samples/aws-sam-terraform-examples
cd aws-sam-terraform-examples/ga

このディレクトリには、2 つのデモアプリケーションが含まれています。api_gateway_v1 は Amazon API Gateway REST API (v1) を、api_gateway_v2 は Amazon API Gateway HTTP API (v2) を使用していること以外は、どちらも同じアプリケーションです。どちらかを選択し、そのディレクトリの tf-resources フォルダに移動します。

cd api_gateway_v1/tf-resources

特に断りのない限り、このブログでは api_gateway_v1 アプリケーションを参照します。

コードの構成

コードの構成図

コードの構成図

Terraform では、IaC を複数のファイルに分割することができます。このため、開発者はすべての Terraform ファイルを 1 つのディレクトリに集約し、リソースファイルを別の場所に保管することがよくあります。サンプルアプリケーションも、このように構成されています。

Terraform や AWS SAM のコマンドは、main.tf ファイルの場所、今回は tf-resources ディレクトリから実行する必要があります。AWS SAM コマンドは一般的にプロジェクトルートから実行されるため、AWS SAM にはネスト構造をサポートするコマンドがあります。ネストされたフォルダから sam build コマンドを実行する場合は、terraform-project-root-path フラグにプロジェクトのルートへの相対パスまたは絶対パスを渡します。

ローカルでの Lambda 関数の呼び出し (local invoke)

Terraform のプレビュー版では、ローカル呼び出しをサポートしていましたが、今回 Serverless.tf に対応したことで体験がシンプルになりました。デモアプリケーションには 2 つの関数があります。responder 関数は API Gateway エンドポイントのバックエンド統合で、Auth 関数はカスタムオーソライザーです。両方のモジュール定義は functions.tf ファイルで見つけられます。

responder 関数

module "lambda_function_responder" {
  source        = "terraform-aws-modules/lambda/aws"
  version       = "~> 6.0"
  timeout       = 300
  source_path   = "${path.module}/src/responder/"
  function_name = "responder"
  handler       = "app.open_handler"
  runtime       = "python3.9"
  create_sam_metadata = true
  publish       = true
  allowed_triggers = {
    APIGatewayAny = {
      service    = "apigateway"
      source_arn = "${aws_api_gateway_rest_api.api.execution_arn}/*/*"
    }
  }
}

ここで、重要なパラメーターが 2 つあります:

  • source_path: これはローカルのフォルダを指します。これは zip ファイルではないので、Serverless.tf は必要に応じて成果物をビルドします。
  • create_sam_data: AWS SAM が必要なファイルとモジュールを見つけるために必要なメタデータを生成します。

この関数をローカルで呼び出すには、以下のコマンドを実行します:

  1. build を実行して、ビルドスクリプトを起動します (訳註: 変数未定義のエラーが出る場合は、export TF_VAR_aws_region=us-west-2 などを実行して設定してください)。
    sam build --hook-name terraform --terraform-project-root-path ../
  2. local invoke を実行して、任意の Lambda 関数を呼び出します。
    sam local invoke --hook-name terraform 'module.lambda_function_responder.aws_lambda_function.this[0]'

Terraform プロジェクトなので、AWS SAM にどのように処理を進めるかを知らせるために、hook-name パラメータに terraform という値を指定する必要があります。関数名は、モジュール名とリソースタイプの組み合わせです。名前がわからない場合は、名前なしでコマンドを実行してください:

sam local invoke --hook-name terraform

AWS SAM がテンプレートを評価します。関数が 1 つしかない場合は、AWS SAM はその関数を呼び出します。今回のように複数ある場合、AWS SAM はどの関数を呼び出すか選択肢のリストを表示します。

エラー文の例

エラー文の例

Auth 関数

オーソライザー関数は、モックイベントとしていくつかの入力データを必要とします。api_gateway_v1 プロジェクトのモックイベントを生成するには、以下のコマンドを実行します:

sam local generate-event apigateway authorizer

api_gateway_v2 プロジェクトでは以下を使用してください。

sam local generate-event apigateway request-authorizer

API Gateway の REST と HTTP API ではカスタムオーソライザーの扱いが異なるため、結果として出力されるイベントも異なります。今回の例では、REST は標準的なトークンオーソライザーを使用して適切な AWS Identity and Access Management (IAM) ロールを返します。HTTP API の例では、シンプルな pass または fail オプションを使用しています。

それぞれのサンプルでは、events/auth.json にテスト用の適切な形式のイベントがすでに含まれています。Auth 関数を呼び出すには、以下を実行します:

sam local invoke --hook-name terraform 'module.lambda_function_auth.aws_lambda_function.this[0]' -e ../events/auth.json

アプリケーションは変更していないので、再度 sam build コマンドを実行する必要はありません。

ローカルでの API の実行 (local start-api)

一般利用可能のリリースで、API Gateway のローカルバージョンのエミュレートができるようになりました。これらのサンプルにはそれぞれ 2 つのエンドポイントが含まれています。片方は公開エンドポイントで、もう一方はカスタムオーソライザーによって保護されています。どちらも同じレスポンスを返します:

{
  “message”: “Hello TF World”,
  “location”: “ip address”
}

以下のコマンドを実行して、ローカルエミュレーターを起動します:

sam local start-api --hook-name terraform

AWS SAM がエミュレータを起動し、ローカルテストのために 2 つのエンドポイントを公開します。

公開エンドポイント

curl を使って、公開エンドポイントをテストしてみましょう:

curl --location http://localhost:3000/open

ローカルエミュレーターがリクエストを処理し、ターミナルウィンドウにレスポンスを表示します。エミュレーターには、Lambda 関数からのログも含まれます。

公開エンドポイントの出力例

公開エンドポイントの出力例

認証エンドポイント

追加の必要なヘッダー (myheader) を渡して、保護されているエンドポイントをテストしてみましょう:

curl -v --location http://localhost:3000/secure --header 'myheader: 123456789'

エンドポイントは、”Hello TF World” というメッセージで、認可済みの応答を返します。無効なヘッダー値でもエンドポイントを試してみてください:

curl --location http://localhost:3000/secure --header 'myheader: IamInvalid'

エンドポイントは、Unauthorized の応答を返します。

認可されていないレスポンス

認可されていないレスポンス

パラメーター

Terraform と AWS SAM を一緒に使う場合、いくつかのオプションがあります:

  • Hook-name: Terraform を使う際にすべてのコマンドで必要になります。プロジェクトが Terraform アプリケーションであることを AWS SAM に知らせます。
  • Skip-prepare-infra: AWS SAM は、terraform plan コマンドを使って必要なすべての成果物の特定と処理を行います。ただし、新しいリソースが追加または変更されたときのみ実行する必要があります。このオプションは、AWS SAM が terraform plan コマンドを実行しないようにします。このフラグが渡されていても、プランが存在しない場合は、AWS SAM はフラグを無視して terraform plan コマンドを実行します。
  • Prepare-infra: AWS SAM に terraform plan コマンドを強制実行させます。
  • Terraform-project-root-path: 現在のディレクトリをプロジェクトのルートとして上書きします。絶対パス (/path/to/project/root) または相対パス (../または../../) を使用できます。
  • Terraform-plan-file: 開発者が特定の Terraform プランファイルを指定できるようにします。このコマンドは、Terraform ユーザーがローカルコマンドを使うことも可能にします。

これらのオプションを組み合わせて、長いコマンドを作成することもできます:

sam build --hook-name terraform --terraform-project-root-path ../

または

sam local invoke –hook-name terraform –skip-prepare-infra 'module.lambda_function_responder.aws_lambda_function.this[0]'

samconfig ファイルを使ってデフォルト値を設定すると、コマンドを短縮し、開発プロセスを最適化することができます。新しい samconfig YAML サポートを使うと、ファイルは次のようになります:

version: 0.1
default:
  global:
    parameters:
      hook_name: terraform
      skip_prepare_infra: true
  build:
    parameters:
      terraform_project_root_path: ../

これらのデフォルト値を設定すると、コマンドは次のように短くなります:

sam local invoke 'module.lambda_function_responder.aws_lambda_function.this[0]'

AWS SAM は Terraform プロジェクトであることを認識し、Terraform プランが見つからない限り準備タスクをスキップするようになりました。プランの更新が必要な場合は、-prepare-infra フラグを追加してデフォルトの設定を上書きします。

デプロイとリモートデバッグ

これらのプロジェクトのアプリケーションは、通常の Terraform アプリケーションです。他の Terraform プロジェクトと同じようにデプロイしてください。

terraform plan
terraform apply

現在、AWS SAM accelerate は Terraform プロジェクトをサポートしていません。しかし、Terraformは API メソッドを使用してデプロイするので、サーバーレスアプリケーションは素早くデプロイされます。サードパーティの監視と terraform apply -auto-approve コマンドを利用することで、同様の体験に近づけることができます。

ロギングについては、sam logs コマンドを活用しましょう。1 つまたは全てのリソースのログを出力する例として、プロジェクトのデプロイ出力を参照してください。

HashiCorp Cloud Platform

HashiCorp Cloud Platform は、開発者がセキュリティと状態を維持するために一元化された場所を使用して、デプロイを実行できるようにします。開発者がクラウド上でビルドを実行する場合、AWS SAM がローカルのプランファイルをローカルのテストやデバッグで使用することはできません。しかし、開発者はクラウドでプランを生成し、ローカルで開発に使用することができます。この手順については、ドキュメントを参照してください。

まとめ

HashiCorp Terraform は、AWS クラウドでアプリケーションを構築するための人気の IaC フレームワークです。AWS SAM は IaC フレームワークであり、CLI は特に開発者がサーバーレスアプリケーションを構築するのを支援するように設計されています。

このブログでは、Terraform の新しい AWS SAM サポートと、開発者が開発体験を最大化するためにこれらを一緒に使う方法について説明してきました。ローカルで単一の関数を呼び出す方法や、ローカルで API Gateway エンドポイントをエミュレートする方法、デプロイする前にローカルで Lambda オーソライザーをテストする方法などを紹介しました。最後に、アプリケーションをデプロイし、AWS SAM を使ってデプロイされたリソースを監視しました。

サーバーレスについてさらに詳しく学びたい方は、Serverless Land もご覧ください。

翻訳は、Partner Solutions Architect の櫻谷が担当しました。