Terraform 으로 aws lambda & function url 만들기 (단일 람다 함수에 API GW 없이 URL 붙이기)
Announcing AWS Lambda Function URLs: Built-in HTTPS Endpoints for Single-Function Microservices | Amazon Web Services
Organizations are adopting microservices architectures to build resilient and scalable applications using AWS Lambda. These applications are composed of multiple serverless functions that implement the business logic. Each function is mapped to API endpoints, methods, and resources using services su…

지금까지는 aws lambda를 URL로 서빙하려면 API Gateway 없이는 불가능했다. 하지만, 이제는 하나의 lambda에 하나의 url을 붙일 수 있다. 그리고 이 프로비저닝을 코드로 관리할 수도 있게 되었다.
GitHub - byunjuneseok/aws-lambda-function-urls-with-terraform: Built-in HTTPS Endpoints for Single-Function Microservices. Example with terraform!
Built-in HTTPS Endpoints for Single-Function Microservices. Example with terraform! - GitHub - byunjuneseok/aws-lambda-function-urls-with-terraform: Built-in HTTPS Endpoints for Single-Function Mic...
terraform aws provider version
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.11.0"
}
}
}
provider "aws" {
profile = var.aws_profile
region = var.aws_region
}
terraform의 aws provider 버전은 4.9.0이상이어야 지원한다.
IAM
data "aws_caller_identity" "current" {}
이 data를 통해 data.aws_caller_identity.current.account_id
12자리 aws 계정번호를 얻을 수 있으니 선언해두도록 한다.
resource "aws_iam_role" "lambda" {
name = "iam_${var.function_name}"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_policy" "lambda" {
name = "policy_${var.function_name}"
policy = templatefile("policy.json.tftpl", {
aws_account_id = data.aws_caller_identity.current.account_id
aws_region = var.aws_region,
function_name = var.function_name
})
}
resource "aws_iam_role_policy_attachment" "iam_for_lambda" {
role = aws_iam_role.lambda.name
policy_arn = aws_iam_policy.lambda.arn
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:${aws_region}:${aws_account_id}:*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:${aws_region}:${aws_account_id}:log-group:/aws/lambda/${function_name}:*"
]
}
]
}
IAM권한은 위와 같이 최소 권한을 주어준다. DynamoDB 같은 리소스를 사용하길 원한다면 policy.json.tftpl
에 정책을 추가해주면 된다.
lambda 선언
resource "aws_lambda_function" "lambda" {
function_name = var.function_name
filename = "lambda.zip"
handler = "handler"
role = aws_iam_role.lambda.arn
source_code_hash = filebase64sha256("lambda.zip")
runtime = "go1.x"
environment {
variables = {
foo = "bar"
}
}
}
람다는 위와같이 선언한다. 기존과 다를 것이 없다.
Function URL 붙이기
resource "aws_lambda_function_url" "lambda" {
function_name = aws_lambda_function.lambda.function_name
authorization_type = "NONE"
}
람다 이름으로 Function url을 할당해주면 끝이다. 인증 없는 url 엔드포인트를 바로 확인할 수 있다.
output "lambda_url" {
value = aws_lambda_function_url.lambda.function_url
}
아웃풋까지 지정해주면 terraform apply
를 입력했을 때 다음과 같은 url을 얻을 수 있을 것이다.


인증이 붙은 Function URL 붙이기
resource "aws_lambda_function_url" "test_live" {
function_name = aws_lambda_function.test.function_name
qualifier = "my_alias"
authorization_type = "AWS_IAM"
}
authorization_type
을 AWS_IAM
으로 지정하면 AWS IAM Sigv4 시그니처 인증을 거치게 된다.
CORS 사용
resource "aws_lambda_function_url" "test_live" {
function_name = aws_lambda_function.test.function_name
qualifier = "my_alias"
authorization_type = "AWS_IAM"
cors {
allow_credentials = true
allow_origins = ["*"]
allow_methods = ["*"]
allow_headers = ["date", "keep-alive"]
expose_headers = ["keep-alive", "date"]
max_age = 86400
}
}
마이크로서비스를 위한 기능이다보니 CORS 기능도 당연히 포함되어 있다.
요약
- 커스텀 도메인 불가능
- 인증은 직접 구현하는게 아니라면 IAM 인증 가능
- 비용은 없음, 오직 람다 비용만 청구
- Cloudwatch Access Logs 안쌓임
- Cloudwatch Metrics는 남음
- HTTP Response timeout 최대 15분! (API GW는 29초)
간단한 웹훅이나, 백오피스, 29초의 응답시간을 넘겨야하는 케이스에서 생산성을 높여줄 것으로 보인다.