Skip to content
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): add availabilityZoneDistribution property to a AutoScalingGroup #32100

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
31 changes: 31 additions & 0 deletions packages/aws-cdk-lib/aws-autoscaling/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,37 @@ new autoscaling.AutoScalingGroup(this, 'ASG', {
});
```

## Availability Zone Distribution

You can configure how Auto Scaling distributes instances across Availability Zones when scaling operations occur. This is particularly useful when you need strict control over instance distribution for high availability.

### capacityDistributionStrategy

If launches fail in an Availability Zone, the following strategies are available.

* `BALANCED_BEST_EFFORT` (default) - If launches fail in an Availability Zone, Auto Scaling will attempt to launch in another healthy Availability Zone instead.
* `BALANCED_ONLY` - If launches fail in an Availability Zone, Auto Scaling will continue to attempt to launch in the unhealthy zone to preserve a balanced distribution.

```ts
declare const vpc: ec2.Vpc;
declare const instanceType: ec2.InstanceType;
declare const machineImage: ec2.IMachineImage;

const myKeyPair = new ec2.KeyPair(this, 'MyKeyPair');

new autoscaling.AutoScalingGroup(this, 'ASG', {
vpc,
instanceType,
machineImage,

// ...

availabilityZoneDistribution: {
capacityDistributionStrategy: autoscaling.CapacityDistributionStrategy.BALANCED_BEST_EFFORT,
}
});
```

## Future work

* [ ] CloudWatch Events (impossible to add currently as the AutoScalingGroup ARN is
Expand Down
29 changes: 29 additions & 0 deletions packages/aws-cdk-lib/aws-autoscaling/lib/auto-scaling-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,28 @@ export enum Monitoring {
DETAILED,
}

/**
* The strategies for when launches fail in an Availability Zone.
*/
export enum CapacityDistributionStrategy {
/**
* If launches fail in an Availability Zone, Auto Scaling will continue to attempt to launch in the unhealthy zone to preserve a balanced distribution.
*/
BALANCED_ONLY = 'balanced-only',
/**
* If launches fail in an Availability Zone, Auto Scaling will attempt to launch in another healthy Availability Zone instead.
*/
BALANCED_BEST_EFFORT= 'balanced-best-effort',
}

export interface AvailabilityZoneDistribution {
/**
* The strategy for distributing instances across Availability Zones.
* @default BALANCED_BEST_EFFORT
*/
readonly capacityDistributionStrategy: CapacityDistributionStrategy;
}

/**
* Basic properties of an AutoScalingGroup, except the exact machines to run and where they should run
*
Expand Down Expand Up @@ -410,6 +432,12 @@ export interface CommonAutoScalingGroupProps {
* @default false
*/
readonly ssmSessionPermissions?: boolean;

/**
* The instance capacity distribution across Availability Zones.
* @default { capacityDistributionStrategy: CapacityDistributionStrategy.BALANCED_BEST_EFFORT }
*/
readonly availabilityZoneDistribution?: AvailabilityZoneDistribution;
}

/**
Expand Down Expand Up @@ -1529,6 +1557,7 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements

const asgProps: CfnAutoScalingGroupProps = {
autoScalingGroupName: this.physicalName,
availabilityZoneDistribution: props.availabilityZoneDistribution,
cooldown: props.cooldown?.toSeconds().toString(),
minSize: Tokenization.stringifyNumber(minCapacity),
maxSize: Tokenization.stringifyNumber(maxCapacity),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2797,6 +2797,29 @@ describe('InstanceMaintenancePolicy', () => {
});
});

test('can specify capacityDistributionStrategy', () => {
// GIVEN
const stack = new cdk.Stack();
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,
availabilityZoneDistribution: {
capacityDistributionStrategy: autoscaling.CapacityDistributionStrategy.BALANCED_ONLY,
},
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', {
AvailabilityZoneDistribution: {
CapacityDistributionStrategy: 'balanced-only',
},
});
});

test('throws if maxHealthyPercentage is greater than 200', () => {
// GIVEN
const stack = new cdk.Stack();
Expand Down
Loading