サーバリースアプリケーションの導入-Lambda+API Gateway


関連項目:Hashcorp Learn

1.環境の構成

git clone https://github.com/hashicorp/learn-terraform-lambda-api-gateway.git
現在のディレクトリにlearne-terraform-lambd-api-gatewayフォルダをコピー
main.tf
## terraform 공급자 정의

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.1.0"
    }
    archive = {
      source  = "hashicorp/archive"
      version = "~> 2.2.0"
    }
  }

  required_version = "~> 1.0"
}

provider "aws" {
  region = var.aws_region
}

resource "random_pet" "lambda_bucket_name" {
  prefix = "learn-terraform-functions"
  length = 4
}

## S3 버킷 정의

resource "aws_s3_bucket" "lambda_bucket" {
  bucket = random_pet.lambda_bucket_name.id

  acl           = "private"
  force_destroy = true
}
terraform init
構成の適用中にエラーが発生しました

バージョンをアップグレードするだけのエラーです.アップグレードオプションを追加するだけで再試行できます.
terraform init -upgrade
terraform apply

またエラーが発生...
検索してみました。 Terraform AWS Provider is upgraded to version 4.0.0 which is published on 10 February 2022.
ベンダーのアップグレードに伴い、一部のサービスではサポートできないようです.
main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0.0"
「~>3.73.0」に変更
}
terraform init -upgrade
terraform apply


2.Lambda関数アーカイブの作成とアップロード


hello.js
module.exports.handler = async (event) => {
  console.log('Event: ', event);
  let responseMessage = 'Hello, World!';

  return {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      message: responseMessage,
    }),
  }
}
Lambdaはイベントを取得してコンソールに書き込み、APIゲートウェイはHTTP応答を生成するオブジェクトを返す
main.tfコードの追加
data "archive_file" "lambda_hello_world" {
  type = "zip"

  source_dir  = "${path.module}/hello-world"
  output_path = "${path.module}/hello-world.zip"
}

resource "aws_s3_object" "lambda_hello_world" {
  bucket = aws_s3_bucket.lambda_bucket.id

  key    = "hello-world.zip"
  source = data.archive_file.lambda_hello_world.output_path

  etag = filemd5(data.archive_file.lambda_hello_world.output_path)
}
terraform apply

まだエラー^0^
データ・ソースの名前は4.0バージョンに基づいています.
やり直す.xバージョンのソース名に変更します.
(Terraform AWS Provider Version 4 Upgrade Guideを参照!)

要するに、line 43のaws_s3_objectaws_s3_bucket_objectに変更する.

S 3の中のhello-worldzipファイルがよく置かれているのが見えます.

3.Lambda関数の作成


main.tfコードの追加
resource "aws_lambda_function" "hello_world" {
  function_name = "HelloWorld"

  s3_bucket = aws_s3_bucket.lambda_bucket.id
  s3_key    = aws_s3_bucket_object.lambda_hello_world.key

  runtime = "nodejs12.x"
  handler = "hello.handler"

  source_code_hash = data.archive_file.lambda_hello_world.output_base64sha256

  role = aws_iam_role.lambda_exec.arn
}

resource "aws_cloudwatch_log_group" "hello_world" {
  name = "/aws/lambda/${aws_lambda_function.hello_world.function_name}"

  retention_in_days = 30
}

resource "aws_iam_role" "lambda_exec" {
  name = "serverless_lambda"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Sid    = ""
      Principal = {
        Service = "lambda.amazonaws.com"
      }
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "lambda_policy" {
  role       = aws_iam_role.lambda_exec.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
このコードでもaws_s3_objectaws_s3_bucket_objectに変更
output.tfコードの追加
output "function_name" {
  description = "Name of the Lambda function."

  value = aws_lambda_function.hello_world.function_name
}


4.APIゲートウェイを使用してHTTP APIを作成する


main.tfコードの追加
resource "aws_apigatewayv2_api" "lambda" {
  name          = "serverless_lambda_gw"
  protocol_type = "HTTP"
}

resource "aws_apigatewayv2_stage" "lambda" {
  api_id = aws_apigatewayv2_api.lambda.id

  name        = "serverless_lambda_stage"
  auto_deploy = true

  access_log_settings {
    destination_arn = aws_cloudwatch_log_group.api_gw.arn

    format = jsonencode({
      requestId               = "$context.requestId"
      sourceIp                = "$context.identity.sourceIp"
      requestTime             = "$context.requestTime"
      protocol                = "$context.protocol"
      httpMethod              = "$context.httpMethod"
      resourcePath            = "$context.resourcePath"
      routeKey                = "$context.routeKey"
      status                  = "$context.status"
      responseLength          = "$context.responseLength"
      integrationErrorMessage = "$context.integrationErrorMessage"
      }
    )
  }
}

resource "aws_apigatewayv2_integration" "hello_world" {
  api_id = aws_apigatewayv2_api.lambda.id

  integration_uri    = aws_lambda_function.hello_world.invoke_arn
  integration_type   = "AWS_PROXY"
  integration_method = "POST"
}

resource "aws_apigatewayv2_route" "hello_world" {
  api_id = aws_apigatewayv2_api.lambda.id

  route_key = "GET /hello"
  target    = "integrations/${aws_apigatewayv2_integration.hello_world.id}"
}

resource "aws_cloudwatch_log_group" "api_gw" {
  name = "/aws/api_gw/${aws_apigatewayv2_api.lambda.name}"

  retention_in_days = 30
}

resource "aws_lambda_permission" "api_gw" {
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.hello_world.function_name
  principal     = "apigateway.amazonaws.com"

  source_arn = "${aws_apigatewayv2_api.lambda.execution_arn}/*/*"
}
output.tfコードの追加
output "base_url" {
  description = "Base URL for API Gateway stage."

  value = aws_apigatewayv2_stage.lambda.invoke_url
}

5.Lambda関数の更新


hello.jsコードの追加
 module.exports.handler = async (event) => {
   console.log('Event: ', event)
   let responseMessage = 'Hello, World!';

+  if (event.queryStringParameters && event.queryStringParameters['Name']) {
+    responseMessage = 'Hello, ' + event.queryStringParameters['Name'] + '!';
+  }
+
   return {
     statusCode: 200,
     headers: {
       'Content-Type': 'application/json',
     },
     body: JSON.stringify({
       message: responseMessage,
     }),
   }
 }
今みんな知ってるよ...また応用が始まった
terraform apply

6.インフラストラクチャのクリーンアップ

terraform destroy