Launch new EC2 instance with a specified EBS volume attached

It's not possible to launch a new EC2 instance with an existing EBS volume attached.

Instead, attach your existing EBS volume after the new EC2 instance has launched. You have two options:

  1. Attach your existing EBS volume during the initial boot sequence of your instance. Using cloud init, you have an initial script run that attaches the volume.

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html

  1. After you launch your new EC2 instance, wait for it to finish launching, then attach the existing EBS volume from within your Python script.

Edit: Added more details based on comments.

All the various language SDKs call the base AWS API. Look at the base AWS API documentation for RunInstances:

http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html

On that command, there is a BlockDeviceMappingparameter such that if you follow it's data structure, does not include a volume ID property.

I'm not familiar with the Python SDK, but it's possible that the SDK is overloading the BlockDeviceMapping class to represent both a specification for launch (which does not permit volume ID) and a mapping for a running instance (which can include a volume ID).

I usually work with the AWS SDK for .NET and I rarely refer to the documentation specific for that. I usually refer to the base API docs (like I referenced above), then I "find" the appropriate methods to use in the .NET SDK. But I take the base API docs as correct if there is a discrepancy.


Unlike Matt says, it is perfectly possible to attach existing EBS volumes to AMI during its creation.

Firstly you should have the snapshot of your volume, it can be done both through console and aws-cli.

Then you create AMI based on this EBS snapshot:

#!/bin/bash

aws --region=sa-east-1 ec2 \
register-image \
--name "image" \
--description "new_image" \
--architecture x86_64 \
--kernel-id aki-912fbcfd \
--root-device-name "/dev/xvda" \
--block-device-mappings "[
{
 \"DeviceName\": \"/dev/xvda\",
 \"Ebs\": {
 \"SnapshotId\": \"snap-0dfgkhdfjkhg77\",
 \"DeleteOnTermination\": false
  }
}
]"

Then you start the instance based on the above AMI. Here I drop the sample of creating spot-instance, but creating On-Demand instance is even simpler:

#!/bin/bash
AWS_DEFAULT_OUTPUT="text"
ami="ami-xxxxxxx"
price="0.0022"
region="sa-east-1"
sgroup="sg-54654765"
zone="sa-east-1b"
key="key"

aws ec2 request-spot-instances  \
    --region $region \
    --spot-price $price  \
    --type "persistent" \
    --instance-interruption-behavior "stop" \
    --launch-specification \
    "{ \"KeyName\": \"$key\", 
       \"ImageId\": \"$ami\" , 
       \"InstanceType\": \"t1.micro\"
     }"

All this is easily scriptable and programmable.