I recently had a task where I needed to quickly start up 50 spot instances that all required an Elastic IP (EIP) address. I initially worked out the steps in the web console and determined I needed to accomplish the following:
- Request 50 spot instances based on an existing AMI
- Allocate 50 new EIPs
- Associate each EIP with one of the newly running spot instances.
Requesting 50 spot instances from the web console was quick and painless. However, the EIP allocation and association quickly become tiresome. As the Amazon web console only allows allocating and associating 1 EIP at a time. To repeat the following steps 50 times did not seem like a good use of time: requesting a new EIP, determining the appropriate instance ID to associate with the EIP and then assigning the EIP
Instead I decided to quickly put together a few commands to achieve the goal using the AWS API. First I issued a request for 50 instances with a command like the following
ec2-request-spot-instances ami-1d2b34e5 --price .15 -n50 -s subnet-c1f234ae -t m2.4xlarge --kernel aki-88aa75e1
Of course the above command will need to be modified for each specific case. The specific AMI ID, max bid price, number of instances, subnet, instance type and kernel will all need their respective values modified.
Then I waited until all of the instances were running with a command like the following:
ec2-describe-instances --filter "instance-state-code=16" | grep 'spot' | grep -E '10\.0\.1\.[0-9]{1,3}\s+vpc' | wc -l
The above command lists all of the running instances (instance-stat-code=16), limits it to only spot instances and then limits the output to a specific VPC that has an internal address in the 10.0.1.* range.
Once the above command displayed 50 I was ready to start allocating and associating IP addresses. I accomplished this with a combinations of commands. I needed to use ec2-allocate-address to request a new EIP and ec2-describe-instances to get a list of instances that need an EIP. Last, ec2-associate-address needed to be used to associate the new EIP with a specific instance ID. The command to accomplish this looked like the following:
for((i=0;i<50;i++)); do ec2-associate-address -a `ec2-allocate-address -d vpc | cut -f5` -i `ec2-describe-instances --filter "instance-state-code=16" | grep 'spot' | grep -E 'monitoring-[a-Z]+\s+10\.0\.1' | cut -f2 | head -n1`; done
The above runs the ec2-associate-address command 50 times. It then runs two sub commands one which requests a new EIP address in the vpc (ec2-allocate-address -d vpc) and one which gets the next running spot instance that does not have an EIP (ec2-describe-instances –filter “instance-state-code=16″…).
Last, the new EIPs can be listed with a command like the following:
ec2-describe-instances | grep 'spot' | cut -f17
This worked beautifully for my goal of quickly firing up 50 spot instances and assigning an EIP address. As always, there is room for improvement. If automating something like this on a regular basis, I would suggest taking the one line command and doing more validation on the output of each command. The above assumes that everything is in a good state and that no issues occur in requesting or assigning the EIPs.
Let me know if you find this useful!