Seamlessly Integrating AWS NLB, ALB, and Lambda

wqwq
3 min readJul 13, 2024

--

Introdcution

AWS released that AWS ALB(ALB) can connect to AWS Lambda(Lambda).
We also can connect to AWS NLB(NLB) to ALB. So I want to write about this and how do we implement this

Overall

Component

What we want to discuss involves the following components. The request begins at the NLB, proceeds to the ALB, and finally reaches the Lambda. This flow is essential for understanding the system’s overall architecture and its operational efficiency. Let’s delve into the details to ensure we cover all aspects thoroughly.

Implementation

# nlb
resource "aws_lb" "sample_nlb" {
name = "nlb"
load_balancer_type = "network"
internal = true
enable_cross_zone_load_balancing = true
subnet_mapping {
subnet_id = aws_subnet.subnet["a"].id,
private_ipv4_address = "10.20.0.01"
}
}

resource "aws_lb_listener" "sample_nlb" {
load_balancer_arn = aws_lb.sample_nlb.arn
protocol = "TCP"
port = "80"

default_action {
type = "forward"
target_group_arn = aws_lb_target_group.sample_nlb_tg.arn
}
}

resource "aws_lb_target_group" "sample_nlb_tg" {
name = "nlb-tg"
target_type = "alb"
vpc_id = aws_vpc.sample.id
protocol = "TCP"
port = 80
}

resource "aws_lb_target_group_attachment" "sample_nlb_alb_attachment" {
target_group_arn = aws_lb_target_group.sample_nlb_tg.arn
target_id = aws_lb.alb.arn
port = 80
}


# alb
resource "aws_lb" "alb" {
name = "alb"
load_balancer_type = "application"
internal = true

subnets = [
aws_subnet.subnet["b"].id,
aws_subnet.subnet["c"].id,
]
security_groups = [
aws_security_group.alb_sg.id,
]
}

resource "aws_lb_listener" "alb_listener" {
load_balancer_arn = aws_lb.alb.arn
port = "80"
protocol = "HTTP"

default_action {
type = "forward"
target_group_arn = aws_lb_target_group.alb_tg.arn
}
}

resource "aws_lb_target_group" "alb_tg" {
name = "alb-tg"
vpc_id = aws_vpc.sample.id
target_type = "lambda"
protocol = "HTTP"
port = 80
}

resource "aws_lb_target_group_attachment" "lambda_attachment" {
target_group_arn = aws_lb_target_group.alb_tg.arn
target_id = module.sample.lambda_function_arn
}

# lambda
module "sample" {
source = "terraform-aws-modules/lambda/aws"

function_name = "sample"
description = "sample"
create_package = false
package_type = "Image"
image_uri = "${aws_ecr_repository.sample.repository_url}:latest"
timeout = 30

vpc_subnet_ids = [
aws_subnet.subnet["d"].id,
aws_subnet.subnet["e"].id,
]
vpc_security_group_ids = [
aws_security_group.alb_to_lambda.id,
]
attach_network_policy = true

environment_variables = {
ENV = "hoge"
}
}

resource "aws_lambda_permission" "with_lb" {
statement_id = "AllowExecutionFromlb"
action = "lambda:InvokeFunction"
function_name = module.receive_notification.lambda_function_arn
principal = "elasticloadbalancing.amazonaws.com"
source_arn = aws_lb_target_group.alb_tg.arn
}

Checkpoint

NLB has heealth check by default

This means we have to implement health check path in lambda. Unlike with an ALB, where we can manually configure and manage health checks, this functionality cannot be manually removed or bypassed in the case of Lambda.

Request from NLB is a Event

The request from the NLB is structured as follows. We retrieve the path through the event object, which differs slightly from typical HTTP frameworks like Gin or Echo. This method introduces some unique nuances in handling requests. Although you might find this repository helpful for implementation, I haven’t had the chance to test it yet,
https://github.com/awslabs/aws-lambda-go-api-proxy

{
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a"
}
},
"httpMethod": "GET",
"path": "/lambda",
"queryStringParameters": {
"query": "1234ABCD"
},
...
...
}

Cross-zone load balancing in NLB

Enabling this function allows traffic to be distributed across all registered targets in every registered Availability Zone. This setup provides an efficient way to design redundancy, ensuring high availability, while keeping costs relatively low.

Lambda permission for Loadbalancer

Of course, it is essential to configure the permission to allow the LoadBalancer to invoke the Lambda.

resource "aws_lambda_permission" "with_lb" {
statement_id = "AllowExecutionFromlb"
action = "lambda:InvokeFunction"
function_name = module.sample.lambda_function_arn
principal = "elasticloadbalancing.amazonaws.com"
source_arn = aws_lb_target_group.alb_tg.arn
}

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response