diff --git a/.gitignore b/.gitignore index 553aafc..fe885dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .terraform tfvars/ +*.tfvars *.exe *.backup *.tfstate diff --git a/aws/ecs-server/rolling-update/variables.tf b/aws/ecs-server/rolling-update/variables.tf index 84b37d8..68cd484 100644 --- a/aws/ecs-server/rolling-update/variables.tf +++ b/aws/ecs-server/rolling-update/variables.tf @@ -16,7 +16,6 @@ variable "environment" { type = string } - // 서버명 (server_name-environment 형태로 구성됩니다.) variable "server_name" { description = "The name of the server machine you want to create." diff --git a/aws/lambder-server/README.md b/aws/lambder-server/README.md new file mode 100644 index 0000000..ea8380d --- /dev/null +++ b/aws/lambder-server/README.md @@ -0,0 +1,3 @@ +# lambda server + +- Lambda 기반의 웹서버 구성입니다. diff --git a/aws/lambder-server/function_url/.terraform.lock.hcl b/aws/lambder-server/function_url/.terraform.lock.hcl new file mode 100644 index 0000000..4c4321e --- /dev/null +++ b/aws/lambder-server/function_url/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "4.66.1" + constraints = "~> 4.16" + hashes = [ + "h1:i5PN+Xs0DXLe6a512XELJcYvFN4oYOkg+WMT39AzgRw=", + "zh:001c707174b7d6bf89a96cf806f925bb852d1a285fb80b81222cbeb4743bcb79", + "zh:19bc6ac0a7fd1c564fd56c536f1743f71a5e7ca724e21ea51a6a79218939733d", + "zh:3dac5c27f40b511239e9fe6f97dc0b6c95f630ba328001820ddc764e766a5ca2", + "zh:49092c92e2565db4cd4c98ec6878386e6957525d3392b63f0d5df4c48a7c1913", + "zh:4f9e2e1d0c5365a4e6689096cc91ba88ca9c0dc7c633377ba674c1dd856b6a9f", + "zh:57e32bb454f2dc17d5631a9559e36188761d8ae95a452478f81f41bb568a3a42", + "zh:678b78ba629dd833f0705ac90630969f514a54013ab9713ce7ceda55fc5ea138", + "zh:8aab1d76348cf2a685f72382cb838a910b77353179e81ab5794b9c45c8fb36a3", + "zh:8b6791bf0948aa8b49258863992a8ad7e7332dcae1a889e86da0e5ab778dc3b6", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:a36f2777452c2cebdaa8a27378416d512ead367acc078a671bb12276dd4bc9dd", + "zh:c492e6f685882fad6481f4793e696d9e1b01aaae419225c2db0a484b632d1cac", + "zh:d4418e0d1d18e321db364a91d7a768e274bb0fb46df9f3cb5b9debb2bb6917b9", + "zh:d5b4310ef2b2ec22ae14cf909deb1231b56bdd79dc2b51e5db4e46a05e0110c4", + "zh:dedfb01e26b34fb61a52b7e953b8bf5d7a69971187e91697b67221298bbed377", + ] +} diff --git a/aws/lambder-server/function_url/README.md b/aws/lambder-server/function_url/README.md new file mode 100644 index 0000000..1a731c3 --- /dev/null +++ b/aws/lambder-server/function_url/README.md @@ -0,0 +1,45 @@ +# Lambda web Server with function URL + +- 가난한 이들을 위한 Lambda 기반의 간단한 웹서버 세팅 +- 장점: 비용이 0부터 시작함. 트래픽이 한달 호출 100만건을 넘지 않으면 비용이 부과되지 않음 +- 단점: 커스텀 도메인을 달 수 없음. + +## 리소스 구성 + +1. Lambda +2. Lambda Function URL +3. Github Action (직접 구성. 예시는 아래에) +4. DynamoDB + +## 프로젝트 템플릿 + +- 현재는 Axum 서버만 고려한 상태입니다. + +### Axum(Rust) + +- [템플릿](https://github.com/myyrakle/axum_serverless_template) 프로젝트를 clone하거나 fork해서 사용합니다. + +## before + +1. github에 레포지토리를 생성합니다. +2. github sercet에 AWS_ACCESS_KEY_ID와 AWS_SECRET_ACCESS_KEY를 추가합니다. + +--- + +## parameter 설정 + +- 자세한 것은 [](./variables.tf)에서 확인하거나 수정할 수 있습니다. + +### required parameter + +1. region: 리전 정보입니다. 서울이라면 ap-northeast-2 값을 넘겨줍니다. +2. environment: 환경 정보입니다. server_name과 조합되어 고유의 리소스 이름을 형성합니다. prod, stage, dev 등의 값을 설정하면 됩니다. +3. server_name: 서버명입니다. environment와 조합해서 고유의 리소스 이름을 형성합니다. + +### optional parameter + +1. lambda_runtime: 람다 런타임. 현재는 커스텀(provided.al2)만 고려해둔 상태입니다. +2. lambda_layers: 컨테이너 포트포워딩 설정입니다. +3. cors_allow_origins: cors 설정. Frontend(브라우저)와 연동할 경우 와일드카드(\*)를 삭제하고 해당 호스트 주소를 추가합니다. +4. cors_allow_headers: cors 설정 +5. cors_expose_headers: cors 설정 diff --git a/aws/lambder-server/function_url/codes/axum.zip b/aws/lambder-server/function_url/codes/axum.zip new file mode 100644 index 0000000..7aa5837 Binary files /dev/null and b/aws/lambder-server/function_url/codes/axum.zip differ diff --git a/aws/lambder-server/function_url/dynamo.tf b/aws/lambder-server/function_url/dynamo.tf new file mode 100644 index 0000000..baf23b9 --- /dev/null +++ b/aws/lambder-server/function_url/dynamo.tf @@ -0,0 +1,29 @@ +# 테이블을 여기에서 정의합니다. + +// 유저 테이블 +resource "aws_dynamodb_table" "user-table" { + name = "${local.resource_id}-user" + billing_mode = "PAY_PER_REQUEST" + hash_key = "uuid" + # range_key = "" + + attribute { + name = "uuid" + type = "S" + } + + attribute { + name = "email" + type = "S" + } + + // 글로벌 보조 인덱스 + global_secondary_index { + name = "email-index" + hash_key = "email" + // range_key = "" + projection_type = "ALL" + } + + tags = local.tags +} diff --git a/aws/lambder-server/function_url/locals.tf b/aws/lambder-server/function_url/locals.tf new file mode 100644 index 0000000..a5f7e20 --- /dev/null +++ b/aws/lambder-server/function_url/locals.tf @@ -0,0 +1,12 @@ +data "aws_caller_identity" "current" {} + +locals { + tags = { + Environment = var.environment + Application = var.server_name + } + + resource_id = join("-", [var.server_name, var.environment]) + + account_id = data.aws_caller_identity.current.account_id +} diff --git a/aws/lambder-server/function_url/main.tf b/aws/lambder-server/function_url/main.tf new file mode 100644 index 0000000..3ab97c4 --- /dev/null +++ b/aws/lambder-server/function_url/main.tf @@ -0,0 +1,47 @@ +terraform { + required_providers { + # 일종의 라이브러리 로드 + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = var.region +} + +resource "aws_lambda_function" "lambda" { + description = "A lambda function for ${local.resource_id}}" + function_name = local.resource_id + role = aws_iam_role.lambda_role.arn + layers = var.lambda_layers + runtime = var.lambda_runtime + handler = "hello.handler" + filename = "codes/axum.zip" + + environment { + variables = { + ServerName = var.server_name + ENVIRONMENT = var.environment + } + } +} + +// Function Url +resource "aws_lambda_function_url" "release_url" { + function_name = aws_lambda_function.lambda.function_name + authorization_type = "NONE" + + cors { + allow_credentials = true + allow_origins = var.cors_allow_origins + allow_methods = ["*"] + allow_headers = var.cors_allow_headers + expose_headers = var.cors_expose_headers + max_age = 86400 + } +} diff --git a/aws/lambder-server/function_url/outputs.tf b/aws/lambder-server/function_url/outputs.tf new file mode 100644 index 0000000..44cf42c --- /dev/null +++ b/aws/lambder-server/function_url/outputs.tf @@ -0,0 +1,9 @@ +output "function_url" { + value = aws_lambda_function_url.release_url.function_url + description = "Function Url" +} + +output "function_name" { + value = aws_lambda_function_url.release_url.function_name + description = "Function Name" +} diff --git a/aws/lambder-server/function_url/roles.tf b/aws/lambder-server/function_url/roles.tf new file mode 100644 index 0000000..e9ce728 --- /dev/null +++ b/aws/lambder-server/function_url/roles.tf @@ -0,0 +1,48 @@ +// Lambda Role +resource "aws_iam_role" "lambda_role" { + name = local.resource_id + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Effect" : "Allow", + "Principal" : { + "Service" : ["lambda.amazonaws.com"] + }, + "Action" : [ + "sts:AssumeRole" + ] + } + ] + }) + + inline_policy { + name = "root" + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Sid" : "SpecificTable", + "Effect" : "Allow", + "Action" : [ + "dynamodb:BatchGet*", + "dynamodb:DescribeStream", + "dynamodb:DescribeTable", + "dynamodb:Get*", + "dynamodb:Query", + "dynamodb:Scan", + "dynamodb:BatchWrite*", + "dynamodb:CreateTable", + "dynamodb:Delete*", + "dynamodb:Update*", + "dynamodb:PutItem" + ], + "Resource" : [ + // 테이블을 추가할 때마다 여기에도 리소스를 추가해줍니다. + "arn:aws:dynamodb:*:*:table/${local.resource_id}_user" + ] + } + ] + }) + } +} diff --git a/aws/lambder-server/function_url/variables.tf b/aws/lambder-server/function_url/variables.tf new file mode 100644 index 0000000..c6bf86a --- /dev/null +++ b/aws/lambder-server/function_url/variables.tf @@ -0,0 +1,57 @@ +// 리전 +variable "region" { + description = "region" + type = string +} + +// tag 및 리소스 이름 구성에 사용됨 +variable "environment" { + description = "environment info. (e.g: prod, dev, stage, test)" + type = string +} + +// 서버명 (server_name-environment 형태로 구성됩니다.) +variable "server_name" { + description = "The name of the server machine you want to create." + type = string +} + +// Lambda runtime +// https://docs.aws.amazon.com/lambda/latest/dg/API_CreateFunction.html#SSS-CreateFunction-request-Runtime 참조 +// 커스텀 런타임은 provided.al2, provided +// nodejs | nodejs4.3 | nodejs6.10 | nodejs8.10 | nodejs10.x | nodejs12.x | nodejs14.x | nodejs16.x | java8 | java8.al2 | java11 | python2.7 | python3.6 | python3.7 | python3.8 | python3.9 | dotnetcore1.0 | dotnetcore2.0 | dotnetcore2.1 | dotnetcore3.1 | dotnet6 | nodejs4.3-edge | go1.x | ruby2.5 | ruby2.7 | provided | provided.al2 | nodejs18.x | python3.10 | java17 +variable "lambda_runtime" { + description = "lambda runtime" + type = string + default = "provided.al2" +} + +// Lambda layers +variable "lambda_layers" { + description = "layer arn list" + type = list(string) + default = [] +} + +// cors 설정 +// Frontend(브라우저)와 연동할 경우 와일드카드(*)를 삭제하고 해당 호스트 주소를 추가합니다. +variable "cors_allow_origins" { + description = "cors allow origins" + type = list(string) + default = ["*"] +} + +// cors 설정 +variable "cors_allow_headers" { + description = "cors allow headers" + type = list(string) + default = ["date", "keep-alive", "content-type", "authorization"] +} + +// cors 설정 +variable "cors_expose_headers" { + description = "cors expose headers" + type = list(string) + default = ["date", "keep-alive"] +} +