Introduction
In this article, we are going to discuss how to deploy an AWS Lambda function using Terraform in a way that’s simple and accessible for all levels of users. In today’s cloud-first world, serverless computing has become a game-changer for developers and organizations alike. AWS Lambda allows you to run code without provisioning or managing servers, making it an excellent choice for building scalable applications. Whether you’re new to cloud computing or an experienced developer, this tutorial will guide you through every step of deploying an AWS Lambda function using Terraform, a powerful infrastructure-as-code (IaC) tool that automates the creation and management of your cloud infrastructure. By the end of this tutorial, you’ll have a clear understanding of how to use Terraform to deploy serverless applications with ease.
Prerequisites
Before we dive into the tutorial, ensure you have the following:
- AWS Account: You’ll need an active AWS account to deploy resources.
- Terraform Installed: Install Terraform on your local machine. You can follow the official Terraform installation guide to get started.
- AWS CLI Configured: Ensure your AWS CLI is configured with the necessary credentials. You can set this up by following the AWS CLI configuration guide
Define the Terraform Configuration
First, we’ll create a Terraform configuration file to define the AWS resources needed for our Lambda function. Below is a breakdown of the configuration:
Terraform Block
The terraform
block specifies the required provider and Terraform version.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
required_version = ">= 1.4.6"
}
Go- required_providers: Specifies the AWS provider, ensuring that Terraform downloads and uses the correct version.
- required_version: Ensures compatibility with the specified Terraform version.
AWS Provider Configuration
The provider
block sets up the AWS provider and specifies the region.
provider "aws" {
region = "us-east-1"
}
Go- provider: The AWS provider block configures the region where your resources will be deployed.
S3 Bucket for Lambda Deployment
Next, we define an S3 bucket where the Lambda function’s code will be stored.
resource "aws_s3_bucket" "lambda_bucket" {
bucket = "buckettfdemo2"
}
Go- aws_s3_bucket: Creates an S3 bucket named
buckettfdemo2
where the Lambda ZIP file will be uploaded.
Upload Lambda Code to S3
We upload the ZIP file containing the Lambda function code to the S3 bucket.
resource "aws_s3_bucket_object" "lambda_zip" {
bucket = aws_s3_bucket.lambda_bucket.bucket
key = "main.zip"
source = "main.zip"
}
Go- aws_s3_bucket_object: Uploads the
main.zip
file from your local machine to the S3 bucket.
Create IAM Role for Lambda
The IAM role grants the necessary permissions for the Lambda function to execute.
resource "aws_iam_role" "lambda_role" {
name = "my_lambda_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
Go- aws_iam_role: Defines a role that allows the Lambda function to assume permissions specified in the policy.
Attach Policies to IAM Role
We attach the AWSLambdaBasicExecutionRole policy to the IAM role.
resource "aws_iam_role_policy_attachment" "lambda_policy_attachment" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
role = aws_iam_role.lambda_role.name
}
Go- aws_iam_role_policy_attachment: Attaches the basic execution role to the IAM role, granting it necessary permissions.
Define the Lambda Function
Now, we define the Lambda function and link it to the S3 bucket and IAM role.
resource "aws_lambda_function" "my_lambda" {
function_name = "my-go-lambda"
s3_bucket = aws_s3_bucket.lambda_bucket.bucket
s3_key = aws_s3_bucket_object.lambda_zip.key
handler = "bootstrap"
runtime = "provided.al2"
role = aws_iam_role.lambda_role.arn
source_code_hash = filebase64sha256("main.zip")
}
Go- aws_lambda_function: Defines the Lambda function, specifying its name, runtime environment, and source code.
Set Up API Gateway
We create an API Gateway to expose the Lambda function as a REST API.
resource "aws_api_gateway_rest_api" "my_api" {
name = "my-api"
description = "API Gateway for Lambda function"
}
Go- aws_api_gateway_rest_api: Creates an API Gateway to route HTTP requests to your Lambda function.
Define API Gateway Resources and Methods
We define the resources and methods within the API Gateway.
resource "aws_api_gateway_resource" "my_resource" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
parent_id = aws_api_gateway_rest_api.my_api.root_resource_id
path_part = "myresource"
}
resource "aws_api_gateway_method" "my_method" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.my_resource.id
http_method = "POST"
authorization = "NONE"
}
Go- aws_api_gateway_resource: Creates a new resource path within the API Gateway.
- aws_api_gateway_method: Defines the HTTP method (POST) for the resource.
Integrate API Gateway with Lambda
We integrate the API Gateway with the Lambda function.
resource "aws_api_gateway_integration" "my_integration" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.my_resource.id
http_method = aws_api_gateway_method.my_method.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/${aws_lambda_function.my_lambda.arn}/invocations"
passthrough_behavior = "WHEN_NO_MATCH"
content_handling = "CONVERT_TO_TEXT"
}
Go- aws_api_gateway_integration: Configures API Gateway to use the Lambda function as the backend for the POST request.
Deploy the API Gateway
Finally, we deploy the API Gateway.
resource "aws_api_gateway_deployment" "my_deployment" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
stage_name = "prod"
depends_on = [
aws_api_gateway_integration.my_integration
]
}
Go- aws_api_gateway_deployment: Deploys the API Gateway, making it accessible at a public URL.
Grant API Gateway Permission to Invoke Lambda
We grant the API Gateway permission to invoke the Lambda function.
resource "aws_lambda_permission" "allow_api_gateway" {
statement_id = "AllowExecutionFromApiGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.my_lambda.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.my_api.execution_arn}/*/*/*"
}
Go- aws_lambda_permission: Allows API Gateway to trigger the Lambda function.
Output the API Gateway URL
Finally, we output the API Gateway URL to easily access the deployed function.
output "api_url" {
value = "https://${aws_api_gateway_rest_api.my_api.id}.execute-api.us-east-1.amazonaws.com/prod/myresource"
description = "The URL of the API Gateway endpoint"
}
Go- output: Displays the API Gateway URL after deployment.
Running Terraform and Deploying to AWS
With the configuration in place, follow these steps to deploy your infrastructure:
Step 1: Initialize Terraform
Run the following command to initialize your Terraform working directory:
terraform init
Step 2: Validate the Configuration
Ensure there are no errors in your configuration by running:
terraform validate
Step 3: Create an Execution Plan
Generate a plan to preview the changes Terraform will apply:
terraform plan
Step 4: Apply the Configuration
Deploy your AWS resources by applying the configuration:
terraform apply
Confirm the prompt to proceed.
Step 5: Verify the Deployment
After the deployment, use the API Gateway URL to test your Lambda function:
curl -X POST <Your-API-Gateway-URL>
Step 6: Clean Up Resources
To delete the resources, run:
terraform destroy
Conclusion
In this article, we’ve learned how to deploy an AWS Lambda function using Terraform, complete with an API Gateway integration. This process simplifies managing cloud infrastructure, allowing you to focus on building and scaling applications.
The complete source code is available on GitHub.