Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New serverless pattern - alb-lambda-terraform #1507

Merged
merged 2 commits into from
Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions alb-lambda-terraform/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*.js
!jest.config.js
*.d.ts
node_modules
!/lib
3 changes: 3 additions & 0 deletions alb-lambda-terraform/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.ts
!*.d.ts

54 changes: 54 additions & 0 deletions alb-lambda-terraform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Application Load balancer with AWS Lambda as target with Terraform

This pattern demonstrates how to create an Application Load Balancer with AWS Lambda as target. Implemented in Terraform.

Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/alb-lambda-terraform

Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.

## Requirements

* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
* [Terraform Installed](https://developer.hashicorp.com/terraform/downloads)

## Deployment Instructions

1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
```
git clone https://github.com/aws-samples/serverless-patterns
```
2. Change directory to the pattern directory:
```
cd alb-lambda-terraform
```
3. From the command line, run:
```
terraform init
```
4. From the command line, run:
```
terraform plan
```
5. From the command line, run:
```
terraform apply --auto-approve
```

## Testing

1. In the stack output, you can see `alb_url`. When you access the url, you should see the response "Hello World" from Lambda.

** Please note: Application Load Balancer's default settings for health check are 5 consecutive health check successes with 35 seconds interval. So, it will take couple of minutes for the target to be healthy.

## Cleanup

1. To delete the stack, run:
```bash
terraform destroy --auto-approve
```
----
Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.

SPDX-License-Identifier: MIT-0
58 changes: 58 additions & 0 deletions alb-lambda-terraform/example-pattern.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"title": "Application Load Balancer with Lambda as target",
"description": "Create an Application Load Balancer with Lambda as target using Terraform",
"language": "TypeScript",
"level": "200",
"framework": "Terraform",
"introBox": {
"headline": "How it works",
"text": [
"This sample project demonstrates how to create an Application Load Balancer with AWS Lambda as target.",
"Implemented in Terraform."
]
},
"gitHub": {
"template": {
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/alb-lambda-terraform",
"templateURL": "serverless-patterns/alb-lambda-terraform",
"projectFolder": "alb-lambda-terraform",
"templateFile": "alb-lambda-terraform/main.tf"
}
},
"resources": {
"bullets": [
{
"text": "Application Load Balancer",
"link": "https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html"
},
{
"text": "ALB - Lambda target",
"link": "https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html"
}
]
},
"deploy": {
"text": [
"terraform init",
"terraform apply"
]
},
"testing": {
"text": [
"See the Github repo for detailed testing instructions."
]
},
"cleanup": {
"text": [
"terraform destroy",
"terraform show"
]
},
"authors": [
{
"name": "Sumit Bhati",
"image": "https://avatars.githubusercontent.com/u/139027745",
"bio": "I am a Customer Solutions Manager at AWS"
}
]
}
Binary file added alb-lambda-terraform/lambda.zip
Binary file not shown.
197 changes: 197 additions & 0 deletions alb-lambda-terraform/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# Required providers configuration
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>4.52.0"
}
}

required_version = "~> 1.0"
}

# AWS provider configuration
provider "aws" {
profile = "default"
region = "us-east-1"
}

# Create AWS VPC
resource "aws_vpc" "vpc" {
cidr_block = var.vpc_cidr

}

# Create public subnet 1
resource "aws_subnet" "public_subnet1" {
cidr_block = "10.0.1.0/24"
vpc_id = aws_vpc.vpc.id
availability_zone = "${var.region}a"
tags = {
Name = "Subnet for ${var.region}a"
}
}

# Create public subnet 2
resource "aws_subnet" "public_subnet2" {
cidr_block = "10.0.2.0/24"
vpc_id = aws_vpc.vpc.id
availability_zone = "${var.region}b"
tags = {
Name = "Subnet for ${var.region}b"
}
}

# Create a route table
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.vpc.id

route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gw.id
}

tags = {
Name = "public_rt"
}
}

# Associate the route table with public subnet 1
resource "aws_route_table_association" "public_rt_table_a" {
subnet_id = aws_subnet.public_subnet1.id
route_table_id = aws_route_table.public_rt.id
}

# Associate the route table with public subnet 2
resource "aws_route_table_association" "public_rt_table_b" {
subnet_id = aws_subnet.public_subnet2.id
route_table_id = aws_route_table.public_rt.id
}

# Create an Internet Gateway
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.vpc.id
}

# Create IAM Role for Lambda Function
resource "aws_iam_role" "lambda_role" {
name = "Lambda_Function_Role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

# Create IAM policy for Lambda to write logs
resource "aws_iam_policy" "iam_policy_for_lambda" {

name = "aws_iam_policy_for_terraform_aws_lambda_role"
path = "/"
description = "AWS IAM Policy for managing aws lambda role"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*",
"Effect": "Allow"
}
]
}
EOF
}

# Attach the IAM policy for writing logs to the Lambda Role
resource "aws_iam_role_policy_attachment" "attach_iam_policy_to_iam_role" {
role = aws_iam_role.lambda_role.name
policy_arn = aws_iam_policy.iam_policy_for_lambda.arn
}

# Create a security group for application load balancer
resource "aws_security_group" "load_balancer_sg" {
name = "myLoadBalancerSG"
vpc_id = aws_vpc.vpc.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "myLoadBalancerSG"
}
}

# Create the application load balancer
resource "aws_lb" "load_balancer" {
name = "myLoadBalancer"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.load_balancer_sg.id]
subnets = [aws_subnet.public_subnet1.id,aws_subnet.public_subnet2.id]
tags = {
Name = "myLoadBalancer"
}
}

# Create the ALB listener with the target group.
resource "aws_lb_listener" "listener" {
load_balancer_arn = aws_lb.load_balancer.arn
port = 80
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = "${aws_lb_target_group.target_group.arn}"
}
}

# Create the ALB target group for Lambda
resource "aws_lb_target_group" "target_group" {
name = "myLoadBalancerTargets"
target_type = "lambda"
vpc_id = aws_vpc.vpc.id
}

# Attach the ALB target group to the Lambda Function
resource "aws_lb_target_group_attachment" "target_group_attachment" {
target_group_arn = aws_lb_target_group.target_group.arn
target_id = aws_lambda_function.lambda_function.arn
}

# Create the Lambda Function
resource "aws_lambda_function" "lambda_function" {
function_name = "lambdaFunction"
runtime = "nodejs14.x"
handler = "index.handler"
filename = "lambda.zip"
role = aws_iam_role.lambda_role.arn
depends_on = [aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role]
tags = {
Name = "lambdaFunction"
}
}

# Allow the application load balancer to access Lambda Function
resource "aws_lambda_permission" "with_lb" {
statement_id = "AllowExecutionFromlb"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.lambda_function.arn
principal = "elasticloadbalancing.amazonaws.com"
source_arn = aws_lb_target_group.target_group.arn
}
6 changes: 6 additions & 0 deletions alb-lambda-terraform/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Output value definitions

output "alb_url" {
value = "http://${aws_lb.load_balancer.dns_name}"
}

11 changes: 11 additions & 0 deletions alb-lambda-terraform/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
variable "region" {
type=string
description = "AWS Region where deploying resources"
default = "us-east-1"
}

variable "vpc_cidr" {
type=string
description = "CIDR block for Batch VPC"
default = "10.0.0.0/16"
}