How to Set Up a Serverless Home Lab with AWS CDK, Lambda, and LocalStack

Are you looking to develop and your cloud application locally without incurring AWS costs? In this tutorial, we’ll guide you through setting up a local serverless environment using AWS CDK, LocalStack, and a simple Python Lambda function. We’ll leverage the PythonFunction construct from the aws-cdk.aws-lambda-python-alpha module to streamline the process.

What is LocalStack?

LocalStack is a fully functional local AWS cloud stack that allows you to develop and test your cloud applications offline. It emulates a vast majority of AWS services, enabling you to test your applications without connecting to the real AWS cloud. This is incredibly useful for development and testing purposes, as it reduces costs and increases development speed.

Prerequisites

Before we begin, ensure you have the following installed on your machine:

Setting Up LocalStack

Install LocalStack using pip and then start it:

pip install localstack
localstack start -d

This will spin up LocalStack in the background, emulating AWS services locally.

Installing awslocal and cdklocal

To interact with LocalStack using AWS CLI commands and AWS CDK, we’ll install awslocal and cdklocal. awslocal is a thin wrapper that runs AWS CLI commands against LocalStack.

pip install awscli-local
npm install -g aws-cdk-local

Creating a Lambda Function

Let’s create a simple Lambda function that echoes back a message. We’ll also set up an API Gateway to invoke this Lambda function.

Create a new directory for your project and navigate into it:

mkdir MyProject
cd MyProject

Initialize a New AWS CDK Project

Initialize a new AWS CDK project in Python:

cdklocal init app --language python

This command sets up a basic CDK project structure with the necessary files.

Create the Lambda Function Directory

Create a directory for your Lambda function:

mkdir lambda

Write the Lambda Function

Inside the lambda directory, create a file named echo.py with the following content:

def handler(event, context):
    message = event.get('message', 'Hello from Lambda!')
    return {
        'statusCode': 200,
        'body': message
    }

This simple function returns the message provided in the event, or a default message if none is provided.

Defining the Infrastructure with AWS CDK

Now, let’s define our infrastructure using AWS CDK.

Update the CDK Stack

First, add the aws-cdk.aws-lambda-python-alpha module to your project’s requirements.txt file:

aws-cdk.aws-lambda-python-alpha

Install the required Python packages:

pip install -r requirements.txt

Creating the CDK Stack

Open MyProject.py and replace its content with the following code:

from aws_cdk import (
    Stack,
    aws_lambda as _lambda,
    aws_lambda_python_alpha as lambda_python,
    aws_apigateway as apigateway,
)
from constructs import Construct

class MyProjectStack(Stack):

    def __init__(self, scope: Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        echo_lambda = lambda_python.PythonFunction(
            self, 'EchoFunction',
            entry='lambda',
            index='echo.py', 
            handler='handler',
            runtime=_lambda.Runtime.PYTHON_3_8,
        )

        # Define the API Gateway REST API
        api = apigateway.LambdaRestApi(
            self, 'EchoApi',
            handler=echo_lambda,
            proxy=True
        )

Before deploying, bootstrap your CDK environment in LocalStack:

cdklocal bootstrap

Deploying to LocalStack Using CDK

Now, let’s deploy our stack to LocalStack.

Install CDK Dependencies

pip install -r requirements.txt

Synthesize the CloudFormation Template

cdklocal synth

This command synthesizes your CDK app into a CloudFormation template, which is then used for deployment.

Deploy the Stack

cdklocal deploy

The CDK will summarize the changes to your stack and you can press y to confirm the changes.

Once deployed, you’ll receive an endpoint URL for your API Gateway. You can test the Lambda function by sending a request to this URL.

After deployment, note the API endpoint URL from the output. It should look something like:

https://<api-id>.execute-api.localhost.localstack.cloud:4566/prod/

Test the API

Use curl to send a POST request to the API endpoint:

curl -X POST 'http://localhost:4566/restapis/<api-id>/prod/_user_request_' -d '{"message": "Hello, LocalStack!"}'

Replace <api-id> with the actual API ID from your deployment output.

Expected Response

You should receive a response similar to:

{
  "statusCode": 200,
  "body": "Hello, LocalStack!"
}

Thoughts

You’ve successfully set up a local serverless environment using AWS CDK and LocalStack. Using LocalStack and AWS CDK together, you can run most AWS services through LocalStack so that you can build and test your entire system locally. We’ve set up a simple lambda and an api gateway, but this project could be extended to include local versions of services like DynamoDB, Cognito and SQS with only a bit more code.

Related Posts

Learning about Distributed Inference with DeepSpeed ZeRO-3 and Docker Compose

Today, we’re going to test out DeepSpeed ZeRO-3 in docker-compose. Perhaps in a future blog post, I’ll cover DeepSpeed-FastGen or how to deploy this on a real multi-node/multi-gpu cluster. I also aim to compare this method vs Multi-Node Inference with vLLM. If you’re setting up a local cluster, consider checking out high bandwidth networking with InfiniBand. It’s surprisingly affordable.

Read More