What is AWS Lambda?
AWS Lambda is a serverless computing service provided by Amazon Web Services (AWS) AWS Lambda lets you run code without provisioning or managing servers.
How does this work?
You may think, how you make your code work without provisioning a server. Well, you write Lambda functions in one of the languages and runtime supported by AWS lambda. Your code is uploaded to AWS lambda which runs your code only when needed and scales automatically. Not having to provision or manage a server and still having your code run is what makes this a part of the Serverless architecture.
Are there no servers involved?
No, the concept of serverless means not needed to maintain your own server. AWS Lambda service takes care of the servers, the operating systems, the network layer and the rest of the infrastructure, so you just need to focus on writing application code.
What does "run your code only when needed" mean?
Your lambda function runs the code when it is triggered by an event. Some common ways to trigger your lambda function are :
- API Gateway
- S3
- DynamoDB Table Streams
Let's code
The best way to learn is to implement.
What are we building?
We are going to make a simple lambda function in golang. Every developer's favourite: Hello world :)
Pre-Requisites
- Basic knowledge of golang
- Basic understanding of handlers
Project setup
From the local machine, create a directory named aws-lambda and change the directory to it.
mkdir aws-lambda-go && cd aws-lambda-go
Initialize the Go project with a module file.
go mod init
The next part in writing the code in main.go
func hello() (events.APIGatewayProxyResponse, error) {
body := "Hello World"
return events.APIGatewayProxyResponse{
StatusCode: 200,
Body: body,
}, nil
}
We have created a handler named hello which returns "Hello World".
One thing to note is, this handler returns events.APIGatewayProxyResponse
This is because we will be using AWS API Gateway to trigger our lambda and AWS API Gateway expects a response in the mentioned format.
It contains our StatusCode which will be 200 for the successful response and our Body which is the "Hello World"
string.
To add the dependencies use the following commands:
go get github.com/aws/aws-lambda-go/lambda
go get github.com/aws/aws-lambda-go/events
Our main function calls the handler with Lambda.Start function. Here is how are main.go looks:
package main
import (
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func hello() (events.APIGatewayProxyResponse, error) {
body := "Hello World"
return events.APIGatewayProxyResponse{
StatusCode: 200,
Body: body,
}, nil
}
func main() {
lambda.Start(hello)
}
Creating the executable file and zip file
Use the following command to build your executable file
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-s -w" -o bootstrap cmd/main.go
Now zip the executable file
zip -9 -j bootstrap.zip bootstrap
The next section covers how we deploy our lambda function.
Serverless Framework
The Serverless Framework is a command-line tool that uses YAML syntax to deploy both your code and cloud infrastructure needed. It supports Node.js, Typescript, Python, Go, Java, and more.
Advantages of serverless framework
- Cost: You pay only for what you use. There is no need to reserve extra space for your services.
- Flexibility: Instances are automatically scaled.
- Accuracy and Speed: Developers can simply deploy their code without having to manage any servers, which helps accelerate delivery cycles and rapidly scale company operations.
Challenges of serverless framework
- Loss of Control: You’re dependent on a cloud provider for functioning of servers
- Security: If the shared server isn’t configured properly, your application data could be exposed.
- Testing: Developers can run unit tests on function code, but integration tests, which evaluate how frontend and backend components interact, are difficult to perform in a serverless environment.
- Performance Impact: Cold starts are common in serverless environments, adding several seconds of latency to code execution when functions are invoked after a period of inactivity.
- Complexity: If something isn't working as it should, spotting the issue could be difficult. You'll have multiple spaces in which to look.
Serverless Architecture Use Cases
Trigger-based tasks: Trigger-based or event-driven tasks are commonly used with serverless framework.
Building RESTful APIs You can build RESTful APIs using Amazon API Gateway with serverless functions with high scalability.
Security checks When you spin up a new container, a function can be invoked to scan the instance for misconfigurations or vulnerabilities. Functions can also be used as a more secure option for SSH verification and two-factor authentication.
Continuous Integration (CI) and Continuous Delivery (CD) Serverless architectures can automate many of the stages in your CI/CD pipelines. For example, code commits can trigger a function to create a build, and pull requests can trigger automated tests.
Install serverless
Set up a new npm package with the following command:
npm init
You will see the following, enter the details as per your wish.
Install the serverless CLI via NPM:
npm install -g serverless
Getting started with serverless
The following command will guide you to create a new serverless project
serverless
Moving ahead we will be using the alias "sls" for the serverless commands
Configure your aws credentials
sls config credentials --provider aws --key <aws access key> --secret <aws secret key>
( You need to create an AWS IAM user and access key first if you don't have one already )
The serverless YAML file
service: aws-lambda-1
provider:
name: aws
runtime: go1.x
region: ap-south-1
functions:
blogExample:
handler: bootstrap
events:
- http:
method: get
path: blogExample
cors:
origin: "*"
headers: "*"
package:
individually: true
artifact: bootstrap.zip
Let us understand the yaml file
- Declare the name of your service
service: aws-lambda-1
- Configure the provider you are using : Here we are using aws with runtime go1.x as we have written our code in Go.
provider:
name: aws
runtime: go1.x
region: ap-south-1
- Declare the functions : We have named our function "blogExample", the handler is the executable file which will run your code when this function is invoked.
functions:
blogExample:
handler: bootstrap
Events is what can trigger our function. We will be using an http event, The path to our function will be blogExample. Configure the cors settings.
events: -http: method: get path: blogExample cors: origin: "*" headers: "*"
Configuration for your package, here we have a zip file named bootstrap.zip which we will be uploading to our lambda function. The individually ture property enables you to package your functions individually.
package:
individually: true
artifact: bootstrap.zip
- We named our file bootstrap because if there's a file named bootstrap in your deployment package, Lambda runs that file. If not, Lambda looks for a runtime in the function's layers. If the bootstrap file isn't found or isn't executable, your function returns an error upon invocation. So, using bootstrap file is a safe and general practice.
Deploy your service
sls deploy
- You should see the following output with your function url:
- You can see your function on the AWS Lambda dashboard
We have successfully deployed our lambda function, the serverless deploy takes care creating the required AWS stack.
Hope this blog was helpful in understanding AWS Lambda and the serverless framework.