Skip to content

New serverless pattern - Amazon VPC Lattice with AWS Lambda as weighted targets (Terraform) #2600

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
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
69 changes: 69 additions & 0 deletions vpc-lattice-lambda-tf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Amazon VPC Lattice with AWS Lambda as weighted targets

This pattern demonstrates how to create a VPC Lattice which shifts traffic to different targets based on the weighted routing policy.

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](https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started) installed

## Deployment Instructions

1. Create a new directory, navigate to that directory in a terminal and clone the repository:
```
git clone https://github.com/aws-samples/serverless-patterns
```
2. Change directory to the pattern directory:
```
cd serverless-patterns/vpc-lattice-lambda-tf
```
3. From the command line, initialize Terraform to downloads and install the providers defined in the configuration:
```
terraform init
```
4. From the command line, apply the configuration in the main.tf file:
```
terraform apply
```
5. Note the outputs from the deployment process. These contain the resource names and/or ARNs which are used for testing.

## How it works

VPC Lattice is to designed to help you easily and effectively discover, secure, connect, and monitor all of the services within it. Each component within VPC Lattice communicates unidirectionally or bi-directionally within the service network based on its association with the service network and its access settings. Access settings are comprised of authentication and authorization policies required for this communication.

This pattern creates below resources:

1. A new VPC with CIDR of 10.0.0.0/16
2. A private subnet
3. Security Group allowing inbound traffic from VPC CIDR 10.0.0.0/16
4. VPC Lattice service
5. VPC Lattice Listener
6. VPC Lattice Service Network
7. VPC Lattice Network Association and Service Association
8. Two Lambda functions (Primary and Secondary) to demonstrate traffic shift.
9. One Lambda function (Demo) to verify traffic shift by calling VPC lattice service DNS.

This pattern uses Lambda as weighted targets. VPC Lattice service shifts traffic based on the percentage of weight configured for target groups under VPC Lattice listener. User may update the weight for the targets according to their use case and requirements.

## Testing

Invoke Demo Lambda function using CLI/Console and observe traffic shift from VPC Lattice service.

## Cleanup

1. Delete all created resources by Terraform
```bash
terraform destroy
```
2. Confirm all created resources has been deleted
```bash
terraform show
```
----
Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.

SPDX-License-Identifier: MIT-0
Binary file added vpc-lattice-lambda-tf/demolambda.zip
Binary file not shown.
60 changes: 60 additions & 0 deletions vpc-lattice-lambda-tf/example-pattern.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"title": "Amazon VPC Lattice with AWS Lambda as weighted targets",
"description": "This pattern demonstrates how to create a VPC Lattice which shifts traffic to different targets based on the weighted routing policy.",
"language": "Python",
"level": "200",
"framework": "Terraform",
"introBox": {
"headline": "How it works",
"text": [
"VPC Lattice is to designed to help you easily and effectively discover, secure, connect, and monitor all of the services within it. Each component within VPC Lattice communicates unidirectionally or bi-directionally within the service network based on its association with the service network and its access settings. Access settings are comprised of authentication and authorization policies required for this communication.",
"This pattern uses Lambda as weighted targets. VPC Lattice service shifts traffic based on the percentage of weight configured for target groups under VPC Lattice listener. User may update the weight for the targets according to their use case and requirements."
]
},
"gitHub": {
"template": {
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/vpc-lattice-lambda-tf",
"templateURL": "serverless-patterns/vpc-lattice-lambda-tf",
"projectFolder": "vpc-lattice-lambda-tf",
"templateFile": "main.tf"
}
},
"resources": {
"bullets": [
{
"text": "VPC Lattice Service",
"link": "https://docs.aws.amazon.com/vpc-lattice/latest/ug/what-is-vpc-lattice.html"
},
{
"text": "Lambda",
"link": "https://docs.aws.amazon.com/lambda/latest/dg/welcome.html"
}
]
},
"deploy": {
"text": [
"terraform init",
"terraform apply"
]
},
"testing": {
"text": [
"Invoke Demo Lambda function using CLI/Console and observe traffice shift from VPC Lattice service."
]
},
"cleanup": {
"text": [
"<code>terraform destroy</code>",
"terraform show"
]
},
"authors": [
{
"name": "Makendran G",
"image": "https://drive.google.com/file/d/1mUObnbmn52UWL-Zn39EpgpneiBNv3LCN/view?usp=sharing",
"bio": "Cloud Support Engineer @ AWS",
"linkedin": "makendran",
"twitter": "@MakendranG"
}
]
}
226 changes: 226 additions & 0 deletions vpc-lattice-lambda-tf/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
# Provider Configuration
provider "aws" {
region = "us-east-1" # Change this to your desired region
}

# Variables
variable "vpc_cidr" {
default = "10.0.0.0/16"
}

variable "subnet_cidr" {
default = "10.0.7.0/24"
}

# VPC Resources
resource "aws_vpc" "vpc_lattice_vpc" {
cidr_block = var.vpc_cidr
enable_dns_support = true
enable_dns_hostnames = true
instance_tenancy = "default"
}

resource "aws_subnet" "vpc_subnet" {
vpc_id = aws_vpc.vpc_lattice_vpc.id
cidr_block = var.subnet_cidr
availability_zone = "${data.aws_region.current.name}b"
map_public_ip_on_launch = false

tags = {
Name = "Private-new-availability"
}
}

# Security Group
resource "aws_security_group" "vpc_lattice_sg" {
name = "VPCLatticeServiceNetworkSecurityGroup"
description = "Security group for VPC LatticeService"
vpc_id = aws_vpc.vpc_lattice_vpc.id

ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"]
}

egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}

# VPC Lattice Resources
resource "aws_vpclattice_service_network" "vl_service_network" {
name = "vl-test-service-network"
auth_type = "NONE"
}

resource "aws_vpclattice_service" "vl_service" {
name = "vl-test-service"
auth_type = "NONE"
}

# IAM Role for Lambda Functions
resource "aws_iam_role" "lambda_role" {
name = "vpc_lattice_lambda_role"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}

# Attach basic Lambda execution policy
resource "aws_iam_role_policy_attachment" "lambda_basic" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
role = aws_iam_role.lambda_role.name
}

# Attach VPC access policy for Lambda
resource "aws_iam_role_policy_attachment" "lambda_vpc" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
role = aws_iam_role.lambda_role.name
}

# Lambda Functions
resource "aws_lambda_function" "vl_function_primary" {
filename = "primary.zip"
function_name = "vl-function-primary"
role = aws_iam_role.lambda_role.arn
handler = "app.lambda_handler"
runtime = "python3.13"
architectures = ["x86_64"]
source_code_hash = filebase64sha256("primary.zip")
}

resource "aws_lambda_function" "vl_function_secondary" {
filename = "secondary.zip"
function_name = "vl-function-secondary"
role = aws_iam_role.lambda_role.arn
handler = "app.lambda_handler"
runtime = "python3.13"
architectures = ["x86_64"]
source_code_hash = filebase64sha256("secondary.zip")
}

resource "aws_lambda_function" "demo_lambda" {
filename = "demolambda.zip"
function_name = "demo-lambda"
role = aws_iam_role.lambda_role.arn
handler = "app.lambda_handler"
runtime = "python3.13"
architectures = ["x86_64"]
source_code_hash = filebase64sha256("demolambda.zip")

vpc_config {
subnet_ids = [aws_subnet.vpc_subnet.id]
security_group_ids = [aws_security_group.vpc_lattice_sg.id]
}

environment {
variables = {
URL = aws_vpclattice_service.vl_service.dns_entry[0].domain_name
}
}
}

# VPC Lattice Target Groups
resource "aws_vpclattice_target_group" "primary_tg" {
name = "vl-primary-target-group"
type = "LAMBDA"

config {
lambda_event_structure_version = "V2"
}
}

resource "aws_vpclattice_target_group_attachment" "primary_tg_attachment" {
target_group_identifier = aws_vpclattice_target_group.primary_tg.id
target {
id = aws_lambda_function.vl_function_primary.arn
}
}

resource "aws_vpclattice_target_group" "secondary_tg" {
name = "vl-secondary-target-group"
type = "LAMBDA"

config {
lambda_event_structure_version = "V2"
}
}

resource "aws_vpclattice_target_group_attachment" "secondary_tg_attachment" {
target_group_identifier = aws_vpclattice_target_group.secondary_tg.id
target {
id = aws_lambda_function.vl_function_secondary.arn
}
}

# VPC Lattice Listener
resource "aws_vpclattice_listener" "vl_listener" {
name = "vl-service-listener"
protocol = "HTTPS"
port = 443
service_identifier = aws_vpclattice_service.vl_service.id

default_action {
forward {
target_groups {
target_group_identifier = aws_vpclattice_target_group.primary_tg.id
weight = 60
}
target_groups {
target_group_identifier = aws_vpclattice_target_group.secondary_tg.id
weight = 40
}
}
}
}

# VPC Lattice Associations
resource "aws_vpclattice_service_network_service_association" "service_association" {
service_identifier = aws_vpclattice_service.vl_service.id
service_network_identifier = aws_vpclattice_service_network.vl_service_network.id
}

resource "aws_vpclattice_service_network_vpc_association" "vpc_association" {
vpc_identifier = aws_vpc.vpc_lattice_vpc.id
service_network_identifier = aws_vpclattice_service_network.vl_service_network.id
security_group_ids = [aws_security_group.vpc_lattice_sg.id]
}

# Outputs
output "vl_function_primary_arn" {
value = aws_lambda_function.vl_function_primary.arn
}

output "vl_function_secondary_arn" {
value = aws_lambda_function.vl_function_secondary.arn
}

output "vl_service_network_id" {
value = aws_vpclattice_service_network.vl_service_network.id
}

output "vl_service_id" {
value = aws_vpclattice_service.vl_service.id
}

output "vl_service_dns" {
value = aws_vpclattice_service.vl_service.dns_entry[0].domain_name
}

# Data source for current region
data "aws_region" "current" {}
Binary file added vpc-lattice-lambda-tf/primary.zip
Binary file not shown.
Binary file added vpc-lattice-lambda-tf/secondary.zip
Binary file not shown.
Loading