6.0.5 • Published 7 years ago

@mapbox/spotswap v6.0.5

Weekly downloads
-
License
ISC
Repository
github
Last release
7 years ago

spotswap

Build Status

Spotswap manages spot priceouts for a spot AutoScaling Group or SpotFleet by activating backup on-demand capacity. It contains three service components, which are described below.


spotswap-poll

spotswap-poll is an upstart service that runs on each spot EC2 instance in a spot AutoScaling Group or Spot Fleet. It polls the termination notification endpoint, and upon finding a termination notice, will tag the instance with a SpotTermination: true tag.

Usage

./node_modules/.bin/spotswap-install

Call spotswap-install if globally linked or call directly from npm installed bin path:

Requirements

Dependencies

  • awscli
  • upstart

Run-time environment

  • Environment variables:

    • TerminationOverrideFunction (optional): An environment variable that contains the AWS ARN of a lambda function that can be invoked whenever a spot EC2 receives a termination notification, instead of directly terminating the instance. If this is not specified, any instances with SpotTermination tags will be terminated.
    • terminationTimeout (optional): An environment variable that determines how long to wait before calling terminateInstanceInAutoScalingGroup on an instance in a spot AutoScaling group. If this is not specified, terminateInstanceInAutoScalingGroup will be called on an instance after 90 seconds.
  • AWS API permissions

    • The main Role resource in your CloudFormation template used to create, update or delete instances should contain permissions to create EC2 tags. For example:
    Role: {
      Type: 'AWS::IAM::Role',
      Properties: {
        AssumeRolePolicyDocument: {
          Statement: [
            {
              Action: [
                'sts:AssumeRole'
              ],
              Effect: 'Allow',
              Principal: {
                Service: [
                  'ec2.amazonaws.com'
                ]
              }
            }
          ]
        },
        Policies: [
          {
            PolicyName: 'tag-instances',
            PolicyDocument: {
              Statement: [
                {
                  Action: ['ec2:CreateTags'],
                  Effect: 'Allow',
                  Resource: '*'
                }
              ]
            }
          }]
      }
    }
    • If you are using the TerminationOverrideFunction environment variable, you also need to include the permissions to invoke this function as part of your cloudformation template.

spotswap-cfn

spotswap-cfn provides the CloudFormation resources necessary for this system to run (mostly for SpotswapFunction), and a validator to make sure you have everything you need in your CFN template.

Usage

var cf = require('@mapbox/cloudfriend');
var spotswap = require('@mapbox/spotswap');

var spotswapConfiguration = {
  name: 'myApplication',
  onDemandGroup: 'OnDemandGroup',
  spotGroup: 'SpotGroup',
  scaleDownPolicy: 'ScaleDownPolicy',
  alarmTopic: 'AlarmEmail',
  SpotSwapFunctionBucket: 'spotswap-code',
  SpotSwapFunctionS3Key: 'lambda.zip'
};

var myTemplate = {
  Parameters: {
    GitSha: { Type: 'String' },
    AlarmEmail: { Type: 'String' },
    OnDemandGroup: { Type: 'String' }
  },
  Resources: {
    MyBucket: {
      Type: 'AWS::S3::Bucket',
      Properties: {
        Name: 'my-bucket'
      }
    },
    LaunchConfigOnDemand: {
      Type : "AWS::AutoScaling::LaunchConfiguration",
      Properties : {
        ImageId : {
          'Fn::FindInMap' : [
            'AWSRegionArch2AMI',
            { 'Ref' : 'AWS::Region' },
            {
               'Fn::FindInMap' : [
                  'AWSInstanceType2Arch', 'c3.8xlarge', 'Arch'
               ]
            }
          ]
        },
        InstanceType : 'c3.8xlarge'
      }
    },
    LaunchConfigSpot: {
      Type : "AWS::AutoScaling::LaunchConfiguration",
      Properties : {
        ImageId : {
          'Fn::FindInMap' : [
            'AWSRegionArch2AMI',
            { 'Ref' : 'AWS::Region' },
            {
               'Fn::FindInMap' : [
                  'AWSInstanceType2Arch', 'c3.8xlarge', 'Arch'
               ]
            }
          ]
        },
        InstanceType : 'c3.8xlarge',
        SpotPrice: {
          'Fn::FindInMap' : [
              PriceMap, 'c3.8xlarge', 'price'
          ]
        }
      }
    },
    OnDemandGroup: {
      Type : 'AWS::AutoScaling::AutoScalingGroup',
      Properties : {
        AvailabilityZones : { 'Fn::GetAZs' : { 'Ref' : 'AWS::Region' } },
        LaunchConfigurationName : { 'Ref' : 'LaunchConfigOnDemand' },
        MaxSize : 1,
        MinSize : 0
      },
      UpdatePolicy : {
        AutoScalingRollingUpdate : {
          MinInstancesInService : 0,
          MaxBatchSize : 5,
          PauseTime : 'PT10M',
          WaitOnResourceSignals : 'true'
        }
      }
    },
    SpotGroup: {
      Type: 'AWS::AutoScaling::AutoScalingGroup',
      Properties: {
        AvailabilityZones: { 'Fn::GetAZs' : { 'Ref' : 'AWS::Region' } },
        LaunchConfigurationName: { Ref: 'LaunchConfigSpot' },
        MaxSize: 3,
        MinSize: 1,
    }
  }
};

cf.merge(myTemplate, spotswap.cfn.template(spotswapConfiguration));

The Spotswap configuration object:

NameDefaultDescriptionRequired?
nameThe application's nameYes
handlernode_modules/@mapbox/spotswap/index.spotswapThe path within the code bundle that provides spotswap's Lambda function code.
spotFleetIf you are using a spot fleet, add the logical name of the spotfleet here.Either the spotFleet option or the spotGroup option is required.No
spotGroupIf you are using a spot autoscaling group, add the logical name of the spot auto-scaling group here.Either the spotFleet option or the spotGroup option is required.
spotInstanceTypesThe logical name of a stack parameter defining spot instance types as a comma-delimited list or a comma-delimited list of parameter names defining several spot instance typesRequired if you are using a spotfleet
spotInstanceWeightsThe logical name of a stack parameter defining spot instance weights as a comma-delimited list. The ordering of the weights must correspond to the ordering of the instance types in the previous parameterRequired if you are using a spotfleet
onDemandWeightThe logical name of a stack parameter defining the weight of a single on-demand instanceRequired if you are using a spotfleet
onDemandGroupThe logical name of an on-demand auto scaling groupYes
scaleDownPolicyThe logical name of an auto scaling policy that should be invoked to scale down the on-demand group when spot capacity is fulfilled. Important: This cannot be a StepScaling policyYes
alarmTopicThe logical name of an SNS topic to receive alarm events if the spotswap function encounters any errorsYes
SpotSwapFunctionBucketThe name of the AWS S3 bucket containing the SpotSwapFunction codeYes
SpotSwapFunctionS3KeyThe name of the AWS S3 key containing the SpotSwapFunction codeYes

SpotswapFunction

SpotswapFunction is a Lambda function that runs minutely, scanning a spot AutoScaling Group or SpotFleet for SpotTermination tags. If tags are found, the function scales up a backup on-demand AutoScaling Group by the number of tags it found, then deletes the tags. If no tags are found, the function evaluates the spot resource to determine if the backup on-demand group can scale down - if so, the function invokes a scale-down Scaling Policy for the on-demand group. This module provides the necessary CloudFormation template to include the spotswap configuration in your CloudFormation.

Usage

  • Include this module as part of your CloudFormation template, and follow the instructions under spotswap-cfn. You can also use cfn-config to easily create, update and delete your cloudformation stacks.

Requirements

  • AWS API permissions
    • All required permissions are fulfilled by spotswap-cfn.

CONTRIBUTORS

At the time this package was moved to becoming open source, contributors were:

  • @arunasank
  • @emilymcafee
  • @emilymdubois
  • @KaiBot3000
  • @rclark
  • @xrwang
  • @yhahn
6.0.5

7 years ago

6.0.4

7 years ago

6.0.3

7 years ago

6.0.3-no-90-s

7 years ago

6.0.2

7 years ago

6.0.1

7 years ago

6.0.0

7 years ago

5.4.2

8 years ago

5.4.1

8 years ago

5.4.0

8 years ago

5.3.2

8 years ago

5.3.2-0

8 years ago

5.3.1

8 years ago

5.3.0

8 years ago

5.3.0-dev2

8 years ago

5.3.0-dev1

8 years ago

5.2.0

8 years ago

5.1.0

8 years ago

5.0.0

8 years ago

4.0.0

8 years ago

3.3.0

8 years ago

3.2.0

8 years ago

3.2.0-dev2

8 years ago

3.2.0-dev1

8 years ago

3.1.0

8 years ago

3.0.0

8 years ago

3.0.0-24

8 years ago

3.0.0-23

8 years ago

3.0.0-22

8 years ago

3.0.0-21

8 years ago

3.0.0-20

8 years ago

3.0.0-18

8 years ago

3.0.0-17

8 years ago

3.0.0-16

8 years ago

3.0.0-15

8 years ago

3.0.0-14

8 years ago

3.0.0-13

8 years ago

3.0.0-12

8 years ago

3.0.0-11

8 years ago

3.0.0-10

8 years ago

3.0.0-9

8 years ago

3.0.0-8

8 years ago

3.0.0-7

8 years ago

3.0.0-6

8 years ago

3.0.0-5

8 years ago

3.0.0-4

8 years ago

3.0.0-3

8 years ago

3.0.0-2

8 years ago

3.0.0-1

8 years ago

3.0.0-0

8 years ago

2.5.0-0

8 years ago

2.4.3

8 years ago

2.4.3-0

8 years ago

2.4.2

8 years ago

2.4.2-0

8 years ago

2.4.1

8 years ago

2.4.0-dev.1

8 years ago

2.4.0-dev.0

8 years ago

2.4.0

8 years ago

2.3.3-ecsdev2

8 years ago

2.3.3-ecsdev1

8 years ago

2.3.3

8 years ago

2.3.2

8 years ago

2.3.1

8 years ago

2.3.0

8 years ago

2.2.3-dev11

8 years ago

2.2.3-dev10

8 years ago

2.2.3-dev9

8 years ago

2.2.3-ecs-dev5

8 years ago

2.2.3-ecs-dev4

8 years ago

2.2.3-ecs-dev3

8 years ago

2.2.3-ecs-dev2

8 years ago

2.2.3-ecs-dev1

8 years ago

2.3.0-dev1

8 years ago

2.2.3

8 years ago

2.2.2

8 years ago

2.2.1-dev2

8 years ago

2.2.1-dev1

8 years ago

2.2.1

8 years ago

2.2.0

8 years ago

2.1.0

8 years ago

2.1.0-dev3

8 years ago

2.1.0-dev2

8 years ago

2.1.0-dev1

8 years ago

2.0.0

8 years ago

2.0.0-dev2

8 years ago

2.0.0-dev1

8 years ago

1.0.3

8 years ago

1.0.2

8 years ago

1.0.1

8 years ago

1.0.0

8 years ago