Search code examples
amazon-web-servicesamazon-ec2autoscalingamazon-ec2-spot-market

How to limit the number of spot instace pools in an ASG?


I'm setting up an auto scaling group (ASG) with a mixed instances policy to use multiple spot instance types. How do I limit the number of spot instance pools used by my ASG?

Spot Instance pools are defined as follows:

A set of unused EC2 instances with the same instance type (for example, m5.large), operating system, Availability Zone, and network platform.

I understand that in my case, a spot instance pool is basically a distinct pair of availability zone and instance type.

My CloudFormation template creates an auto scaling group of 16 instances with a mixed instances policy. It uses four instance types and all availability zones. The test region us-west-2 has four availability zones. In theory, the group should be able to use up to sixteen spot isntance pools.

The stack's SpotInstancePools parameter sets the eponymous property of the ASG. I've tried setting it to various values, but it doesn't seem to directly control the number of spot instance pools used by the ASG.

CloudFormation template:

AWSTemplateFormatVersion: '2010-09-09'
Description: Testing mixed instance policies

Parameters:

  SpotInstancePools:
    Type: Number
    Default: 1
    Description: The ASG's number of spot instance pools.

  ImageId:
    Type: AWS::EC2::Image::Id
    Default: ami-061392db613a6357b
    Description: Launch template's AMI. Defaults to Amazon Linux 2.

Resources:

  AutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AvailabilityZones: !GetAZs
      MaxSize: 16
      MinSize: 16
      MixedInstancesPolicy:
        InstancesDistribution:
          OnDemandAllocationStrategy: prioritized
          OnDemandBaseCapacity: 0
          OnDemandPercentageAboveBaseCapacity: 0
          SpotAllocationStrategy: lowest-price
          SpotInstancePools: !Ref SpotInstancePools
          SpotMaxPrice: ''
        LaunchTemplate:
          LaunchTemplateSpecification:
            LaunchTemplateId: !Ref LaunchTemplate
            Version: !GetAtt LaunchTemplate.LatestVersionNumber
          Overrides:
            - InstanceType: t2.small
            - InstanceType: t3.small
            - InstanceType: t2.medium
            - InstanceType: t3.medium

  LaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateData:
        ImageId: !Ref ImageId

Command to create stack mixed-instances-policy-test-1, which has a SpotInstancePools count of 1:

aws cloudformation create-stack \
--stack-name mixed-instances-policy-test-1 \
--template-body file://mixed-instances-policy.yaml \
--parameters ParameterKey=SpotInstancePools,ParameterValue=1 \
--region us-west-2 \
--profile test

Command to create stack mixed-instances-policy-5, which has a SpotInstancePools count of 5:

aws cloudformation create-stack \
--stack-name mixed-instances-policy-test-5 \
--template-body file://mixed-instances-policy.yaml \
--parameters ParameterKey=SpotInstancePools,ParameterValue=5 \
--region us-west-2 \
--profile test

Command to list the number of unique spot instance pools used (replace name of stack as appropriate):

aws ec2 describe-instances \
--filters 'Name=tag:aws:cloudformation:stack-name,Values=mixed-instances-policy-test-1' \
--query 'Reservations[].Instances[].[InstanceType, Placement.AvailabilityZone]' \
--output text \
--region us-west-2 \
--profile test |
sort |
uniq --count

After waiting for each stack to finish creating, I check the number of unique spot instance pools.

Where SpotInstancePools is set to 1, I see 3 unique pools.

      5 t2.small    us-west-2a
      5 t3.small    us-west-2b
      6 t3.small    us-west-2c

Where SpotInstancePools is set to 5, I see 11 unique pools.

      2 t2.medium   us-west-2a
      1 t2.medium   us-west-2b
      1 t2.medium   us-west-2c
      2 t2.small    us-west-2a
      2 t2.small    us-west-2b
      1 t2.small    us-west-2c
      1 t3.medium   us-west-2a
      1 t3.medium   us-west-2b
      1 t3.medium   us-west-2c
      2 t3.small    us-west-2b
      2 t3.small    us-west-2c

In each case, I expect the number of pools to equal the parameter value.


Solution

  • What you are seeing is the normal behavior as described in the feature release notes here: https://aws.amazon.com/blogs/aws/new-ec2-auto-scaling-groups-with-multiple-instance-types-purchase-options/

    The key paragraph:

    Spot Allocation Strategy – Control the amount of per-AZ diversity for the Spot Instances. A larger number adds some flexibility at times when a particular instance type is in high demand within an AZ.

    The weighting impact on how instances are identified and grouped is explained here: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-fleet.html#spot-instance-weighting

    You can modify/force, among other features, the InstanceType and AvailabilityZone by placing some restrictions in the Overrides section of your template as noted here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-autoscalinggroup-instancesdistribution.html#cfn-as-mixedinstancespolicy-spotinstancepools

    So, there's nothing wrong per se, but you can add some constraints to make the pools equal to the parameters if that is preferred.