如何使用 CloudFormation 自动标记根设备卷

How to automate root device volume's tagging using CloudFormation

我无法以任何方式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?谢谢

CloudFormation

这刚刚在 CloudFormation 中发布,可通过 属性

PropagateTagsToVolumeOnCreation

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-propagatetagstovolumeoncreation

用户数据

这可以使用 UserData - if you are running a linux host with cloudinit and the awscli installed, it's possible to run the following in your UserData 脚本来标记与实例关联的所有卷

"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"

确保当您启动 EC2 实例时它有一个实例 IAM 策略,使其能够创建标签和描述卷

"PolicyDocument": {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ec2:CreateTags",
                "ec2:DescribeVolumes"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}

## CloudWatch 事件 另一种自动化方法是通过 CloudWatch Events,设置事件规则侦听和 EC2 状态更改,然后在 Lambda 函数中标记卷,我在下面包含了几个 CloudFormation 片段

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