How do you tag and name the EC2 Instance that was launched by an EC2 Spot Request?

I have a couple of EC2 Spot Requests that launch EC2 Instances when the price is right. I'd like the resulting instances to get tagged with a Name and Role tag so my configuration management tool knows what type of machine it is.

UPDATE:

I took Hyper Anthony's advice and implemented it -- because polling was going to be error-prone and resource-intensive I added a startup script to my AMI which updates the tags when an instance launches, these are the steps I took:

Ensure Boto is installed on whatever AMI you're using

pip install boto

Assign an IAM Role to the EC2 Instance

The instance you're launching must have some way to access information about the spot request. Use an IAM role or alternatively make access keys available to your instance. The policy that I attached to the IAM role that I used is:

{
    "Statement": [
        {
            "Action": [
                "ec2:CreateTags",
                "ec2:DescribeTags",
                "ec2:DescribeInstances"
            ],
            "Effect": "Allow",
            "Resource": [
                "*"
            ],
            "Sid": "Stmt1432737176000"
        }
    ],
    "Version": "2012-10-17"
}

Run a script on startup to update the tags

def get_tags_from_spot_request():

    instance_id = boto.utils.get_instance_identity()['document']['instanceId']
    region = boto.utils.get_instance_identity()['document']['region']
    conn = boto.ec2.connect_to_region(region)
    inst = boto.ec2.instance.Instance(connection=conn)
    inst.id = instance_id
    inst.update()
    spot_id = inst.spot_instance_request_id
    tags = conn.get_all_tags(filters={'resource-type': 'spot-instances-request', 'resource-id': spot_id})
    for tag in tags:
        inst.add_tag(tag.name, tag.value)

Spot instances requests are a type of EC2 resource. The AWS documentation notes that this type of resource can be tagged, but the resulting tags are not carried over to the actual instances:

The tags that you create for your Spot Instance requests only apply to the requests. These tags are not added automatically to the Spot Instance that the Spot service launches to fulfill the request. You must add tags to a Spot Instance yourself when you create the Spot Instance request or after the Spot Instance is launched.

So you'll need to add the tags after the instances have launched. You have some options here:

  • User Data Script on the created instance: Write a user data script that uses command line tools and the EC2 meta data service to allow the instance to discover its instance Id and create tags for itself. You can use the AWS CLI create-tags to tag any of your EC2 resources. Alternatively, you could bake this into the AMI as a startup script for whatever OS you intend to use. In either situation, the instance will have to have sufficient permissions to create EC2 tags for itself.
  • External Utility that monitors your spot request: You can use one of the AWS SDKs to monitor your spot request and tag the instances once they have been created. AWS has a tutorial on this very topic under the "How to Tag Your Spot Requests and Instances" header. Without getting too verbose, this simply involves polling Describe Spot Instance Requests until a created Instance Id is available, and then calling Create Tags.

You can now supply tags to your SpotFleetLaunchSpecification when creating a spot fleet request, and those tags will be applied to new instances in that fleet automatically.

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


Another possibility is to use Ansible as your configuration management tool. In the ec2 module, which allows you to fire up both spot and normal lifecycle instances, you can add the "instance_tags" attributes to create the tags. A simple playbook would be:


  - name: Provision Spot Instance
    hosts: localhost
    connection: local
    gather_facts: False
    tasks:
      - name: Launch the new Spot Instance
        local_action:
          module: ec2
          spot_price: 0.02
          group: testSG
          instance_type: m3.medium
          image: ami-12345
          wait: true
          instance_tags:
            Name: TagValueForName
            Foo: TagValueForFoo
          region: us-east-1
          keypair: mykeypair

Interestingly enough, my complaint is that it only tags the instance and doesn't tag the spot request, the opposite of your issue.