Skip to content

Latest commit

 

History

History
281 lines (232 loc) · 15.2 KB

File metadata and controls

281 lines (232 loc) · 15.2 KB

AWS Lambda on Graviton2

AWS Lambda now allows you to configure new and existing functions to run on Arm-based AWS Graviton2 processors in addition to x86-based functions. Using this processor architecture option allows you to get up to 34% better price performance. Duration charges, billed with millisecond granularity, are 20 percent lower when compared to current x86 pricing. This also applies to duration charges when using Provisioned Concurrency. Compute Savings Plans supports Lambda functions powered by Graviton2.

The blog post Migrating AWS Lambda functions to Arm-based AWS Graviton2 processors shows some considerations when moving from x86 to arm64 as the migration process is code and workload dependent.

This page highlights some of the migration considerations and also provides some simple to deploy demos you can use to explore how to build and migrate to Lambda functions using Arm/Graviton2.

The architecture change does not affect the way your functions are invoked or how they communicate their responses back. Integrations with APIs, services, applications, or tools are not affected by the new architecture and continue to work as before. The following runtimes, which use Amazon Linux 2, are supported on Arm:

  • Node.js 12 and above
  • Python 3.8 and above
  • Java 8 (java8.al2) and above
  • .NET Core 3.1 and above
  • Ruby 2.7 and above
  • Custom runtime (provided.al2) and above

Migrating x86 Lambda functions to arm64

Functions without architecture-specific dependencies or binaries

Many Lambda functions may only need a configuration change to take advantage of the price/performance of Graviton2. Other functions may require repackaging the Lambda function using Arm-specific dependencies, or rebuilding the function binary or container image.

If your functions don’t use architecture-specific dependencies or binaries, you can switch from one architecture to the other with a single configuration change. Many functions using interpreted languages such as Node.js and Python, or functions compiled to Java bytecode, can switch without any changes. Ensure you check binaries in dependencies, Lambda layers, and Lambda extensions.

Building function code for Graviton2

For compiled languages like Rust and Go, you can use the provided.al2 or provided.al2023 custom runtimes, which supports Arm. You provide a binary that communicates with the Lambda Runtime API.

When compiling for Go, set GOARCH to arm64.

GOOS=linux GOARCH=arm64 go build

When compiling for Rust, set the target.

cargo build --release -- target-cpu=neoverse-n1

The default installation of Python pip on some Linux distributions is out of date (<19.3). To install binary wheel packages released for Graviton, upgrade the pip installation using:

sudo python3 -m pip install --upgrade pip

Functions packaged as container images must be built for the architecture (x86 or arm64) they are going to use. There are arm64 architecture versions of the AWS provided base images for Lambda. To specify a container image for arm64, use the arm64 specific image tag, for example, for Node.js 20:

public.ecr.aws/lambda/nodejs:20-arm64
public.ecr.aws/lambda/nodejs:latest-arm64
public.ecr.aws/lambda/nodejs:20.2024.01.05.14-arm64

Arm64 images are also available from Docker Hub. You can also use arbitrary Linux base images in addition to the AWS provided Amazon Linux 2 images. Images that support arm64 include Alpine Linux 3.12.7 or later, Debian 10 and 11, Ubuntu 18.04 and 20.04. For more information and details of other supported Linux versions, see Operating systems available for Graviton based instances.

The AWS Lambda Power Tuning open-source project runs your functions using different settings to suggest a configuration to minimize costs and maximize performance. The tool allows you to compare two results on the same chart and incorporate arm64-based pricing. This is useful to compare two versions of the same function, one using x86 and the other arm64.

DEMO: Building Lambda functions for Graviton2

Demo requirements:

Clone the repository and change into the demo directory

git clone https://github.com/aws/aws-graviton-getting-started
cd aws-graviton-getting-started/aws-lambda/GravitonLambdaNumber

Migrating a Lambda function from x86 to arm64

This demo shows how to migrate an existing Lambda function from x86 to arm64 using an x86 based workstation. The Node.js function code in /src/app.js uses the axios client to connect to a third part service, http://numbersapi.com/, to find interesting facts about numbers. As the axios library is not a binary file, it can seamlessly work on Graviton2 without compilation.

The existing application consists of an API endpoint which invokes the Lambda function, retrieves the number fact, and returns the response.

Build the existing x86 function version using AWS SAM.

sam build

sam build

Deploy the function to your AWS account:

sam deploy --stack-name GravitonLambdaNumber -g

Accept the initial defaults, and ensure you enter Y for LambdaNumberFunction may not have authorization defined, Is this okay? [y/N]: y

sam deploy -g

AWS SAM deploys the infrastructure and outputs an APIBasePath

ApiBasePath

Use curl and make a POST request to the APIBasePath URL with a number as a date.

curl -X POST https://6ioqy4z9ee.execute-api.us-east-1.amazonaws.com -H 'Content-Type: application/json' -d '{ "number": "345", "type": "date" }'

The Lambda function should respond with the x64 processor architecture and a fact about the date.

curl x86

Amend the processor architecture within the AWS SAM template.yml file. replace

Architectures:
- x86_64

with

Architectures:
- arm64

Build the function using an arm64 architecture and deploy the change to the cloud.

sam build
sam deploy

Use the same curl command, making a POST request to the APIBasePath URL with a number as a date.

curl -X POST https://6ioqy4z9ee.execute-api.us-east-1.amazonaws.com -H 'Content-Type: application/json' -d '{ "number": "345", "type": "date" }'

The Lambda function should respond with the arm64 processor architecture and a fact about the date.

curl arm64

The function has seamlessly migrated from x86 to arm64.

Building a Lambda function with binary dependencies

This function has no binary dependencies. If you do have a function that required compilation for arm64, AWS SAM can use an arm64 build container image to create the artifacts for arm64. This functionality works both ways. You can build arm64 specific dependencies on an x86 workstation and also build x86 specific dependencies on an arm64 workstation.

Specify --use-container to use the build container.

sam build --use-container

sam build --use-container

Local testing

You can test the arm64 function locally using either AWS SAM or Docker natively.

When using AWS SAM, you can use sam local invoke to test your function locally, passing in a sample event.json

sam local invoke LambdaNumberFunction -e ./test/event.json

sam local invoke

Building arm64 Lambda functions as container images

You can build arm64 functions as container images. You can use AWS SAM natively to build container images.

You can also use Docker native commands instead of AWS SAM. To build a container image of this function using Docker, use the Dockerfile and specify the nodejs:20-arm64 base image.

FROM public.ecr.aws/lambda/nodejs:20-arm64
COPY app.js package*.json $LAMBDA_TASK_ROOT
RUN npm install
CMD [ "app.lambdaHandler" ]

Build the container image.

docker build -t dockernumber-arm ./src 

docker build

Inspect the container image to confirm the Architecture.

docker inspect dockernumber-arm | grep Architecture 

docker inspect

You can locally test the function using docker run In another terminal window run the Lambda function docker container image.

docker run -p 9000:8080 dockernumber-arm:latest

docker run

Use curl to invoke the Lambda function using the local docker endpoint, passing in a sample event.json.

curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d @./test/event.json

docker run response

You can view the local logs in the docker run terminal window.

To create a Lambda function from the local image, first create an [Amazon Elastic Container Registry (ECR)]](https://aws.amazon.com/ecr/) repository and login to ECR. Substitute the AWS account number 123456789012 and AWS Region values with your details

aws ecr create-repository --repository-name dockernumber-arm --image-scanning-configuration scanOnPush=true
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com

Tag and push the docker image to ECR.

docker tag dockernumber-arm:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/dockernumber-arm:latest
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/dockernumber-arm:latest

You can then create a Lambda function from the container image using the AWS Management Console, AWS CLI, or other tools. Create function from image

Comparing x86 and arm64 performance and cost.

You can use the AWS Lambda Power Tuning open-source project to suggest a configuration to minimize costs and maximize performance. The tool allows you to compare two results on the same chart and incorporate arm64-based pricing. This is useful to compare two versions of the same function, one using x86 and the other arm64.

A demo application computes prime numbers. The AWS SAM template.yml file contains two Lambda functions, one for x86 and one for arm64. Both functions use the same Python source code in ./src/app.py to compute the prime numbers.

Ensure the repository is cloned from the previous demo and change into the directory.

cd ../PythonPrime

Build the application within the AWS SAM build container images and deploy to the cloud. Accept the default sam deploy prompts.

sam build --use-container
sam deploy --stack-name PythonPrime -g

Note the Output values of the two Lambda functions: Prime Functions

Deploy the AWS Lambda Power Tuning State Machine

Navigate to https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:451282441545:applications~aws-lambda-power-tuning and choose Deploy. Select I acknowledge that this app creates custom IAM roles and choose Deploy.

Once deployed, under Resources, choose the powerTuningStateMachine.

Choose Start execution For the state machine input, specify the ARN of the x86 Lambda function from the AWS SAM Outputs, and set the memory powerValues to check. Run 10 invocations for each memory configuration, in parallel, specifying the Lambda function payload. The following is an example input.

{
	"lambdaARN": "arn:aws:lambda:us-east-1:123456789012:function:gravitonpythonprime-PythonPrimeX86Function-3Gge9WXmHObZ",
	"powerValues": [
		128,
		256,
		512,
		1024,
		1536,
		2048,
		3008,
		10240
	],
	"num": 10,
	"parallelInvocation": true,
	"payload": {
		"queryStringParameters": {
			"max": "1000000"
		}
	}
}

Select Open in a new browser tab and choose Start execution. The Lambda Power Tuning state machine runs for each configured memory value. PowerTuningStateMachine

Once complete, the Execution event history final step, ExecutionSucceeded contains a visualization URL.

{
  "output": {
    "power": 512,
    "cost": 0.000050971200000000004,
    "duration": 6067.418333333332,
    "stateMachine": {
      "executionCost": 0.00035,
      "lambdaCost": 0.007068295500000001,
      "visualization": "https://lambda-power-tuning.show/#gAAAAQACAAQABgAIwAsAKA==;5njERiCGREZZm71F9rxARW12AkU66d5EDqzeRLFs30Q=;a4NdODSTXTjpyVU42k9ZOLixXDipans4V224ONx8nTk="
    }
  },
  "outputDetails": {
    "truncated": false
  }
}

Browse to the lambda-power-tuning URL to view the average Invocation time (ms) and Invocation Cost (USD) for each memory value for the x86 function.

PowerTuning x86 results

Navigate back to the Step Functions console and run another state machine, specifying the ARN of the arm64 Lambda function from the AWS SAM Outputs. Once complete, copy the visualization URL from the Execution event history final step, ExecutionSucceeded.

In the lambda-power-tuning browser tab showing the x86 results, choose Compare. Enter x86 as name for function 1 Enter arm64 as the name for function 2 Paste in the URL from the arm64 function and choose Compare.

PowerTuning Compare

View the comparison between the x86 and the arm64 function.

PowerTuning Comparison

At 2048 MB, the arm64 function is 29% faster and 43% cheaper than the identical Lambda function running on x86! Power Tuning gives you a data driven approach to select the optimal memory configuration for your Lambda functions. This allows you to also compare x86 and arm64 and may allow you to reduce the memory configuration of your arm64 Lambda functions, further reducing costs.