Getting More From AWS: the Spot Instances (via SDK for .NET)

Taras Kushnir
Software engineer at ELEKS

We have discussed the basic principles of working with On-Demand instances of AWS web-services in the previous post. On-Demand instances are quite straightforward and have expected behaviour. But… what about something more stochastic and thus more interesting?

Amazon EC2 instance types

Amazon offers us several types of its compute instances: On-Demand, Reserved and Spot instances. You can read the details on the AWS website, but, to make the long story short, there are several types of instances:

  1. On-Demand instances are fixed hourly rate mostly always available instances which are often used for applications which need some basic guarantees about start time of the instance.
  2. Reserved instances are pre-paid On-Demand instances that allow you to reduce the cost on the long run if you utilize the machines rather heavily.
  3. Spot instances are the most interesting kind of instances, because we act like an auction player and set a price which we are willing to pay to run such an instance and if our bid beats other customers at the moment we are able to launch requested instances for some time period. If current Spot price moves higher than ours, Amazon EC2 service shuts down our instance.

More about Spot instances

Spot instances are kind of tricky instances which are not guaranteed to run when we request them. We have to place a bid and wait until it wins (if it will someday) in order to run a Spot instance. To do this we can send Spot instance request with our suggested price to Amazon EC2 service. Each request has a state which indicates if our bid won. Initially request has state “open”. Our request’s state becomes “active” in case our bid won and we can see new running instances which are connected to our request with SpotInstanceRequestId property.

Describing Spot requests

A DescribeSpotInstanceRequestsRequest is used to describe our Spot requests state. We can query opened and active Spot requests using filter property. For example, that is how one can query opened Spot requests:

var describeSpotRequestsRequest = new DescribeSpotInstanceRequestsRequest();

describeSpotRequestsRequest.Filter.Add(new Filter(){Name="state", Value="open"});

var openedSpotInstanceRequests = ec2Client.DescribeInstances(describeSpotRequestsRequest);
var openedRequests =
openedSpotInstanceRequests.SpotInstanceRequest;

Running Spot instances

To launch Spot instances we have to send a RequestSpotInstances request and pass our price, maximum desirable Spot instances number and usual launch parameters like image Id, instance type, key pair name, security groups etc. If our price wins AWS will try to launch as many instances as it can limited by our desired maximum number.

var ec2Client = new AmazonEC2Client(accessKey, secretKey);
var spotRequest = new RequestSpotInstancesRequest();

spotRequest.SpotPrice = "2.0";
spotRequest.InstanceCount = maxInstancesCount;
spotRequest.LaunchSpecification = new LaunchSpecification() {ImageID = imageID};

var spotResponse = ec2Client.RequestSpotInstances(spotRequest);
var spotResult = spotResponse.RequestSpotInstancesResult;
var placedSpotRequests = spotResult.SpotInstanceRequest.Select(rq => rq.SpotInstanceRequestId);

Spot request can throw several exceptions, one of which is AmazonEC2Exception with ErrorCode == "MaxSpotInstanceCountExceeded". This exception means we requested more instances than our account allows us to launch.

Requesting Spot instances can fail even not for our fault, but because Amazon is not able to provide us with such number of EC2 instances in our region at the moment. An "InsufficientInstanceCapacity" error code is thrown with AmazonEC2Exception in this case.

Requesting current Spot price

It is useful to know the current price of Spot instances when placing your own bid. AWS SDK has DescribeSpotPriceHistoryRequest for this purposes.

var ec2Client = new AmazonEC2Client(accessKey, secretKey);

var spotPriceHistoryRequest = new DescribeSpotPriceHistoryRequest();
spotPriceHistoryRequest.StartTime = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.000Z");
spotPriceHistoryRequest.EndTime = spotPriceHistoryRequest.StartTime;

var spotPriceHistoryResponse = ec2Client.DescribeSpotPriceHistory(spotPriceHistoryRequest);
var priceHistory = spotPriceHistoryResponse.DescribeSpotPriceHistoryResult.SpotPriceHistory;

var currentPrice = priceHistory.First().SpotPrice;

A note: as it is said in the official documentation: “You can view the Spot Price history over a period from one to 90 days based on the instance type, the operating system you want the instance to run on, the time period, and the Availability Zone in which it will be launched.”

Tagging Spot instances

There is a problem with tagging of Spot instances: we cannot tag them just after start, because we don’t know when they will start. But there is a simple workaround: when we place Spot requests, we can tag them and when actual Spot instances would be launched, we can match each running instance Spot request id and get corresponding tags.

Stopping Spot instances

To stop Spot instances we have to work with SpotInstanceRequest but not with the running Spot instance itself just like when launching Spot instances. CancelSpotInstanceRequestsRequest does the job with SpotInstanceRequest Id-s to stop in parameters.

var ec2Client = new AmazonEC2Client(accessKey, secretKey);

var cancelSpotRequestsRequest = new CancelSpotInstanceRequestsRequest();
cancelSpotRequestsRequest.SpotInstanceRequestId.Add(spotRequestId);

var cancelSpotInstancesResponse = ec2Client.CancelSpotInstanceRequests(cancelSpotRequestsRequest);
var cancelledSpotRequests = cancelSpotInstancesResponse.CancelSpotInstanceRequestsResult.CancelledSpotInstanceRequest.Select(csr => csr.SpotInstanceRequestId);

After the Spot request is cancelled, AWS shuts down the corresponding Spot instance.

Conclusion

Spot instances service from Amazon is interesting, tricky yet powerful. It allows using Amazon unused capacities at a lower price. You can purchase these instances by placing a bid, which you are willing to pay for those instances and for the time your bid is highest, you get them. Spot instances are useful in a number of situations when losing partial work is acceptable like cost-driven workloads or application testing. They help you to save your money when used wisely.

tags

Comments