[Terraform] 테라폼으로 Lambda함수 생성하기 (feat. cloudwatch event trigger)
IT/Terraform

[Terraform] 테라폼으로 Lambda함수 생성하기 (feat. cloudwatch event trigger)

반응형

Intro

오늘은 테라폼으로 AWS Lambda 함수를 관리하는 방법에 대해 이야기 해보도록 하겠습니다.

테라폼으로 람다 함수를 관리 하는 이유

  • 람다 소스 형상관리

테라폼 소스코드내에 람다 소스코드(python, nodejs 등)를 포함시킬 수 있으며, 이 테라폼 소스코드를 git으로 형상관리를 할때 자동으로 람다 소스코드도 함께 형상관리를 할 수 있게 됩니다.

  • AWS리소스 연동

Lambda함수를 생성할때 선택적으로 iam role, vpc, subnet, security group, lambda layer 등을 참조합니다. 테라폼을 사용하면 리소스간 참조를 쉽게 할 수 있기 때문에 람다함수를 생성, 운영하기가 수월해집니다.

람다 소스코드를 zip으로 만들기

아래와 같이 테라폼으로 람다함수를 생성할때 람다 소스를 zip으로 넣어주어야합니다.

resource "aws_lambda_function" "example_lambda" {

    filename         = "./lambda_function/example_lambda.zip"
    source_code_hash = filebase64sha256("./lambda_function/example_lambda.zip")


...ommit....
}

이때 data의 archive_file 를 활용해야 하는데, 테라폼 공식 문서를 보면 zip으로 변형하는 과정에서 버그가 있어서 현재는 사용할 수 없습니다. (https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/archive_file)

그림1.

data "archive_file" "init" {
  type        = "zip"
  source_file = "${path.module}/init.py"
  output_path = "${path.module}/files/init.zip"
}

즉, 수동으로 zip파일을 만들어줘야 합니다.

(참고로 이 bug가 언제 보완 될지 예상할 수 없으니 방법을 찾아보다가 AWS CDK를 사용하여 해결 하긴 했습니다. 하지만 개인적으로 AWS CDK는 벤더 종속에서 벗어나기 힘든 IAC툴 이기 때문에 선호하지 않습니다.)

람다 함수 생성 예시

테라폼으로 람다 함수를 생성할때 주의 할점은 handler 파라미터 인데요. handler는 반드시 filename과 동일하게 설정해야 합니다.

resource "aws_lambda_function" "example_lambda" {

  filename      = "./lambda_function/example_lambda.zip"

  function_name = "example_lambda"

  role          = data.terraform_remote_state.iam.outputs.iamrole__arn

  handler       = "example_lambda.lambda_handler"
  timeout       = "600"

  source_code_hash = filebase64sha256("./lambda_function/example_lambda.zip")

  #현재 Bug때문에 archive_file 사용불가 
  #source_code_hash = data.archive_file.example_lambda.output_base64sha256

  runtime = "python3.6" 

  layers = [aws_lambda_layer_version.lambda_layer_requests.arn]

  vpc_config {
    # Every subnet should be able to reach an EFS mount target in the same Availability Zone. Cross-AZ mounts are not permitted.
    subnet_ids         = ["subnet-0123456789"]
    security_group_ids = [data.terraform_remote_state.sg.outputs.sg_id]
  }

  tags = merge(local.common_tags,
        {
        Name = "example_lambda"
        Resource = "lambda"
        CreateDate = "2022-03-03-1624"
        }
  )
}

번외 - Cloudwatch EventBridge를 Lambda trigger를 설정하기

Lambda함수는 Cloudwatch EventBridge(구 Cloudwatch Event Rules)를 통해서 스케줄링을 걸어 배치 Job을 구현할 수 있습니다.

일반적으로 AWS콘솔에서 EventBridge를 생성하고 Target을 Lambda함수를 설정하면 Lambda 함수에서도 Trigger 대상이 설정한 EventBridge로 설정됩니다. 하지만 테라폼으로 이를 구현할때 2가지 작업이 필요합니다.

첫째, EventBridge Target으로 Lambda함수를 넣어주는 작업.

resource "aws_cloudwatch_event_target" "example_target" {
  arn       = data.terraform_remote_state.lambda.outputs.example_lambda_arn
  rule      = aws_cloudwatch_event_rule.example_cw_event.name
}

둘째, Lambda함수에서 EventBridge에서 실행할 수 있도록 권한을 생성하는 작업

resource "aws_lambda_permission" "kps_lambda_event_prod_daily_report" {
  statement_id  = "AllowExecutionFromCloudWatch"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.kps_lambda_prod_daily_report.function_name
  principal     = "events.amazonaws.com"
  source_arn    = data.terraform_remote_state.cw.outputs.kps_cw_events_prod_daily_report_arn
}

마치며

테라폼으로 AWS리소스를 생성하는 작업은 AWS콘솔로 리소스를 생성하는 것보다 더 많은 노하우를 필요로 하는 것 같습니다. AWS콘솔로 리소스를 생성하는 것에 통달하고 있어야하며 파라미터 하나하나 어떤 의미인지 이해하고 있어야 하기 때문입니다.

그렇기 때문에 앞으로 많은 많은 사람들과 노하우를 주고 받았으면 합니다. 오늘은 여기까지 입니다. 감사합니다.

반응형