如何通过 CloudFormation 设置 EC2 实例根卷的标签

Posted

技术标签:

【中文标题】如何通过 CloudFormation 设置 EC2 实例根卷的标签【英文标题】:How to set tags of the root volume of EC2 instance via CloudFormation 【发布时间】:2018-05-10 00:43:10 【问题描述】:

使用 CloudFormation 创建 EC2 实例,但根卷的名称(标签)为空。如何使用 CloudFormation 进行设置?

# ec2-instance.yml (CloudFormation template)
MyInstance:
  Type: "AWS::EC2::Instance"
  Properties:
    ImageId: "ami-da9e2cbc"
    InstanceType: "t2.nano"
    KeyName: !Ref "KeyPair"
    Tags: # This is for EC2 instance (not root volume)
      - Key: "Name"
        Value: "my-instance"

我找到了“Volumes”和“BlockDeviceMappings”属性,但找不到。

【问题讨论】:

【参考方案1】:

我知道 EC2 RunInstances 现在支持标记 EBS volumes on launch,但我不确定 CloudFormation 是否支持。

其他人在 CloudFormation 中有 requested this feature。另见this thread。

在 CloudFormation 支持此功能之前,您可能需要查看 graffiti-monkey,它查看 EC2 实例具有的标签,将这些标签复制到附加到该实例的 EBS 卷,然后复制这些标签到 EBS 快照。 (我还没有验证它是否将标签传播到根设备卷,但假设它确实如此。)

【讨论】:

哦...请求的日期是 5 年前 :( 我会尝试寻找其他标记方式。谢谢! 有人找到解决方案了吗?我有一个根卷和一个辅助 EBS 卷,它们会自动附加到实例(由于自定义 AMI)。现在我想用与 EC2 相同的标签来标记两个 EBS。【参考方案2】:

CloudFormation 目前似乎不支持此功能。但是使用实例user data script,您可以这样做来标记根卷:

apt-get -y install unzip
unzip awscli-bundle.zip
./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws    
rm -rf  awscli-bundle awscli-bundle.zip
EC2_INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
EC2_REGION=$EC2_AVAIL_ZONE:0:$#EC2_AVAIL_ZONE - 1
ROOT_DISK_ID=$(aws ec2 describe-volumes --filters Name=attachment.instance-id,Values=EC2_INSTANCE_ID Name=attachment.device,Values=/dev/sda1 --query 'Volumes[*].[VolumeId]' --region=$EC2_REGION --out \"text\" | cut -f 1)
aws ec2 create-tags --resources $ROOT_DISK_ID --tags Key=Name,Value=\"Root Volume my-instance\" --region $EC2_REGION

此脚本将使用 Name=Root Volume my-instance 标记 /dev/sda1 EBS 卷

请注意,对于我的 Ubuntu AMI,我必须先安装 AWS 工具。 Amazon Linux AMI 已安装这些工具。

对于 CloudFormation,您可以使用:

# ec2-instance.yml (CloudFormation template)
MyInstance:
  Type: "AWS::EC2::Instance"
  Properties:
    ImageId: "ami-da9e2cbc"
    InstanceType: "t2.nano"
    KeyName: !Ref "KeyPair"
    UserData:
      "Fn::Base64": !Sub |
       #!/bin/bash -x
       apt-get -y install unzip
       unzip awscli-bundle.zip
       ./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws    
       rm -rf  awscli-bundle awscli-bundle.zip
       EC2_INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
       EC2_REGION=$EC2_AVAIL_ZONE:0:$#EC2_AVAIL_ZONE - 1
       ROOT_DISK_ID=$(aws ec2 describe-volumes --filters Name=attachment.instance-id,Values=EC2_INSTANCE_ID Name=attachment.device,Values=/dev/sda1 --query 'Volumes[*].[VolumeId]' --region=$EC2_REGION --out \"text\" | cut -f 1)
       aws ec2 create-tags --resources $ROOT_DISK_ID --tags Key=Name,Value=\"Root Volume my-instance\" --region $EC2_REGION

【讨论】:

这太丑了!我采用使用UserData 属性及其脚本或放弃...谢谢! 是的,这些用户数据脚本看起来很脏;-)。但是您可以通过 CLI 轻松完成任何您需要的操作。 如果您无法承受重启实例的费用,请不要接触用户数据。改用脚本【参考方案3】:

UserData下有一些语法错误

查看下面的代码,使其工作

# Download and install AWS CLI
apt-get -y install unzip
curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip"
unzip awscli-bundle.zip
./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws  
rm -rf awscli-bundle awscli-bundle.zip
EC2_INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
EC2_AVAIL_ZONE=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
VOLUME_ID=$(aws ec2 describe-volumes --filters Name=attachment.instance-id,Values=$EC2_INSTANCE_ID Name=attachment.device,Values=/dev/sda1 --query 'Volumes[*].[VolumeId]' --region $AWS::Region --out text | cut -f 1)
aws ec2 create-tags --resources $VOLUME_ID --tags Key=Name,Value=\"Root Volume my-instance\" --region $AWS::Region

【讨论】:

以上是关于如何通过 CloudFormation 设置 EC2 实例根卷的标签的主要内容,如果未能解决你的问题,请参考以下文章

EC2 终止时启动 CloudFormation 创建堆栈

如何修复与 AWS::CloudFormation::Init 一起创建 EC2 的 cloudformation 模板

AWS Cloudformation - Helper Scripts

如何使用 CloudFormation 在现有 EC2 实例上启动容器?

无法使用 CloudFormation 模板通过 SSH 连接到 EC2 实例

Cloudformation 模板 - 如何确保 EC2 实例启动后特定服务正在运行