-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(autoscaling): health check configuration #3390
Changes from 2 commits
5944005
ef18ded
837f97f
1978b98
a68f32c
50f9e06
430812c
e254ac6
10a41d0
621c076
0b8a6a7
5cf98c4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -156,6 +156,13 @@ export interface CommonAutoScalingGroupProps { | |
* @default none | ||
*/ | ||
readonly spotPrice?: string; | ||
|
||
/** | ||
* Configuration for health checks | ||
* | ||
* @default - HealthCheckConfiguration with defaults. | ||
*/ | ||
readonly healthCheck?: HealthCheckConfiguration; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will lends itself nicely to a "union-like" API: export interface Ec2HealthCheckOptions {
readonly grace?: Duration;
}
export interface ElbHealthCheckOptions {
readonly grace: Duration; // <-- required here
}
export class HealthCheck {
public static ec2(options: Ec2HealthCheckOptions = {}): HealthCheck {
return new HealthCheck('EC2', options.grace && options.grace.toSeconds());
}
public static elb(options: ElbHealthCheckOptions): HealthCheck {
return new HealthCheck('ELB', options.grace.toSeconds());
}
private constructor(public readonly type: string, public readonly gradePeriod?: number) { }
} And then the usage is: healthCheck: HealthCheck.ec2();
healthCheck: HealthCheck.ec2({ grace: Duration.minutes(5) });
healthCheck: HealthCheck.elb({ grace: Duration.minutes(5) }); // <-- required grace enforced by compiler There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a much cleaner API, thanks. How would you feel about using a export interface HealthCheckOptions {
readonly grace: Duration;
}
export class HealthCheck {
public static ec2(options: Partial<HealthCheckOptions> = {}): HealthCheck {
return new HealthCheck('EC2', options.grace && options.grace.toSeconds());
}
public static elb(options: HealthCheckOptions): HealthCheck {
return new HealthCheck('ELB', options.grace.toSeconds());
}
private constructor(public readonly type: string, public readonly gradePeriod?: number) { }
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Never mind, it seems like JSII doesn't support the Partial keyword:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, thanks |
||
} | ||
|
||
/** | ||
|
@@ -424,6 +431,10 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements | |
throw new Error(`Should have minCapacity (${minCapacity}) <= desiredCapacity (${desiredCapacity}) <= maxCapacity (${maxCapacity})`); | ||
} | ||
|
||
if (props.healthCheck && props.healthCheck.type === HealthCheckType.ELB && !props.healthCheck.gracePeriod) { | ||
throw new Error('The healthCheck.gracePeriod property must be set with healthCheck.type === HealthCheckType.ELB'); | ||
} | ||
|
||
const { subnetIds, hasPublic } = props.vpc.selectSubnets(props.vpcSubnets); | ||
const asgProps: CfnAutoScalingGroupProps = { | ||
cooldown: props.cooldown !== undefined ? props.cooldown.toSeconds().toString() : undefined, | ||
|
@@ -444,7 +455,9 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements | |
], | ||
} | ||
], | ||
vpcZoneIdentifier: subnetIds | ||
vpcZoneIdentifier: subnetIds, | ||
healthCheckType: props.healthCheck && props.healthCheck.type, | ||
healthCheckGracePeriod: props.healthCheck && props.healthCheck.gracePeriod ? props.healthCheck.gracePeriod.toSeconds() : undefined, | ||
}; | ||
|
||
if (!hasPublic && props.associatePublicIpAddress) { | ||
|
@@ -673,6 +686,35 @@ export enum ScalingProcess { | |
ADD_TO_LOAD_BALANCER = 'AddToLoadBalancer' | ||
} | ||
|
||
/** | ||
* Health check settings | ||
*/ | ||
export interface HealthCheckConfiguration { | ||
/** | ||
* Specifies the service to use for the health checks | ||
* | ||
* If you configure an Auto Scaling group to use ELB health checks, it considers the instance unhealthy | ||
* if it fails either the EC2 status checks or the load balancer health checks. | ||
* | ||
* @default HealthCheckType.EC2 | ||
*/ | ||
readonly type?: HealthCheckType; | ||
|
||
/** | ||
* Specified the time Auto Scaling waits before checking the health status of an EC2 instance that has come into service | ||
* | ||
* This property required with ELB health check type. | ||
* | ||
* @default - | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't find a current default value in the CloudFormation documentation. The API Reference mentions a default of 0. Should I use |
||
*/ | ||
readonly gracePeriod?: Duration; | ||
} | ||
|
||
export enum HealthCheckType { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to export this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
EC2 = 'EC2', | ||
ELB = 'ELB', | ||
} | ||
|
||
/** | ||
* Render the rolling update configuration into the appropriate object | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -397,6 +397,54 @@ export = { | |
test.done(); | ||
}, | ||
|
||
'can configure health check'(test: Test) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add a test for ec2 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
// GIVEN | ||
const stack = new cdk.Stack(undefined, 'MyStack', { env: { region: 'us-east-1', account: '1234' } }); | ||
const vpc = mockVpc(stack); | ||
|
||
// WHEN | ||
new autoscaling.AutoScalingGroup(stack, 'MyFleet', { | ||
instanceType: ec2.InstanceType.of(ec2.InstanceClass.M4, ec2.InstanceSize.MICRO), | ||
machineImage: new ec2.AmazonLinuxImage(), | ||
vpc, | ||
healthCheck: { | ||
type: autoscaling.HealthCheckType.ELB, | ||
gracePeriod: cdk.Duration.minutes(15) | ||
} | ||
}); | ||
|
||
// THEN | ||
expect(stack).to(haveResourceLike("AWS::AutoScaling::AutoScalingGroup", { | ||
HealthCheckType: 'ELB', | ||
HealthCheckGracePeriod: 900 | ||
})); | ||
|
||
test.done(); | ||
}, | ||
|
||
'throws when healthCheck.type is ELB without a gracePeriod'(test: Test) { | ||
// GIVEN | ||
const stack = new cdk.Stack(undefined, 'MyStack', { env: { region: 'us-east-1', account: '1234' } }); | ||
const vpc = mockVpc(stack); | ||
|
||
// WHEN | ||
const toThrow = () => { | ||
new autoscaling.AutoScalingGroup(stack, 'MyFleet', { | ||
instanceType: ec2.InstanceType.of(ec2.InstanceClass.M4, ec2.InstanceSize.MICRO), | ||
machineImage: new ec2.AmazonLinuxImage(), | ||
vpc, | ||
healthCheck: { | ||
type: autoscaling.HealthCheckType.ELB, | ||
} | ||
}); | ||
}; | ||
|
||
// THEN | ||
test.throws(() => toThrow(), /gracePeriod property must be set/); | ||
|
||
test.done(); | ||
}, | ||
|
||
'can add Security Group to Fleet'(test: Test) { | ||
// GIVEN | ||
const stack = new cdk.Stack(undefined, 'MyStack', { env: { region: 'us-east-1', account: '1234' } }); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If
healthCheck
is not specified, then there are no health checks, right? Fix the default description.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the health check is mandatory. The CloudFormation documentation says EC2 is the default, and the API reference says the value is required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, so we should say that EC2 with no grace period is the default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done