Skip to content

Commit

Permalink
feat(lambda): support for ARM architecture (#16719)
Browse files Browse the repository at this point in the history
Add support for the `architectures` and `compatibleArchitectures` key
in the `Function` and `LayerVersion` constructs.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
mergify[bot] authored Sep 29, 2021
2 parents 65761fe + 64c9524 commit 67b4921
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 1 deletion.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [1.125.0](https://github.com/aws/aws-cdk/compare/v1.124.0...v1.125.0) (2021-09-29)


### Features

* **lambda:** support for ARM architecture ([b3ba35e](https://github.com/aws/aws-cdk/commit/b3ba35e9b8b157303a29350031885eff0c73b05b))

## [1.124.0](https://github.com/aws/aws-cdk/compare/v1.123.0...v1.124.0) (2021-09-21)


Expand Down
25 changes: 25 additions & 0 deletions packages/@aws-cdk/aws-lambda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,31 @@ new LayerVersion(this, 'MyLayer', {
});
```

## Architecture

Lambda functions, by default, run on compute systems that have the 64 bit x86 architecture.

The AWS Lambda service also runs compute on the ARM architecture, which can reduce cost
for some workloads.

A lambda function can be configured to be run on one or both of these platforms -

```ts
new Function(this, 'MyFunction', {
...
architectures: [ Architecture.X86_64, Architecture.ARM_64 ],
});
```

Similarly, lambda layer versions can also be tagged with architectures it is compatible with.

```ts
new LayerVersion(this, 'MyLayer', {
...
compatibleArchitectures: [ Architecture.X86_64, Architecture.ARM_64 ],
});
```

## Lambda Insights

Lambda functions can be configured to use CloudWatch [Lambda Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights.html)
Expand Down
32 changes: 32 additions & 0 deletions packages/@aws-cdk/aws-lambda/lib/architecture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Architectures supported by AWS Lambda
*/
export class Architecture {
/**
* 64 bit architecture with x86 instruction set.
*/
public static readonly X86_64 = new Architecture('x86_64');

/**
* 64 bit architecture with the ARM instruction set.
*/
public static readonly ARM_64 = new Architecture('arm64');

/**
* Used to specify a custom architecture name.
* Use this if the architecture name is not yet supported by the CDK.
* @param name the architecture name as recognized by AWS Lambda.
*/
public static custom(name: string) {
return new Architecture(name);
}

/**
* The name of the architecture as recognized by the AWS Lambda service APIs.
*/
public readonly name: string;

private constructor(archName: string) {
this.name = archName;
}
}
13 changes: 13 additions & 0 deletions packages/@aws-cdk/aws-lambda/lib/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as logs from '@aws-cdk/aws-logs';
import * as sqs from '@aws-cdk/aws-sqs';
import { Annotations, CfnResource, Duration, Fn, Lazy, Names, Stack } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { Architecture } from './architecture';
import { Code, CodeConfig } from './code';
import { ICodeSigningConfig } from './code-signing-config';
import { EventInvokeConfigOptions } from './event-invoke-config';
Expand Down Expand Up @@ -310,6 +311,12 @@ export interface FunctionOptions extends EventInvokeConfigOptions {
* @default - Not Sign the Code
*/
readonly codeSigningConfig?: ICodeSigningConfig;

/**
* The system architectures compatible with this lambda function.
* @default [Architecture.X86_64]
*/
readonly architectures?: Architecture[];
}

export interface FunctionProps extends FunctionOptions {
Expand Down Expand Up @@ -680,6 +687,7 @@ export class Function extends FunctionBase {
kmsKeyArn: props.environmentEncryption?.keyArn,
fileSystemConfigs,
codeSigningConfigArn: props.codeSigningConfig?.codeSigningConfigArn,
architectures: props.architectures?.map(a => a.name),
});

resource.node.addDependency(this.role);
Expand Down Expand Up @@ -792,6 +800,11 @@ export class Function extends FunctionBase {
const runtimes = layer.compatibleRuntimes.map(runtime => runtime.name).join(', ');
throw new Error(`This lambda function uses a runtime that is incompatible with this layer (${this.runtime.name} is not in [${runtimes}])`);
}

// Currently no validations for compatible architectures since Lambda service
// allows layers configured with one architecture to be used with a Lambda function
// from another architecture.

this.layers.push(layer);
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-lambda/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export * from './scalable-attribute-api';
export * from './code-signing-config';
export * from './lambda-insights';
export * from './log-retention';
export * from './architecture';

// AWS::Lambda CloudFormation Resources:
export * from './lambda.generated';
Expand Down
8 changes: 8 additions & 0 deletions packages/@aws-cdk/aws-lambda/lib/layers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IResource, RemovalPolicy, Resource } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { Architecture } from './architecture';
import { Code } from './code';
import { CfnLayerVersion, CfnLayerVersionPermission } from './lambda.generated';
import { Runtime } from './runtime';
Expand Down Expand Up @@ -46,6 +47,12 @@ export interface LayerVersionProps extends LayerVersionOptions {
*/
readonly compatibleRuntimes?: Runtime[];

/**
* The system architectures compatible with this layer.
* @default [Architecture.X86_64]
*/
readonly compatibleArchitectures?: Architecture[];

/**
* The content of this Layer.
*
Expand Down Expand Up @@ -196,6 +203,7 @@ export class LayerVersion extends LayerVersionBase {

const resource: CfnLayerVersion = new CfnLayerVersion(this, 'Resource', {
compatibleRuntimes: props.compatibleRuntimes && props.compatibleRuntimes.map(r => r.name),
compatibleArchitectures: props.compatibleArchitectures?.map(a => a.name),
content: {
s3Bucket: code.s3Location.bucketName,
s3Key: code.s3Location.objectKey,
Expand Down
15 changes: 15 additions & 0 deletions packages/@aws-cdk/aws-lambda/test/function.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2174,6 +2174,21 @@ describe('function', () => {
})).toThrow(/Layers are not supported for container image functions/);
});

test('specified architecture is recognized', () => {
const stack = new cdk.Stack();
new lambda.Function(stack, 'MyFunction', {
code: lambda.Code.fromInline('foo'),
runtime: lambda.Runtime.NODEJS_12_X,
handler: 'index.handler',

architectures: [lambda.Architecture.ARM_64],
});

expect(stack).toHaveResource('AWS::Lambda::Function', {
Architectures: ['arm64'],
});
});

});

function newTestLambda(scope: constructs.Construct) {
Expand Down
14 changes: 14 additions & 0 deletions packages/@aws-cdk/aws-lambda/test/layers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,18 @@ describe('layers', () => {
DeletionPolicy: 'Retain',
}, ResourcePart.CompleteDefinition);
});

test('specified compatible architectures is recognized', () => {
const stack = new cdk.Stack();
const bucket = new s3.Bucket(stack, 'Bucket');
const code = new lambda.S3Code(bucket, 'ObjectKey');
new lambda.LayerVersion(stack, 'MyLayer', {
code,
compatibleArchitectures: [lambda.Architecture.ARM_64],
});

expect(stack).toHaveResource('AWS::Lambda::LayerVersion', {
CompatibleArchitectures: ['arm64'],
});
});
});
41 changes: 41 additions & 0 deletions packages/@aws-cdk/cfnspec/spec-source/530_Lambda_ARM_patch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"ResourceType": {
"AWS::Lambda::Function": {
"patch": {
"description": "AWS::Lambda::Function changes for early support of Lambda ARM launch. Remove once CFN spec is updated",
"operations": [
{
"op": "add",
"path": "/Properties/Architectures",
"value": {
"Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-architectures",
"UpdateType": "Mutable",
"Required": false,
"Type": "List",
"PrimitiveItemType": "String",
"DuplicatesAllowed": true
}
}
]
}
},
"AWS::Lambda::LayerVersion": {
"patch": {
"description": "AWS::Lambda::LayerVersion changes for early support of Lambda ARM launch. Remove once CFN spec is updated",
"operations": [
{
"op": "add",
"path": "/Properties/CompatibleArchitectures",
"value": {
"PrimitiveItemType": "String",
"Type": "List",
"Required": false,
"Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-layerversion.html#cfn-lambda-layerversion-compatiblearchitectures",
"UpdateType": "Immutable"
}
}
]
}
}
}
}
2 changes: 1 addition & 1 deletion version.v1.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "1.124.0"
"version": "1.125.0"
}

0 comments on commit 67b4921

Please sign in to comment.