AWS: Lambda functions — an overview, and integration with AWS API Gateway
AWS Lambda functions overview - its features, create and update a function. AWS Lambda and AWS API Gateway integration
AWS Lambda allows running a code without the need to create and manage servers, also known as the serverless approach.
AWS Lambda will determine how much CPU and memory is needed to run a function, and when it’s necessary it will perform autoscaling.
A code to be running is organized in lambda functions and can be triggered with triggers. Results can be checked using CloudWatch Logs.
As a trigger, you can use almost any AWS service such as API Gateway, SQS, Application LoadBalancer, CloudFront, Kinesis, or an external event, for example, a webhook from GitHub.
In this post, we will create a simple AWS Lambda function, will check its control panel, available options, and features, and then will create an AWS API Gateway which will forward HTTP requests to an AWS Lambda function.
AWS Lambda — use cases
In general, Lambda in AWS can do really a lot of things. Such a “silver bullet”, allows us to do things that are not realized by the AWS Console itself.
Example use cases could be:
a website: a javascript-based frontend in AWS S3 with Static hosting, the frontend will receive requests via an AWS API Gateway to a database via a Lambda function
log analysis: a good example is AWS WAF Security Automations when all incoming HTTP requests are sent to the AWS Kinesis, it will forward them to the Lambda, it will perform some checks, and if needed will block a client’s IP
backups automation: AWS SNS can send an event, for example when too much disk space is used in an AWS S3 bucket, to a Lambda function, that will delete some old backups
data processing: for example, when a new file is uploaded to an AWS S3, it will generate an event that will trigger a Lambda function that will perform a video file encoding
serverless cronjobs: with CloudWatch Events generate an event by a schedule, that will trigger a Lambda function
Components and concepts
Let’s take a short overview of the AWS Lambda main concepts:
function: is a code to run in a function. Can be as a zip file or a Docker image (deployment package). See Configuring AWS Lambda functions.
trigger: an AWS resource that will trigger a function. Such an event includes an AWS service and event mapping. See Invoking AWS Lambda functions и Using AWS Lambda with other services.
event: a JSON object that contains data for a Lambda function for processing
execution environment: secured environment to execute a function. See AWS Lambda execution environment.
deployment package: a Lambda function code to be running. Can be as a zip archive or a Docker image. See Lambda deployment packages.
runtime: a working environment to run a function. See Lambda runtimes
layer: a zip archive with additional code to run a function, for example — an external library. See Creating and sharing Lambda layers.
extensions: AWS Lambda allows to use of extensions that can be used to integrate a function with external services such as monitoring. See Using Lambda Extensions.
concurrency: a number of Lambda function instances to be running at the same time to process incoming data. See Managing concurrency for a Lambda function.
qualifier: a “pointer” to a version or an alias. See Lambda function versions.
destination: an AWS resource where a function will send processed data. See Configuring destinations for asynchronous invocation.
Creating a “Hello, World” Lambda function
First, let’s create the simplest Lambda function to see how it’s working and what we have there.
Create a function
Go to the AWS Lambda, and click on the Create function:
For now, let’s use an existing template. Choose the Use a blueprint, find a hello-world-python:
Click on the Configure:
Set a function’s name, for example, example-hello, and leave a default IAM role — it will allow our function to use CloudWatch Logs, and check the code that will be used:
Click on the Create function:
Switch to the Test tab:
Here, we can pass a JSON with data to be processed by our function.
Run it:
Now, let’s go to see what AWS Console suggests to use for Lambda function management.
Monitoring
The first thing is monitoring. Here we can use AWS CloudWatch metrics and logs, calls tracing with AWS X-Ray, Lambda insights, and AWS CodeGuru:
Configuration
General configuration
memory settings: a maximum RAM allowed to be used when running a function. Also, depending on the memory settings, Lambda will provide a CPU limit: for every 1769 MB, one vCPU will be. See Configuring function memory (console).
execution timeouts: maximum can be set to 900 seconds, after that, a function execution will be stopped. Remember, that this will affect costs. See Timeout.
IAM role: includes IAM policies with permissions to AWS resources
Triggers
Well, triggers that will trigger our function.
Can be almost any AWS service:
For example, we can create a trigger from an AWS Application LoadBalancer that will accept connections to a specific URI and will forward it to a Lambda function:
Permissions
Here, you can view and adjust an IAM role and policies that will configure a function’s permissions:
Destinations
Where to send a function’s execution results.
For example, can be an AWS SNS topic that will forward to Opsgenie which will send a message to a Slack channel:
Environment variables
Variables that can be used in our function. Sensitive data can be encrypted with AWS Key Management Service (KMS):
VPC
A function can be placed to a dedicated AWS Virtual Private Cloud to limit its network access:
Monitoring and operations tools
Monitoring settings, where you can enable or disable additional services such as AWS X-Ray, CloudWatch Lambda Insights, and Amazon CodeGuru Profiler:
In the Extentions, you can choose from a list of already existing solutions or create your own:
Concurrency
A maximum number of a function’s instances that can be run simultaneously. See Managing concurrency for a Lambda function.
Can be one of two types:
reserved concurrency: reserve a number from the generally available for the whole account (1000 by default) and is applied to the whole function including all its versions and aliases
provisioned concurrency: will prepare an already initialized runtime environment so during scaling your function will not have to wait for it, applies to a specific version or an alias
Asynchronous invocation
Settings for the event queue — lifetime, number of retries in case of errors, error notifications, etc.
See also Synchronous invocation and Asynchronous invocation.
Database proxies
An Amazon RDS Proxy configuration to be used with your function. RDS Proxy used to decrease the number of connections to a database server:
File system
You can mount an AWS Elastic File System directory inside your function:
Aliases
An alias is a kind of pointer to a specific version of your function’s code that can be used in its ARN later.
Also, you can have a couple of aliases and distribute requests between them. See Lambda function aliases:
Versions
AWS Lambda allows using a code and part of settings versioning. Can be useful when testing a new code on a Dev environment, for example by creating a dedicated alias:
AWS Lambda, and AWS API Gateway — an integration example
So, we’ve checked what AWS Lambda is and what it has in its settings.
Now, let’s create an AWS API Gateway that will forward requests to an AWS Lambda function.
API Gateway will accept requests to the /test URI and will use its event to send them to our Lambda.
Create a Lambda function
At this time, choose Author from scratch, in the Runtime use Python:
Leave the default code:
Here, the lambda_handler()
is a default function to be called when a function is called. It accepts two arguments:
event
: an API Gateway event, see Using AWS Lambda with other servicescontext
: allowed methods and parameters to run a function, see AWS Lambda context object in Python
Create an AWS API Gateway
Create a new gateway, and set its type to the HTTP API:
Add an integration:
Choose Lambda, an AWS Region, and a function to be called:
Set the URI as /test:
Leave the default stage:
In less than a minute your Gateway is ready. Copy its URL:
And try with the curl
:
$ curl [https://fwu399qo70.execute-api.us-east-2.amazonaws.com/test](https://fwu399qo70.execute-api.us-east-2.amazonaws.com/test)
“Hello from Lambda!”
To check the full content of the event, print it with the json.dumps()
:
import json
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': json.dumps(event)
}
After making code changes, click Deploy:
Try it:
$ curl [https://fwu399qo70.execute-api.us-east-2.amazonaws.com/test](https://fwu399qo70.execute-api.us-east-2.amazonaws.com/test)
{“version”: “2.0”, “routeKey”: “ANY /test”, “rawPath”: “/test”, “rawQueryString”: “”, “headers”: {“accept”: “*/*”, “content-length”: “0”, “host”: “fwu399qo70.execute-api.us-east-2.amazonaws.com”, “user-agent”: “curl/7.78.0”, “x-amzn-trace-id”: “Root=1–611bbaa4–3cb7c28e4e3181dd647f1030”, “x-forwarded-for”: “194. ***.***.29”, “x-forwarded-port”: “443”, “x-forwarded-proto”: “https”}, “requestContext”: {“accountId”: “534 ***385”, “apiId”: “fwu399qo70”, “domainName”: “fwu399qo70.execute-api.us-east-2.amazonaws.com”, “domainPrefix”: “fwu399qo70”, “http”: {“method”: “GET”, “path”: “/test”, “protocol”: “HTTP/1.1”, “sourceIp”: “194.***.***.29”, “userAgent”: “curl/7.78.0”}, “requestId”: “ENoZriIrCYcEPWg=”, “routeKey”: “ANY /test”, “stage”: “$default”, “time”: “17/Aug/2021:13:33:24 +0000”, “timeEpoch”: 1629207204179}, “isBase64Encoded”: false}
Now, let’s see how we can use environment variables in the function.
Add a new one:
And print its value with the os.getenv()
:
import os
import json
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': os.getenv('Env')
}
Check it:
$ curl [https://fwu399qo70.execute-api.us-east-2.amazonaws.com/test](https://fwu399qo70.execute-api.us-east-2.amazonaws.com/test)
test
Also, you can change the default handler.
Rename the lambda_handler
to the main_handler
:
import os
import json
def main_handler(event, context):
return {
'statusCode': 200,
'body': os.getenv('Env')
}
If you’ll try to access the function now, you’ll get the Internal Server Error :
$ curl [https://fwu399qo70.execute-api.us-east-2.amazonaws.com/test](https://fwu399qo70.execute-api.us-east-2.amazonaws.com/test)
{“message”:”Internal Server Error”}
Scroll down to the Runtime settings:
And change the Handler:
Run it again:
$ curl [https://fwu399qo70.execute-api.us-east-2.amazonaws.com/test](https://fwu399qo70.execute-api.us-east-2.amazonaws.com/test)
test
Done.
Originally published at RTFM: Linux, DevOps, and system administration.