GithubHelp home page GithubHelp logo

spotswap's Introduction

spotswap

Build Status

⚠️ Spotswap is deprecated and not actively maintained anymore. ⚠️


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:

Name Default Description Required?
name The application's name Yes
handler node_modules/@mapbox/spotswap/index.spotswap The path within the code bundle that provides spotswap's Lambda function code.
spotFleet If you are using a spot fleet, add the logical name of the spotfleet here. Either the spotFleet option or the spotGroup option is required.
spotGroup If 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.
spotInstanceTypes The 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 types Required if you are using a spotfleet
spotInstanceWeights The 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 parameter Required if you are using a spotfleet
onDemandWeight The logical name of a stack parameter defining the weight of a single on-demand instance Required if you are using a spotfleet
onDemandGroup The logical name of an on-demand auto scaling group Yes
scaleDownPolicy The 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 policy Yes
alarmTopic The logical name of an SNS topic to receive alarm events if the spotswap function encounters any errors Yes
SpotSwapFunctionBucket The name of the AWS S3 bucket containing the SpotSwapFunction code Yes
SpotSwapFunctionS3Key The name of the AWS S3 key containing the SpotSwapFunction code Yes

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

spotswap's People

Contributors

freenerd avatar tadiseshan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spotswap's Issues

On-demand group took 10 minutes to scale up after total priceout

cloudwatch_management_console

On 10/2 at 18:43:00, one of our EC2-based saw a priceout of the last AZ available to us in the region for that instance type, which took out all 9 of our spot instances, leaving us with 0 instances running in the service. That state of 0 running instances lasted about 7 minutes before the spot market briefly returned to normal. The only scale up we saw for the on-demand group was 10 minutes after the total priceout.

Looking in the logs of the spotswap lambda function, I found the logs that were closest to the priceout:

START 
2017-10-02T18:23:08.038Z Finding instance ids in spot group: SpotGroup
2017-10-02T18:23:08.342Z Checking for termination tags on 9 instances
2017-10-02T18:23:09.624Z Found 9 instances with SpotTermination tag
2017-10-02T18:23:12.362Z No-op on stack during a CloudFormation update
END 
REPORT Duration: 4325.97 ms Billed Duration: 4400 ms Memory Size: 128 MB Max Memory Used: 53 MB
START
2017-10-02T18:25:08.775Z Finding instance ids in spot group: SpotGroup
2017-10-02T18:25:09.199Z No instances listed
2017-10-02T18:25:09.255Z Found 0 instances with SpotTermination tag
2017-10-02T18:25:09.276Z Checking spot group SpotGroup for scaledown
2017-10-02T18:25:09.276Z Checking spot group SpotGroup for scaledown
18:25:09 END

Strangely, the No-op on stack during CloudFormation update appeared when there was no cloudformation update in progress. Then, in the second message, it shows No instances listed, which seems to then no-op the function when it should have taken the lack of instances as an indication that the on-demand group should scale up.

Two questions:

  • Why did spotswap misjudge the cloudformation update?
  • Should the lack of spot instances have scaled up the on-demand group?

cc/ @arunasank @emilymcafee

Error during installation

ubuntu@ip-123-45-67-789:~$ ./node_modules/.bin/spotswap-install
/home/ubuntu/node_modules/@mapbox/spotswap/index.js:18
if (!process.env[key]) throw new Error('Env var ' + key + ' is required');
^

Error: Env var INSTANCE_ID is required
at /home/ubuntu/node_modules/@mapbox/spotswap/index.js:18:34
at Array.forEach (native)
at envCheck (/home/ubuntu/node_modules/@mapbox/spotswap/index.js:17:5)
at Object. (/home/ubuntu/node_modules/@mapbox/spotswap/bin/install.js:9:1)
at Module._compile (module.js:410:26)
at Object.Module._extensions..js (module.js:417:10)
at Module.load (module.js:344:32)
at Function.Module._load (module.js:301:12)
at Function.Module.runMain (module.js:442:10)
at startup (node.js:136:18)

What are the actual steps to install and deploy this to an existing AWS environment? There seem to be a lot of missing info in the documentation. I'm willing to help once I have it up and running. Thanks.

cc:
@arunasank
@emilymcafee
@jakepruitt

Deprecate

This project is not in use at Mapbox anymore and not actively maintained. I think we should mark that in the readme and archive this repository.

@emilymcafee @rclark ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.