Reputation: 812
I am not able to tag the root device volume attached to EC2 using CloudFormation's block device mapping because tags are not propagated to Amazon EBS volumes that are created from block device mappings. Can root device volume's tagging be automated using Cloudformation in any way? Thanks.
Upvotes: 10
Views: 2332
Reputation: 1039
This has just shipped in CloudFormation settable via the property
PropagateTagsToVolumeOnCreation
This is possible to do using UserData - if you are running a linux host with cloudinit and the awscli installed, it's possible to run the following in your UserData script to tag all the volumes associate with an Instance
"VOLUME_IDS=$(aws ec2 describe-volumes --output text --filters Name=attachment.instance-id,Values=$(curl http://169.254.169.254/latest/meta-data/instance-id) --query 'Volumes[].VolumeId')",
"aws ec2 create-tags --resources ${VOLUME_IDS} --tags Key=my,Value=tag"
ensure that when you launch your EC2 Instance it has an Instance IAM Policy that enables it to create tags and describe volumes
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:CreateTags",
"ec2:DescribeVolumes"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
## CloudWatch Events Another way to automate this is via CloudWatch Events, set up an Events rule listening for and EC2 State Change, then tag The volumes in a Lambda function, I've included a couple of CloudFormation snippets below
LambdaEC2CopyTagsToEBS:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: LambdaEC2CopyTagsToEBS
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- ec2:DescribeInstances
- ec2:CreateTags
Resource: '*'
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: '*'
LambdaEC2CopyTagsToEBSEvent:
Type: AWS::Events::Rule
Properties:
Description: Invokes CopyInstanceTagsToEBSVolumes when an Instance starts running
EventPattern:
source:
- aws.ec2
detail-type:
- EC2 Instance State-change Notification
detail:
state:
- running
State: ENABLED
Targets:
- Arn: !GetAtt CopyInstanceTagsToEBSVolumes.Arn
Id: !Ref CopyInstanceTagsToEBSVolumes
CopyInstanceTagsToEBSVolumes:
Type: AWS::Lambda::Function
Properties:
Description: Copies Tags from and EC2 to all its EBS Volumes
Code:
ZipFile: |
import boto3
ec2 = boto3.client('ec2')
def get_volume_ids(instance):
for device in instance.get('BlockDeviceMappings', []):
yield device.get('Ebs', {}).get('VolumeId')
def handler(event, context):
state, instance_id = event['detail']['state'], event['detail']['instance-id']
if state == 'running':
instance = ec2.describe_instances(InstanceIds=[instance_id])
instance = instance['Reservations'][0]['Instances'][0]
volume_ids = get_volume_ids(instance)
tags = [tag for tag in instance['Tags'] if not tag['Key'].startswith('aws:')]
ec2.create_tags(Resources=list(volume_ids),
Tags=tags
)
Handler: index.handler
Role: !GetAtt LambdaEC2CopyTagsToEBS.Arn
Runtime: python3.6
Timeout: 5
EventsInvokeCopyInstanceTagsToEBSVolumes:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref CopyInstanceTagsToEBSVolumes
Principal: events.amazonaws.com
SourceArn: !GetAtt LambdaEC2CopyTagsToEBSEvent.Arn
Upvotes: 9