Create and Deploy AWS Lambda with Terraform

Create and Deploy AWS Lambda with Terraform

·

7 min read

The focus of this blog post is on utilizing Terraform to manage AWS Lambda functions.

AWS Lambda

AWS Lambda is an event-driven computing service provided by Amazon Web Services that enables developers to create functions on a pay-per-use basis without having to manage storage or compute resources. This is known as Function-as-a-service (FaaS).

Lambda allows code to be executed without server management (Serverless), with payment only required for consumed compute time.

With Lambda, code can be run for various applications and backend services, with automatic scaling and high availability managed by the service. Lambda functions can be triggered automatically from other AWS services or directly called from web or mobile applications.

Terraform script to create AWS Lambda function

Here are some benefits of Deploying the Lambda function using Terraform.

Terraform allows you to define and manage your AWS infrastructure as code, which means you can use version control systems like Git to manage changes and collaborate with other team members. This approach brings consistency, repeatability, and reliability to your infrastructure deployments.

Terraform can automate the process of creating and updating Lambda functions, reducing the risk of human error and saving time. It also allows you to easily roll back changes if necessary.

Terraform can integrate Lambda functions with other AWS resources, such as API Gateway, S3, and CloudWatch, making it easier to manage the entire infrastructure in a single configuration.

Terraform ensures that your Lambda function is deployed in the same way every time, regardless of who deploys it or where it is deployed. This brings consistency to your infrastructure and reduces the risk of configuration drift.

We need to follow the below steps -

Prerequisites

Let’s start with the prerequisites for this tutorial.

  1. You should have Terraform installed on your machine.

  2. You must have an AWS account.

I am using AWS Cloud9 for this implementation. I explained more in detail about AWS Cloud9 in my previous blog.

Configure AWS Provider with Access Key Credentials

Use the CLI to create environment variables that contain your keys. First, make sure you have the Access Key and Secret Key of your AWS user. Follow this, if you don't have it.

Once you have your Access Key and Secret Key readily available, run the following commands in the Cloud9 interactive terminal:

export AWS_ACCESS_KEY_ID="<access_key>"
export AWS_SECRET_ACCESS_KEY="<secret_key>"

Create a directory structure as below.

Create Terraform variables.tf and output.tf file

Create a file named variables.tf to pass the required variables to the Terraform.

variable "aws_region" {
  default     = "us-east-1"
}

Next, create another file named output.tf file to store the output of our Terraform execution

output "lambda" {
  value = aws_lambda_function.terraform_lambda_func.qualified_arn
}

Create main.tf and add IAM Role

To begin, we'll create a file named "main.tf" and use it to define a role called "Test_Lambda_Function_Role".

resource "aws_iam_role" "lambda_role" {
name   = "Test_Lambda_Function_Role"
assume_role_policy = <<EOF
{
 "Version": "2012-10-17",
 "Statement": [
   {
     "Action": "sts:AssumeRole",
     "Principal": {
       "Service": "lambda.amazonaws.com"
     },
     "Effect": "Allow",
     "Sid": ""
   }
 ]
}
EOF
}

Add IAM Policy

This code block creates a JSON-formatted IAM Policy document.

To keep the focus of this article on managing Lambda functions with Terraform, we will maintain simplicity in our IAM Roles and Policies.

As this is a basic application, we will be assigning the following permissions:

  1. logs:CreateLogGroup

  2. logs:CreateLogStream

  3. logs:PutLogEvents

Add the following IAM Policy resource block to main.tf:

resource "aws_iam_policy" "iam_policy_for_lambda" {
  name        = "aws_iam_policy_for_terraform_aws_lambda_role"
  path        = "/"
  description = "AWS IAM Policy for managing aws lambda role"
  policy      = <<EOF
{
 "Version": "2012-10-17",
 "Statement": [
   {
     "Action": [
       "logs:CreateLogGroup",
       "logs:CreateLogStream",
       "logs:PutLogEvents"
     ],
     "Resource": "arn:aws:logs:*:*:*",
     "Effect": "Allow"
   }
 ]
}
EOF
}

Attach IAM Policy to IAM Role

Having established an IAM Policy and IAM Role for the AWS Lambda function managed by Terraform, the subsequent step is to associate the IAM Policy with the IAM Role.

resource "aws_iam_role_policy_attachment" "attach_iam_policy_to_iam_role" {
 role        = aws_iam_role.lambda_role.name
 policy_arn  = aws_iam_policy.iam_policy_for_lambda.arn
}

Write the Python Application

Now that we have produced the requisite Terraform code for generating the AWS Lambda function, the subsequent step is to create the source code file in Python and name it "hello-world.py".

  1. Create a directory python parallel to main.tf.

  2. Inside the directory python, create a file hello-world.py.

  3. Add the following Python function to it:

     def lambda_handler(event, context):
         name = event['name']
         age = event['age']
         city = event['city']
         greeting = f"Hello {name}, you are {age} years old and live in {city}!"
         return {
             'message': greeting
         }
    

    This way we will create a directory structure.

    Create a ZIP of the Python Application

    In the previous step, we generated a Python file named "hello-world.py". The subsequent step involves producing a ZIP file since the "aws_lambda_function" requires the code to be stored in a ZIP file before it can be uploaded to AWS.

    This ZIP file we are going to upload and submit this to AWS Lambda function:

     data "archive_file" "zip_the_python_code" {
     type        = "zip"
     source_dir  = "${path.module}/python/"
     output_path = "${path.module}/python/python-hello-func.zip"
     }
    

    Add aws_lambda_function Function

    We now have all the necessary components (IAM Role, IAM Policy, Python code) in position. It is time to write the resource block for the "aws_lambda_function" and add it in main.tf

     resource "aws_lambda_function" "terraform_lambda_func" {
     filename                       = "${path.module}/python/python-hello-func.zip"
     function_name                  = "Test_Lambda_Function"
     role                           = aws_iam_role.lambda_role.arn
     handler                        = "hello-world.lambda_handler"
     runtime                        = "python3.8"
     depends_on                     = [aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role]
     }
    

    Here are a few things you should keep in mind while writing aws_lambda_function resource block:

    1. Runtime: You must specify the correct runtime that AWS Lambda will use to run your function. AWS Lambda currently supports several programming languages, including Node.js, Python, Java, Ruby, Go, and .NET.

    2. IAM Role: It is important to specify the appropriate IAM role that you created for the Lambda function.

    3. Depends_on: You should specify the appropriate IAM policy attachment block that connects the IAM role to the IAM policy. This is done to ensure that the IAM policy and IAM roles are already established before generating the Lambda function, serving as a sanity check.

Run and Execute Terraform main.tf

Here is the complete main.tf file:

    provider "aws" {
      region =var.aws_region
    }
    resource "aws_iam_role" "lambda_role" {
    name   = "Test_Lambda_Function_Role"
    assume_role_policy = <<EOF
    {
     "Version": "2012-10-17",
     "Statement": [
       {
         "Action": "sts:AssumeRole",
         "Principal": {
           "Service": "lambda.amazonaws.com"
         },
         "Effect": "Allow",
         "Sid": ""
       }
     ]
    }
    EOF
    }
    resource "aws_iam_policy" "iam_policy_for_lambda" {

     name         = "aws_iam_policy_for_terraform_aws_lambda_role"
     path         = "/"
     description  = "AWS IAM Policy for managing aws lambda role"
     policy = <<EOF
    {
     "Version": "2012-10-17",
     "Statement": [
       {
         "Action": [
           "logs:CreateLogGroup",
           "logs:CreateLogStream",
           "logs:PutLogEvents"
         ],
         "Resource": "arn:aws:logs:*:*:*",
         "Effect": "Allow"
       }
     ]
    }
    EOF
    }

    resource "aws_iam_role_policy_attachment" "attach_iam_policy_to_iam_role" {
     role        = aws_iam_role.lambda_role.name
     policy_arn  = aws_iam_policy.iam_policy_for_lambda.arn
    }

    data "archive_file" "zip_the_python_code" {
    type        = "zip"
    source_dir  = "${path.module}/python/"
    output_path = "${path.module}/python/python-hello-func.zip"
    }

    resource "aws_lambda_function" "terraform_lambda_func" {
    filename                       = "${path.module}/python/python-hello-func.zip"
    function_name                  = "Test_Lambda_Function"
    role                           = aws_iam_role.lambda_role.arn
    handler                        = "index.lambda_handler"
    runtime                        = "python3.8"
    depends_on                     = [aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role]
    }

Now it is time to put our terraform script to use and create an AWS lambda function with terraform. Let’s run the following commands in sequence:

    terraform init
    terraform fmt
    terraform validate
    terraform plan
    terraform apply

Output After terraform init

Output after terraform fmt and terraform validate

Upon running terraform plan, you will notice that the python-hello-func.zip file is generated.

Output after terraform apply

After executing terraform apply , a terraform.tfstate file is generated in the directory.

Verify the Lambda Function From AWS Console

Let’s head over to AWS Console and do the test run. Click on Lambda to see the Lambda function we have provisioned using Terraform:

Click on it, then use the Test button to run the Lambda function:

A new window will open where you need to specify the event name. As you can see in the below pic name, I have assigned the event name as test1 and entered a custom message as below.

Click on Test to execute the test event

As you can see, it has returned the message "Hello Mr XYZ, you are 25 years and live in Dubai", which we have written inside the Python file.

You have successfully automated the deployment of your Python code to a lambda function using Terraform and then validated using the Lambda console.

Clean Up

To clean up and delete all of the infrastructure resources we created, run the following command:

terraform destroy

Conclusion

In conclusion, by using Terraform, you were able to automate the deployment of your Python code to an AWS Lambda function. The process involved creating the necessary IAM roles and policies, uploading the Python code as a ZIP file, and defining the AWS Lambda function resource block with the appropriate configuration. After executing the Terraform plan and Terraform apply commands, you were able to validate the deployment using the AWS Lambda console. This streamlined and automated approach to AWS Lambda function management allows for increased efficiency and scalability in the development process.

Github: https://github.com/sunitabachhav2007/Terraform-Projects.git

Thanks for reading to the end; I hope you gained some knowledge.

Thanks and keep learning.

#terraform #Devops #serverless #lambda #aws #iac #cloudcomputing #git #awscloud #hashicorp #devopscommunity #amazon #github

References :

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function

https://developer.hashicorp.com/terraform/tutorials/aws/lambda-api-gateway