| « PreviousNext » | |
![]() ![]() | Did this page help you? Yes | No | Tell us about it... |
Spot Instances allow you to bid on unused Amazon Elastic Compute Cloud (Amazon EC2) capacity and run the acquired instances for as long as your bid exceeds the current Spot Price. Amazon EC2 changes the Spot Price periodically based on supply and demand, and customers whose bids meet or exceed it gain access to the available Spot Instances. Like On-Demand Instances and Reserved Instances, Spot Instances provide another option for obtaining more compute capacity.
Spot Instances can significantly lower your Amazon EC2 costs for applications such as batch processing, scientific research, image processing, video encoding, data and web crawling, financial analysis, and testing. Additionally, Spot Instances are an excellent option when you need large amounts of computing capacity but the need for that capacity is not urgent.
To use Spot Instances, place a Spot Instance request specifying the maximum price you are willing to pay per instance hour; this is your bid. If your bid exceeds the current Spot Price, your request is fulfilled and your instances will run until either you choose to terminate them or the Spot Price increases above your bid (whichever is sooner). You can terminate a Spot Instance programmatically as shown in this tutorial or by using the AWS Console.
It's important to note two points:
(1) You will often pay less per hour than your bid. Amazon EC2 adjusts the Spot Price periodically as requests come in and available supply changes. Everyone pays the same Spot Price for that period regardless of whether their bid was higher. Therefore, you might pay less than your bid, but you will never pay more than your bid.
(2) If you're running Spot Instances and your bid no longer meets or exceeds the current Spot Price, your instances will be terminated. This means that you will want to make sure that your workloads and applications are flexible enough to take advantage of this opportunistic—but potentially transient—capacity.
Spot Instances perform exactly like other Amazon EC2 instances while running, and like other Amazon EC2 instances, Spot Instances can be terminated when you no longer need them. If you terminate your instance, you pay for any partial hour used (as you would for On-Demand or Reserved Instances). However, if your instance is terminated by Amazon EC2 because the Spot Price goes above your bid, you will not be charged for any partial hour of usage.
This tutorial provides an overview of how to use the PHP programming environment to do the following.
Submit a Spot Request
Determine when the Spot Request becomes fulfilled
Cancel the Spot Request
Terminate associated instances
This tutorial assumes that you have signed up for AWS, set up your PHP development environment, and installed the AWS SDK for PHP.
To begin using this code sample, you need to populate the config.inc.php file with your credentials, that is, your Access Key ID and your Secret Key.
You can find instructions for adding your credentials to config.inc.php in the Getting Started section of this guide under Configure PHP Environment with Your AWS Security Credentials.
To view your AWS access credentials
Go to the Amazon Web Services website at http://aws.amazon.com.
Click My Account/Console, and then click Security Credentials.
Under Your Account, click Security Credentials.
In the spaces provided, type your user name and password, and then click Sign in using our secure server.
Under Access Credentials, on the Access Keys tab, your access key ID is displayed. To view your secret key, under Secret Access Key, click Show.
A security group acts as a firewall that controls the traffic allowed in and out of a group of instances. By default, an instance is started without any security group, which means that all incoming IP traffic, on any TCP port will be denied. So, before submitting your Spot Request, you will set up a security group that allows the necessary network traffic. For the purposes of this tutorial, we will create a new security group called "GettingStarted" that allows connection using SSH from the IP address of the local computer, that is, the computer where you are running the application.
To set up a new security group, you need to include or run the following code sample that sets up the security group programmatically. You only need to run this code once to create the new security group. However, the code is designed so that it is safe to run even if the security group already exists. In this case, the code catches and ignores the "InvalidGroup.Duplicate" exception.
In the code below, we first use instantiate an AmazonEC2 client object. We then call the create_security_group action with the name, "GettingStarted" and a description for the security group.
// Create the AmazonEC2 object so we can call various APIs.
$ec2 = new AmazonEC2();
// Create a new security group.
$response = $ec2->create_security_group ( 'GettingStartedGroup', 'Getting Started Security Group');
if (!$response->isOK())
{
if (((string) $response->body->Errors->Error->Code) === 'InvalidGroup.Duplicate')
{
// This means that the group is already created, so ignore.
echo 'create_security_group returned an acceptable error: ' . $response->body->Errors->Error->Message . PHP_EOL;
} else {
print_r($response);
exit();
}
}
To enable access to the group, we create an associative array ("$ingress_opt") to store the access configuration. We set the IP address to the CIDR representation of the IP address of the local computer. The "/32" suffix on the IP address indicates that the security group should accept traffic only from the local computer. We also configure the ipPermission object with the TCP protocol and port 22 (SSH). You will need to fill in the IP address of the local computer. If your connection to the Internet is mediated by a firewall or some other type of proxy, you will need to determine the external IP address that is used by the proxy. One technique is to query a search engine such as Google or Bing with the string: "what is my IP address".
// TODO - Change the code below to use your external ip address.
$ip_source = 'XXX.XXX.XXX.XX/32';
// Open up port 22 for TCP traffic to the associated IP
// from above (e.g. ssh traffic).
$ingress_opt = array(
'GroupName' => 'GettingStartedGroup',
'IpPermissions' => array(
array(
'IpProtocol' => 'tcp',
'FromPort' => '22',
'ToPort' => '22',
'IpRanges' => array(
array('CidrIp' => $ip_source),
)
)
)
);
The final step is to call authorize_security_group_ingress with the name of our security group and the configuration array.
// Authorize the ports to be used.
$response = $ec2->authorize_security_group_ingress($ingress_opt);
if (!$response->isOK())
{
if (((string) $response->body->Errors->Error->Code) === 'InvalidPermission.Duplicate')
{
echo 'authorize_security_group_ingress returned an acceptable error: ' . $response->body->Errors->Error->Message . PHP_EOL;
} else {
print_r($response);
exit();
}
}
You can also create the security group using the AWS Toolkit for Eclipse. Go to the toolkit documentation for more information.
To submit a Spot request, you first need to determine the instance type, Amazon Machine Image (AMI), and maximum bid price you want to use. You must also include the security group we configured above, so that you can log into the instance if desired.
There are several instance types to choose from; go to Amazon EC2 Instance Types for a complete list. For this tutorial, we will use t1.micro, the least expensive instance type available. Next, we will determine the type of AMI we would like to use. We'll use ami-31814f58, the most up-to-date Linux AMI available when we wrote this tutorial. The latest AMI may change over time, but you can always determine the latest version AMI by:
Logging into the AWS Management Console, clicking the EC2 tab, and, from the EC2 Console Dashboard, attempting to launch an instance.

In the window that displays AMIs, just use the AMI ID as shown below. Alternatively, you can use the DescribeImages API, but leveraging that command is outside the scope of this tutorial.

There are many ways to approach bidding for Spot instances; to get a broad overview of the various approaches you should view the Bidding for Spot Instances video. However, to get started, we'll describe three common strategies: bid to ensure cost is less than on-demand pricing; bid based on the value of the resulting computation; bid so as to acquire computing capacity as quickly as possible.
Reduce Cost below On-Demand You have a batch processing job that will take a number of hours or days to run. However, you are flexible with respect to when it starts and when it completes. You want to see if you can complete it for less cost than with On-Demand Instances. You examine the Spot Price history for instance types using either the AWS Management Console or the Amazon EC2 API. For more information, go to Viewing Spot Price History. After you've analyzed the price history for your desired instance type in a given Availability Zone, you have two alternative approaches for your bid:
You could bid at the upper end of the range of Spot Prices (which are still below the On-Demand price), anticipating that your one-time Spot request would most likely be fulfilled and run for enough consecutive compute time to complete the job.
Or, you could bid at the lower end of the price range, and plan to combine many instances launched over time through a persistent request. The instances would run long enough--in aggregate--to complete the job at an even lower total cost. (We will explain how to automate this task later in this tutorial.)
Pay No More than the Value of the Result You have a data processing job to run. You understand the value of the job's results well enough to know how much they are worth in terms of computing costs. After you've analyzed the Spot Price history for your instance type, you choose a bid price at which the cost of the computing time is no more than the value of the job's results. You create a persistent bid and allow it to run intermittently as the Spot Price fluctuates at or below your bid.
Acquire Computing Capacity Quickly You have an unanticipated, short-term need for additional capacity that is not available through On-Demand Instances. After you've analyzed the Spot Price history for your instance type, you bid above the highest historical price to provide a high likelihood that your request will be fulfilled quickly and continue computing until it completes.
After you choose your bid price, you are ready to request a Spot Instance. For the purposes of this tutorial, we will set our bid price equal to the On-Demand price ($0.03) to maximize the chances that the bid will be fulfilled. You can determine the types of available instances and the On-Demand prices for instances by going to Amazon EC2 Pricing page.
To request a Spot Instance, you simply need to build your request with the parameters we have specfied so far. We start by creating a associative array ("$spot_opt") to hold the configuration for the instance. The request requires the number of instances you want to start (2) and the bid price ($0.03). Additionally, we need to set the LaunchSpecification for the request, which includes the instance type, AMI ID, and security group you want to use. Once the request is populated, we call the request_spot_instances method on the $ec2 object. An example of how to request a Spot Instance is shown below.
// Setup the specifications of the launch. This includes the
// instance type (e.g. t1.micro) and the latest Amazon Linux
// AMI id available. Note, you should always use the latest
// Amazon Linux AMI id or another of your choosing.
$spot_opt = array(
'InstanceCount' => 2
'LaunchSpecification' => array(
'ImageId' => 'ami-31814f58',
'SecurityGroup' => 'GettingStartedGroup',
'InstanceType' => 't1.micro'
)
);
// Request 1 x t1.micro instance with a bid price of $0.03.
$response = $ec2->request_spot_instances('0.03', $spot_opt);
if (!$response->isOK())
{
print_r($response);
exit();
}
There are other options you can use to configure your Spot Requests. To learn more, visit the request_spot_instances method in the PHP SDK.
Running this code will launch a new Spot Instance Request.
Note
You will be charged for any Spot Instances that are actually launched, so make sure that you cancel any requests and terminate any instances you launch to reduce any associated fees. Code for cancelling requests and terminating instances is show below.
Next, we want to create code to wait until the Spot request reaches the "active" state before proceeding to the last step. To determine the state of our Spot request, we poll the describe_spot_instance_requests method for the state of the Spot request ID we want to monitor.
The request ID created in Step 2 is embedded in the response to our request_spot_instances request. The following example code gathers request IDs from the request_spot_instances response and stores them in an array called $spot_instance_request_ids.
$spot_instance_request_ids = array();
for ($i=0; $i < $response->body->spotInstanceRequestSet->item->count(); $i++)
{
$spot_instance_request_id = (string)$response->body->spotInstanceRequestSet->item[$i]->spotInstanceRequestId;
$spot_instance_request_ids[] = $spot_instance_request_id;
}
To monitor the request IDs, we loop through them calling the describe_spot_instance_requests method to determine the state of each request. We loop until none of the requests are in the "open" state. Note that we monitor for a state of not "open", rather a state of, say, "active", because the request can go straight to "closed" if there is a problem with your request arguments. The code example below provides the details of how to accomplish this task.
// Initialize a variable that will track whether there are any
// requests still in the open state.
$any_open = false;
// Initialize an array to hold any instances we activate so we can terminate them later.
$instance_ids = array();
do {
// Call describe_spot_instance_requests with all of the request ids to
// monitor (e.g. that we started).
$describe_opt = array(
'SpotInstanceRequestId' => $spot_instance_request_ids
);
$response = $ec2->describe_spot_instance_requests($describe_opt);
if (!$response->isOK())
{
print_r($response);
exit();
}
// Reset the any_open variable to false - which assumes there
// are no requests open unless we find one that is still open.
$any_open = false;
// Look through each request and determine if they are all in
// the active state.
foreach ($response->body->spotInstanceRequestSet->item as $item)
{
echo "spotInstanceRequestId = $item->spotInstanceRequestId, state = $item->state" . PHP_EOL;
// If the state is open, it hasn't changed since we attempted
// to request it. There is the potential for it to transition
// almost immediately to closed or cancelled so we compare
// against open instead of active.
if (((string)$item->state) === 'open')
{
$any_open = true;
break;
}
if (((string)$item->state) === 'active')
{
// Get the instanceId once the spot instance request is active
$instance_id = (string)$item->instanceId;
echo 'Instance $instanceId is active.' . PHP_EOL;
// Store the instanceId for any instances we've started so we can terminate them later.
if (!in_array($instanceId, $instanceIds))
{
$instance_ids[] = (string)$item->instanceId;
}
}
}
if ($any_open)
{
echo 'Requests still in open state, will retry in 60 seconds.' . PHP_EOL;
sleep(60);
}
}
while($any_open);
If you just ran the code up to this point, your, your Spot Instance Request would complete—or possibly fail with an error. For the purposes of this tutorial, we'll add some code that cleans up after all of the requests have transitioned out of the open state.
The final step is to clean up our requests and instances. It is important to both cancel any outstanding requests and terminate any instances. Just canceling your requests will not terminate your instances, which means that you will continue to pay for them. If you terminate your instances, your Spot requests may be canceled, but there are some scenarios--such as if you use persistent bids--where terminating your instances is not sufficient to stop your request from being re-fulfilled. Therefore, it is a best practice to both cancel any active bids and terminate any running instances.
The following code demonstrates how to cancel your requests.
$response = $ec2->cancel_spot_instance_requests($spot_instance_request_ids);
if ($response->isOK())
{
echo 'Canceled spot instance requests.' . PHP_EOL;
} else {
print_r($response);
exit();
}
To terminate any outstanding instances, we use the instance_ids array, which we populated with the instance IDs of those instances that transitioned to the active state. We terminate these instances by paste this array to the terminate_instances method.
if (count($instance_ids) > 0)
{
$response = $ec2->terminate_instances($instanceIds);
if ($response->isOK())
{
echo 'Terminated requested spot instances.' . PHP_EOL;
} else {
print_r($response);
exit();
}
}
Congratulations! You have just completed the getting started tutorial for developing Spot Instance software with the AWS SDK for PHP.