Skip to content

Commit f1d9b6a

Browse files
authored
feat(lambda): add support for ephemeral storage (#19552)
Depends on cfnspec bump PR #19553 CFN Docs: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-ephemeralstorage.html Blog: https://aws.amazon.com/blogs/aws/aws-lambda-now-supports-up-to-10-gb-ephemeral-storage/ <img width="1453" alt="image" src="https://user-images.githubusercontent.com/31543/160157013-1cc67553-60e7-461e-b90b-1e47d0d1215b.png"> Closes #19605. ---- ### All Submissions: * [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/master/INTEGRATION_TESTS.md)? * [ ] Did you use `cdk-integ` to deploy the infrastructure and generate the snapshot (i.e. `cdk-integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 2ae79e2 commit f1d9b6a

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

Diff for: packages/@aws-cdk/aws-lambda/README.md

+18
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,24 @@ const fn = new lambda.Function(this, 'MyLambda', {
710710
});
711711
```
712712

713+
## Ephemeral Storage
714+
715+
You can configure ephemeral storage on a function to control the amount of storage it gets for reading
716+
or writing data, allowing you to use AWS Lambda for ETL jobs, ML inference, or other data-intensive workloads.
717+
The ephemeral storage will be accessible in the functions' `/tmp` directory.
718+
719+
```ts
720+
import { Size } from '@aws-cdk/core';
721+
722+
const fn = new lambda.Function(this, 'MyFunction', {
723+
runtime: lambda.Runtime.NODEJS_14_X,
724+
handler: 'index.handler',
725+
code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')),
726+
ephemeralStorageSize: Size.mebibytes(1024),
727+
});
728+
```
729+
730+
Read more about using this feature in [this AWS blog post](https://aws.amazon.com/blogs/aws/aws-lambda-now-supports-up-to-10-gb-ephemeral-storage/).
713731

714732
## Singleton Function
715733

Diff for: packages/@aws-cdk/aws-lambda/lib/function.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as kms from '@aws-cdk/aws-kms';
66
import * as logs from '@aws-cdk/aws-logs';
77
import * as sns from '@aws-cdk/aws-sns';
88
import * as sqs from '@aws-cdk/aws-sqs';
9-
import { Annotations, ArnFormat, CfnResource, Duration, Fn, Lazy, Names, Stack, Token } from '@aws-cdk/core';
9+
import { Annotations, ArnFormat, CfnResource, Duration, Fn, Lazy, Names, Size, Stack, Token } from '@aws-cdk/core';
1010
import { Construct } from 'constructs';
1111
import { Architecture } from './architecture';
1212
import { Code, CodeConfig } from './code';
@@ -95,6 +95,13 @@ export interface FunctionOptions extends EventInvokeConfigOptions {
9595
*/
9696
readonly memorySize?: number;
9797

98+
/**
99+
* The size of the function’s /tmp directory in MB.
100+
*
101+
* @default 512 MiB
102+
*/
103+
readonly ephemeralStorageSize?: Size;
104+
98105
/**
99106
* Initial policy statements to add to the created Lambda Role.
100107
*
@@ -747,6 +754,11 @@ export class Function extends FunctionBase {
747754
}
748755
this._architecture = props.architecture ?? (props.architectures && props.architectures[0]);
749756

757+
if (props.ephemeralStorageSize && !props.ephemeralStorageSize.isUnresolved()
758+
&& (props.ephemeralStorageSize.toMebibytes() < 512 || props.ephemeralStorageSize.toMebibytes() > 10240)) {
759+
throw new Error(`Ephemeral storage size must be between 512 and 10240 MB, received ${props.ephemeralStorageSize}.`);
760+
}
761+
750762
const resource: CfnFunction = new CfnFunction(this, 'Resource', {
751763
functionName: this.physicalName,
752764
description: props.description,
@@ -767,6 +779,9 @@ export class Function extends FunctionBase {
767779
// Token, actually *modifies* the 'environment' map.
768780
environment: Lazy.uncachedAny({ produce: () => this.renderEnvironment() }),
769781
memorySize: props.memorySize,
782+
ephemeralStorage: props.ephemeralStorageSize ? {
783+
size: props.ephemeralStorageSize.toMebibytes(),
784+
} : undefined,
770785
vpcConfig: this.configureVpc(props),
771786
deadLetterConfig: this.buildDeadLetterConfig(dlqTopicOrQueue),
772787
tracingConfig: this.buildTracingConfig(props),

Diff for: packages/@aws-cdk/aws-lambda/test/function.test.ts

+46
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import * as cdk from '@aws-cdk/core';
1515
import * as constructs from 'constructs';
1616
import * as _ from 'lodash';
1717
import * as lambda from '../lib';
18+
import { Lazy, Size } from '@aws-cdk/core';
1819

1920
describe('function', () => {
2021
test('default function', () => {
@@ -2584,6 +2585,7 @@ describe('function', () => {
25842585
architectures: [lambda.Architecture.X86_64, lambda.Architecture.ARM_64],
25852586
})).toThrow(/one architecture must be specified/);
25862587
});
2588+
25872589
test('Architecture is properly readable from the function', () => {
25882590
const stack = new cdk.Stack();
25892591
const fn = new lambda.Function(stack, 'MyFunction', {
@@ -2635,6 +2637,50 @@ describe('function', () => {
26352637
});
26362638
});
26372639

2640+
test('throws if ephemeral storage size is out of bound', () => {
2641+
const stack = new cdk.Stack();
2642+
expect(() => new lambda.Function(stack, 'MyLambda', {
2643+
code: new lambda.InlineCode('foo'),
2644+
handler: 'bar',
2645+
runtime: lambda.Runtime.NODEJS_14_X,
2646+
ephemeralStorageSize: Size.mebibytes(511),
2647+
})).toThrow(/Ephemeral storage size must be between 512 and 10240 MB/);
2648+
});
2649+
2650+
test('set ephemeral storage to desired size', () => {
2651+
const stack = new cdk.Stack();
2652+
new lambda.Function(stack, 'MyLambda', {
2653+
code: new lambda.InlineCode('foo'),
2654+
handler: 'bar',
2655+
runtime: lambda.Runtime.NODEJS_14_X,
2656+
ephemeralStorageSize: Size.mebibytes(1024),
2657+
});
2658+
2659+
Template.fromStack(stack).hasResource('AWS::Lambda::Function', {
2660+
Properties:
2661+
{
2662+
Code: { ZipFile: 'foo' },
2663+
Handler: 'bar',
2664+
Runtime: 'nodejs14.x',
2665+
EphemeralStorage: {
2666+
Size: 1024,
2667+
},
2668+
},
2669+
});
2670+
});
2671+
2672+
test('ephemeral storage allows unresolved tokens', () => {
2673+
const stack = new cdk.Stack();
2674+
expect(() => {
2675+
new lambda.Function(stack, 'MyLambda', {
2676+
code: new lambda.InlineCode('foo'),
2677+
handler: 'bar',
2678+
runtime: lambda.Runtime.NODEJS_14_X,
2679+
ephemeralStorageSize: Size.mebibytes(Lazy.number({ produce: () => 1024 })),
2680+
});
2681+
}).not.toThrow();
2682+
});
2683+
26382684
function newTestLambda(scope: constructs.Construct) {
26392685
return new lambda.Function(scope, 'MyLambda', {
26402686
code: new lambda.InlineCode('foo'),

0 commit comments

Comments
 (0)