Terraform: Create And Deploy AWS Lambda

July 8, 2022

Introduction

This article will cover creating and deploying an AWS Lambda function using Terraform.

Terraform IaC code allows the deployment of infrastructure to AWS cloud without using AWS CloudFormation. You can access this article's FREE template for download HERE.

What is Terraform?

Terraform is HashiCorp's infrastructure as a code tool. It lets you define resources and infrastructure in human-readable, declarative configuration files, and manages your infrastructure's lifecycle. Using Terraform has several advantages over manually managing your infrastructure:

  • Terraform can manage infrastructure on multiple cloud platforms.
  • The human-readable configuration language helps you write infrastructure code quickly.
  • Terraform's state allows you to track resource changes throughout your deployments.
  • You can commit your configurations to version control to safely collaborate on infrastructure.
Source

To deploy infrastructure with Terraform:

  • Scope - Identify the infrastructure for your project.
  • Author - Write the configuration for your infrastructure.
  • Initialize - Install the plugins Terraform needs to manage the infrastructure.
  • Plan - Preview the changes Terraform will make to match your configuration.
  • Apply - Make the planned changes.

Prerequisites

  • An AWS Account
  • AWS CLI Configured
  • NodeJs

Installing The Terraform

Windows: choco install terraform

Linux: ****sudo apt-get install terraform

Mac OS: brew install hashicorp/tap/terraform

Let’s Start - Create an Empty Project Folder

  
mkdir sg-terraform-lambda-deploy
cd sg-terraform-lambda-deploy
  

Create And Upload The Lambda Function Archive

Create File sg-demo/demo.js with below lambda function code

  • Lambda Function Code with NodeJs
  
module.exports.handler = async (event) => {
  console.log('Event: ', event);
  let responseMessage = 'SG Terraform Lambda Deployed!';

  return {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      message: responseMessage,
    }),
  }
}
  

Create File main.tf with Below Terraform IaC Code Configuration which will define:

  • Initialize Providers Plugins
  • Provider AWS
  • S3 bucket
  • S3 Object For Lambda Function Code Archive
  
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.1.0"
    }
    archive = {
      source  = "hashicorp/archive"
      version = "~> 2.2.0"
    }
  }

  required_version = ">= 1.2.0"
}

provider "aws" {
  region = var.aws_region
}

resource "random_pet" "lambda_bucket_name" {
  prefix = "sg-terraform-demo"
  length = 4
}

resource "aws_s3_bucket" "lambda_bucket" {
  bucket = random_pet.lambda_bucket_name.id  
  force_destroy = true
}

resource "aws_s3_bucket_acl" "lambda_bucket_acl" {
  bucket = aws_s3_bucket.lambda_bucket.id
  acl    = "private"
}

data "archive_file" "lambda_sg_demo" {
  type = "zip"

  source_dir  = "${path.module}/sg-demo"
  output_path = "${path.module}/sg-demo.zip"
}

resource "aws_s3_object" "lambda_sg_demo" {
  bucket = aws_s3_bucket.lambda_bucket.id

  key    = "sg-demo.zip"
  source = data.archive_file.lambda_sg_demo.output_path

  etag = filemd5(data.archive_file.lambda_sg_demo.output_path)
}
  

Create The Lambda Function And Relevant Resource

Add below Terraform IaC code configuration to main.tf file which will define:

  • Lambda Function
  • Lambda CloudWatch Log Group
  • Lambda Execution IAM Role
  • Lambda Execution IAM Role Policy
  
resource "aws_lambda_function" "sg_demo" {
  function_name = "SGDemo"

  s3_bucket = aws_s3_bucket.lambda_bucket.id
  s3_key    = aws_s3_object.lambda_sg_demo.key

  runtime = "nodejs12.x"
  handler = "demo.handler"

  source_code_hash = data.archive_file.lambda_sg_demo.output_base64sha256

  role = aws_iam_role.lambda_exec.arn
}

resource "aws_cloudwatch_log_group" "sg_demo" {
  name = "/aws/lambda/${aws_lambda_function.sg_demo.function_name}"

  retention_in_days = 30
}

resource "aws_iam_role" "lambda_exec" {
  name = "serverless_lambda"

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

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

Create An Output Value For Your Lambda Function's Name

Create file outputs.tf with the below IaC code configuration

Defined Output values are displayed in CLI during executing Terraform commands like apply.

  
# Output value definitions

output "lambda_bucket_name" {
  description = "Name of the S3 bucket used to store function code."

  value = aws_s3_bucket.lambda_bucket.id
}

output "function_name" {
  description = "Name of the Lambda function."

  value = aws_lambda_function.sg_demo.function_name
}
  

Define Needful Variables

Create file variables.tf with the below IaC code configuration

These defined variables are used within the main.tf file using var.aws_region:

  
# Input variable definitions

variable "aws_region" {
  description = "AWS region for all resources."

  type    = string
  default = "ap-south-1"
}
  

Project Folder Structure At The End

After following the above steps, at the end you will have the below folder structure created:

Project Terraform Initialization

Terraform init prepares the working directory so Terraform can run the configuration.

  
D:\slsguru\Demo-projects>terraform init

Initializing the backend...

Initializing provider plugins...
- Installing hashicorp/archive v2.2.0...
- Installed hashicorp/archive v2.2.0 (signed by HashiCorp)
- Installing hashicorp/aws v4.18.0...
- Installed hashicorp/aws v4.18.0 (signed by HashiCorp)
- Installing hashicorp/random v3.1.3...
- Installed hashicorp/random v3.1.3 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!
  

Terraform downloads the AWS provider and installs it in a hidden subdirectory of your current working directory, named .terraform. The terraform init command prints out which version of the provider was installed. Along with that it also installs other specified plugins like archive, and random.

Terraform also creates a lock file named .terraform.lock.hcl which specifies the exact provider versions used, so that you can control when you want to update the providers used for your project.

Terraform Plan

Terraform plan lets you preview any changes before you apply them.

Terraform Apply

Terraform apply executes the changes defined by your Terraform configuration to create, update, or destroy resources.

Apply the configuration now with the terraform apply command, which will create infrastructure in a specified cloud provider with defined resources.

  
D:\slsguru\Demo-projects>terraform apply
## ...

Apply complete! Resources: 8 added, 0 changed, 0 destroyed.

Outputs:

function_name = "SGDemo"
lambda_bucket_name = "sg-terraform-demo-slightly-strongly-immense-wahoo"
  

Before it applies any changes, Terraform prints out the execution plan which describes the actions Terraform will take in order to change your infrastructure to match the configuration.

Terraform will now pause and wait for your approval before proceeding, In this case, the plan is acceptable, so type yes at the confirmation prompt to proceed. After executing the plan it will take a few minutes for your Lambda and relevant resources to get successfully deployed to AWS. Apply command response in CLI show number of resources deployed with outputs items.

That’s It!!! Demo Lambda Successfully Deployed To AWS Using Terraform :)

AWS S3 Bucket And Relevant Objects Created

AWS Lambda Function Deployed

Lambda Function Execution Role Created With Needful Permission

CloudWatch Logs Group Created For Lambda Function

Terraform Destroy

  
D:\slsguru\Demo-projects\sg-terraform-lambda-deploy>terraform destroy
## ...
Terraform used the selected providers to generate the following execution plan. 
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:
  # aws_cloudwatch_log_group.sg_demo will be destroyed
  # aws_iam_role.lambda_exec will be destroyed
  # aws_iam_role_policy_attachment.lambda_policy will be destroyed
  # aws_lambda_function.sg_demo will be destroyed
  # aws_s3_bucket.lambda_bucket will be destroyed
  # aws_s3_bucket_acl.lambda_bucket_acl will be destroyed
  # aws_s3_object.lambda_sg_demo will be destroyed
  # random_pet.lambda_bucket_name will be destroyed

Plan: 0 to add, 0 to change, 8 to destroy.

Changes to Outputs:
  - function_name      = "SGDemo" -> null
  - lambda_bucket_name = "sg-terraform-demo-slightly-strongly-immense-wahoo" -> null

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

## ...
Destroy complete! Resources: 8 destroyed.
  

The terraform destroy command terminates resources managed by your Terraform project. This command is the inverse of terraform apply in that it terminates all the resources specified in your Terraform state. It does not destroy resources running elsewhere that are not managed by the current Terraform project.

That’s All Done!!! Now you are ready to get started with the basics of Terraform.

Conclusion

Terraform infrastructure as code allows you to easily create and deploy resources to multiple cloud providers including AWS.

By following this article you will get a basic idea about Terraform CLI commands, Infrastructure as Code configurations, and the basics of deploying the AWS Lambda function that helps you to get started on Terraform.

To explore more about Terraform see these official getting started Terraform documents.

Sources

  1. https://learn.hashicorp.com/tutorials/terraform/infrastructure-as-code?in=terraform/aws-get-started
  2. https://learn.hashicorp.com/collections/terraform/aws-get-started
Serverless Handbook
Access free book

The dream team

At Serverless Guru, we're a collective of proactive solution finders. We prioritize genuineness, forward-thinking vision, and above all, we commit to diligently serving our members each and every day.

See open positions

Looking for skilled architects & developers?

Join businesses around the globe that trust our services. Let's start your serverless journey. Get in touch today!
Ryan Jones - Founder
Ryan Jones
Founder
Speak to a Guru
arrow
Edu Marcos
Chief Technology Officer
Speak to a Guru
arrow
Mason Toberny
Mason Toberny
Head of Enterprise Accounts
Speak to a Guru
arrow

Join the Community

Gather, share, and learn about AWS and serverless with enthusiasts worldwide in our open and free community.