The source code for this blog is available on GitHub.

Blog of NLAMONT Tech Guy.

Serverles and Terraform

Cover Image for Serverles and Terraform
Neil Lamont
Neil Lamont

Note testing chatgpt for writing blogs.

Deploying Serverless Applications with Terraform: A Comprehensive Guide

In today's rapidly evolving tech landscape, serverless architectures offer a compelling solution for building scalable and cost-effective applications. By leveraging serverless services, developers can focus on writing code without worrying about server management. Terraform, a popular Infrastructure as Code (IaC) tool, simplifies the deployment of serverless applications by allowing you to define your infrastructure in code. In this blog post, we'll explore how to deploy serverless applications using Terraform, complete with code examples.

Why Serverless?

Serverless architectures provide several benefits:

Cost Efficiency: Pay only for the compute time you consume. Scalability: Automatically scales with the demand. Reduced Operational Overhead: No need to manage servers or infrastructure. Getting Started with Terraform Before we dive into the code, ensure you have the following prerequisites:

Terraform installed on your local machine. An AWS account. AWS CLI configured with appropriate permissions. Example: Deploying a Serverless REST API Let's create a simple serverless REST API using AWS Lambda and API Gateway.

Step 1: Define Your AWS Lambda Function

First, create a directory for your Terraform project and navigate to it. Then, create a file named main.tf and add the following code to define your AWS Lambda function:

` provider "aws" { region = "us-east-1" }

resource "aws_lambda_function" "my_lambda" { function_name = "my_serverless_function" handler = "index.handler" runtime = "nodejs14.x" role = aws_iam_role.lambda_exec.arn filename = "lambda_function_payload.zip"

source_code_hash = filebase64sha256("lambda_function_payload.zip") }

resource "aws_iam_role" "lambda_exec" { name = "lambda_exec_role"

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

resource "aws_iam_role_policy_attachment" "lambda_exec_attach" { role = aws_iam_role.lambda_exec.name policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" } `

In this example:

We define an AWS Lambda function named my_serverless_function. The handler is the entry point of your Lambda function. The runtime specifies the environment for the function. The role is the IAM role that AWS Lambda assumes when it executes the function. The filename points to the zip file containing your function code. Step 2: Create the Lambda Function Code Next, create your Lambda function code. In the same directory, create a file named index.js with the following content:

` exports.handler = async (event) => { return { statusCode: 200, body: JSON.stringify({ message: "Hello, World!" }), }; }; Then, zip the file:

zip lambda_function_payload.zip index.js Step 3: Define API Gateway Now, add the following code to main.tf to define an API Gateway that triggers the Lambda function:

resource "aws_api_gateway_rest_api" "my_api" { name = "MyServerlessAPI" }

resource "aws_api_gateway_resource" "lambda_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 = "hello" }

resource "aws_api_gateway_method" "get_method" { rest_api_id = aws_api_gateway_rest_api.my_api.id resource_id = aws_api_gateway_resource.lambda_resource.id http_method = "GET" authorization = "NONE" }

resource "aws_api_gateway_integration" "lambda_integration" { rest_api_id = aws_api_gateway_rest_api.my_api.id resource_id = aws_api_gateway_resource.lambda_resource.id http_method = aws_api_gateway_method.get_method.http_method type = "AWS_PROXY" integration_http_method = "POST" uri = aws_lambda_function.my_lambda.invoke_arn }

resource "aws_lambda_permission" "api_gateway_permission" { statement_id = "AllowAPIGatewayInvoke" 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}//" }

resource "aws_api_gateway_deployment" "api_deployment" { depends_on = [ aws_api_gateway_integration.lambda_integration ]

rest_api_id = aws_api_gateway_rest_api.my_api.id stage_name = "prod" } `

In this part:

We define an API Gateway REST API. Create a resource /hello and a GET method. Integrate the GET method with our Lambda function. Grant API Gateway permission to invoke the Lambda function. Deploy the API to a stage named prod. Step 4: Deploy Your Infrastructure Run the following commands to deploy your infrastructure:

terraform init terraform apply Confirm the apply step when prompted. Terraform will create the necessary AWS resources and output the API Gateway endpoint URL.

Testing the API

Once the deployment is complete, you can test your API by navigating to the endpoint provided by Terraform. You should see a JSON response:

{ "message": "Hello, World!" }

Conclusion

Deploying serverless applications with Terraform streamlines the process of managing infrastructure as code. By following the steps outlined in this guide, you can easily set up a serverless REST API using AWS Lambda and API Gateway. Terraform's modular and reusable nature allows you to scale and modify your infrastructure effortlessly, making it an invaluable tool in modern DevOps practices.

Happy coding!