Skip to content

Commit 737e611

Browse files
authored
feat(autoscaling): support warm pools (#19214)
*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* ### Summary This PR adds an interface to create a warm pool easily, which gives an ability to decrease latency for applications that have exceptionally long boot times: https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-warm-pools.html ### Test - Run unit test and integration test. ``` PASS test/warm-pool.test.js ... =============================== Coverage summary =============================== Statements : 93.22% ( 413/443 ) Branches : 87% ( 288/331 ) Functions : 93.39% ( 99/106 ) Lines : 92.95% ( 396/426 ) ================================================================================ ... Verifying integ.warm-pool.js against integ.warm-pool.expected.json ... OK. ... ``` ### Notes - I borrowed description from [AWS public doc](https://docs.aws.amazon.com/autoscaling/ec2/APIReference/API_PutWarmPool.html) for docstring.
1 parent 7104d2c commit 737e611

File tree

8 files changed

+750
-0
lines changed

8 files changed

+750
-0
lines changed

packages/@aws-cdk/aws-autoscaling/README.md

+21
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,27 @@ const aspect = new autoscaling.AutoScalingGroupRequireImdsv2Aspect();
488488
Aspects.of(this).add(aspect);
489489
```
490490

491+
## Warm Pool
492+
493+
Auto Scaling offers [a warm pool](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-warm-pools.html) which gives an ability to decrease latency for applications that have exceptionally long boot times. You can create a warm pool with default parameters as below:
494+
495+
```ts
496+
declare const autoScalingGroup: autoscaling.AutoScalingGroup;
497+
498+
autoScalingGroup.addWarmPool();
499+
```
500+
501+
You can also customize a warm pool by configuring parameters:
502+
503+
```ts
504+
declare const autoScalingGroup: autoscaling.AutoScalingGroup;
505+
506+
autoScalingGroup.addWarmPool({
507+
minSize: 1,
508+
reuseOnScaleIn: true,
509+
});
510+
```
511+
491512
## Future work
492513

493514
* [ ] CloudWatch Events (impossible to add currently as the AutoScalingGroup ARN is

packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts

+16
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { BasicStepScalingPolicyProps, StepScalingPolicy } from './step-scaling-p
2323
import { BaseTargetTrackingProps, PredefinedMetric, TargetTrackingScalingPolicy } from './target-tracking-scaling-policy';
2424
import { TerminationPolicy } from './termination-policy';
2525
import { BlockDevice, BlockDeviceVolume, EbsDeviceVolumeType } from './volume';
26+
import { WarmPool, WarmPoolOptions } from './warm-pool';
2627

2728
/**
2829
* Name tag constant
@@ -744,6 +745,16 @@ abstract class AutoScalingGroupBase extends Resource implements IAutoScalingGrou
744745
});
745746
}
746747

748+
/**
749+
* Add a pool of pre-initialized EC2 instances that sits alongside an Auto Scaling group
750+
*/
751+
public addWarmPool(options?: WarmPoolOptions): WarmPool {
752+
return new WarmPool(this, 'WarmPool', {
753+
autoScalingGroup: this,
754+
...options,
755+
});
756+
}
757+
747758
/**
748759
* Scale out or in based on time
749760
*/
@@ -1630,6 +1641,11 @@ export interface IAutoScalingGroup extends IResource, iam.IGrantable {
16301641
*/
16311642
addLifecycleHook(id: string, props: BasicLifecycleHookProps): LifecycleHook;
16321643

1644+
/**
1645+
* Add a pool of pre-initialized EC2 instances that sits alongside an Auto Scaling group
1646+
*/
1647+
addWarmPool(options?: WarmPoolOptions): WarmPool;
1648+
16331649
/**
16341650
* Scale out or in based on time
16351651
*/

packages/@aws-cdk/aws-autoscaling/lib/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export * from './step-scaling-policy';
99
export * from './target-tracking-scaling-policy';
1010
export * from './termination-policy';
1111
export * from './volume';
12+
export * from './warm-pool';
1213

1314
// AWS::AutoScaling CloudFormation Resources:
1415
export * from './autoscaling.generated';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { Lazy, Names, Resource } from '@aws-cdk/core';
2+
import { Construct } from 'constructs';
3+
import { IAutoScalingGroup } from './auto-scaling-group';
4+
import { CfnWarmPool } from './autoscaling.generated';
5+
6+
/**
7+
* Options for a warm pool
8+
*/
9+
export interface WarmPoolOptions {
10+
/**
11+
* Indicates whether instances in the Auto Scaling group can be returned to the warm pool on scale in.
12+
*
13+
* If the value is not specified, instances in the Auto Scaling group will be terminated
14+
* when the group scales in.
15+
*
16+
* @default false
17+
*/
18+
readonly reuseOnScaleIn?: boolean;
19+
20+
/**
21+
* The maximum number of instances that are allowed to be in the warm pool
22+
* or in any state except Terminated for the Auto Scaling group.
23+
*
24+
* If the value is not specified, Amazon EC2 Auto Scaling launches and maintains
25+
* the difference between the group's maximum capacity and its desired capacity.
26+
*
27+
* @default - max size of the Auto Scaling group
28+
*/
29+
readonly maxGroupPreparedCapacity?: number;
30+
/**
31+
* The minimum number of instances to maintain in the warm pool.
32+
*
33+
* @default 0
34+
*/
35+
readonly minSize?: number;
36+
/**
37+
* The instance state to transition to after the lifecycle actions are complete.
38+
*
39+
* @default PoolState.STOPPED
40+
*/
41+
readonly poolState?: PoolState;
42+
}
43+
44+
/**
45+
* Properties for a warm pool
46+
*/
47+
export interface WarmPoolProps extends WarmPoolOptions {
48+
/**
49+
* The Auto Scaling group to add the warm pool to.
50+
*/
51+
readonly autoScalingGroup: IAutoScalingGroup;
52+
}
53+
54+
/**
55+
* Define a warm pool
56+
*/
57+
export class WarmPool extends Resource {
58+
constructor(scope: Construct, id: string, props: WarmPoolProps) {
59+
super(scope, id, {
60+
physicalName: Lazy.string({ produce: () => Names.uniqueId(this) }),
61+
});
62+
63+
if (props.maxGroupPreparedCapacity && props.maxGroupPreparedCapacity < -1) {
64+
throw new Error('\'maxGroupPreparedCapacity\' parameter should be greater than or equal to -1');
65+
}
66+
67+
if (props.minSize && props.minSize < 0) {
68+
throw new Error('\'minSize\' parameter should be greater than or equal to 0');
69+
}
70+
71+
new CfnWarmPool(this, 'Resource', {
72+
autoScalingGroupName: props.autoScalingGroup.autoScalingGroupName,
73+
instanceReusePolicy: props.reuseOnScaleIn !== undefined ? {
74+
reuseOnScaleIn: props.reuseOnScaleIn,
75+
} : undefined,
76+
maxGroupPreparedCapacity: props.maxGroupPreparedCapacity,
77+
minSize: props.minSize,
78+
poolState: props.poolState,
79+
});
80+
}
81+
}
82+
83+
/**
84+
* The instance state in the warm pool
85+
*/
86+
export enum PoolState {
87+
/**
88+
* Hibernated
89+
*
90+
* To use this state, prerequisites must be in place.
91+
* @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/hibernating-prerequisites.html
92+
*/
93+
HIBERNATED = 'Hibernated',
94+
95+
/**
96+
* Running
97+
*/
98+
RUNNING = 'Running',
99+
100+
/**
101+
* Stopped
102+
*/
103+
STOPPED = 'Stopped',
104+
}

packages/@aws-cdk/aws-autoscaling/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
"export:@aws-cdk/aws-autoscaling.IAutoScalingGroup",
123123
"props-physical-name:@aws-cdk/aws-autoscaling.AutoScalingGroupProps",
124124
"props-physical-name:@aws-cdk/aws-autoscaling.ScheduledActionProps",
125+
"props-physical-name:@aws-cdk/aws-autoscaling.WarmPoolProps",
125126
"props-default-doc:@aws-cdk/aws-autoscaling.EbsDeviceOptionsBase.iops",
126127
"docs-public-apis:@aws-cdk/aws-autoscaling.ScalingProcess.ADD_TO_LOAD_BALANCER",
127128
"docs-public-apis:@aws-cdk/aws-autoscaling.ScalingProcess.SCHEDULED_ACTIONS",

0 commit comments

Comments
 (0)