如何标记通过 CloudFormation 创建的实例的根卷?
我想标记通过 AWS CloudFormation 创建的 Amazon Elastic Compute Cloud(Amazon EC2)实例的根卷。
简短描述
EC2 实例资源的标签属性不会扩展到通过 CloudFormation 创建的卷中。标记可能会限制您对实例的控制。标记可帮助您管理特定资源的成本并限制 AWS Identity and Access Management(IAM)策略。标记还可帮助您对其他资源进行类似控制。
通过 CloudFormation 进行引导,您可以标记实例的 Amazon Elastic Block Store(Amazon EBS)根卷。引导方法通过 AWS::EC2::Instance 资源的 UserData 属性来实现。要执行引导,请在创建实例后使用 AWS 命令行界面(AWS CLI)命令或标准 Windows PowerShell 命令。
**注意:**如果在运行 AWS CLI 命令时收到错误,请确保您使用的是最新的 AWS CLI 版本。
解决方法
使用 CloudFormation 模板创建实例
1. 打开 CloudFormation 控制台。
2. 依次选择创建堆栈和设计模板。
3. 在代码编辑器的参数选项卡中,选择模板。
4. 对于选择模板语言,选择 YAML。
5. 复制以下 JSON 模板或 YAML 模板,然后将复制的模板粘贴到代码编辑器中。
JSON 模板:
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "AWS CloudFormation Sample Template Tagging Root Volumes of EC2 Instances: This template shows you how to automatically tag the root volume of the EC2 instances that are created through the AWS CloudFormation template. This is done through the UserData property of the AWS::EC2::Instance resource. **WARNING** This template creates two Amazon EC2 instances and an IAM role. You will be billed for the AWS resources used if you create a stack from this template.", "Parameters": { "KeyName": { "Type": "AWS::EC2::KeyPair::KeyName", "Description": "Name of an existing EC2 KeyPair to enable SSH access to the ECS instances." }, "InstanceType": { "Description": "EC2 instance type", "Type": "String", "Default": "t2.micro", "AllowedValues": [ "t2.micro", "t2.small", "t2.medium", "t2.large", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "m4.large", "m4.xlarge", "m4.2xlarge", "m4.4xlarge", "m4.10xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge" ], "ConstraintDescription": "Please choose a valid instance type." }, "InstanceAZ": { "Description": "EC2 AZ.", "Type": "AWS::EC2::AvailabilityZone::Name", "ConstraintDescription": "Must be the name of an Availability Zone." }, "WindowsAMIID": { "Description": "The Latest Windows 2016 AMI taken from the public Systems Manager Parameter Store", "Type": "AWS::SSM::Parameter::Value<String>", "Default": "/aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base" }, "LinuxAMIID": { "Description": "The Latest Amazon Linux 2 AMI taken from the public Systems Manager Parameter Store", "Type": "AWS::SSM::Parameter::Value<String>", "Default": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" } }, "Resources": { "WindowsInstance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": { "Ref": "WindowsAMIID" }, "InstanceType": { "Ref": "InstanceType" }, "AvailabilityZone": { "Ref": "InstanceAZ" }, "IamInstanceProfile": { "Ref": "InstanceProfile" }, "KeyName": { "Ref": "KeyName" }, "UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "<powershell>\n", "try {\n", "$AWS_AVAIL_ZONE=(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/placement/availability-zone' -UseBasicParsing).Content\n ", "$AWS_REGION=$AWS_AVAIL_ZONE.Substring(0,$AWS_AVAIL_ZONE.length-1)\n ", "$AWS_INSTANCE_ID=(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/instance-id' -UseBasicParsing).Content\n ", "$ROOT_VOLUME_IDS=((Get-EC2Instance -Region $AWS_REGION -InstanceId $AWS_INSTANCE_ID).Instances.BlockDeviceMappings | where-object DeviceName -match '/dev/sda1').Ebs.VolumeId\n ", "$tag = New-Object Amazon.EC2.Model.Tag\n ", "$tag.key = \"MyRootTag\"\n ", "$tag.value = \"MyRootVolumesValue\"\n ", "New-EC2Tag -Resource $ROOT_VOLUME_IDS -Region $AWS_REGION -Tag $tag\n", "}\n", "catch {\n", "Write-Output $PSItem\n", "}\n", "</powershell>\n" ] ] } }, "Tags": [ { "Key": "Name", "Value": { "Ref": "AWS::StackName" } } ], "BlockDeviceMappings": [ { "DeviceName": "/dev/sdm", "Ebs": { "VolumeType": "io1", "Iops": "200", "DeleteOnTermination": "true", "VolumeSize": "10" } } ] } }, "LinuxInstance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": { "Ref": "LinuxAMIID" }, "InstanceType": { "Ref": "InstanceType" }, "AvailabilityZone": { "Ref": "InstanceAZ" }, "IamInstanceProfile": { "Ref": "InstanceProfile" }, "KeyName": { "Ref": "KeyName" }, "UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "#!/bin/sh\n", "AWS_AVAIL_ZONE=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone)\n", "AWS_REGION=${AWS_AVAIL_ZONE::-1}\n", "AWS_INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id)\n", "ROOT_VOLUME_IDS=$(aws ec2 describe-instances --region $AWS_REGION --instance-id $AWS_INSTANCE_ID --output text --query Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId)\n", "aws ec2 create-tags --resources $ROOT_VOLUME_IDS --region $AWS_REGION --tags Key=MyRootTag,Value=MyRootVolumesValue\n" ] ] } }, "Tags": [ { "Key": "Name", "Value": { "Ref": "AWS::StackName" } } ], "BlockDeviceMappings": [ { "DeviceName": "/dev/sdm", "Ebs": { "VolumeType": "io1", "Iops": "200", "DeleteOnTermination": "true", "VolumeSize": "10" } } ] } }, "InstanceRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "ec2.amazonaws.com" ] }, "Action": [ "sts:AssumeRole" ] } ] }, "Path": "/", "Policies": [ { "PolicyName": "taginstancepolicy", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:Describe*" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ec2:CreateTags" ], "Resource": [ { "Fn::Sub": "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:volume/*" }, { "Fn::Sub": "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:instance/*" } ] } ] } } ] } }, "InstanceProfile": { "Type": "AWS::IAM::InstanceProfile", "Properties": { "Path": "/", "Roles": [ { "Ref": "InstanceRole" } ] } } } }
YAML 模板:
AWSTemplateFormatVersion: 2010-09-09 Description: >- AWS CloudFormation Sample Template Tagging Root Volumes of EC2 Instances: This template shows you how to automatically tag the root volume of the EC2 instances that are created through the AWS CloudFormation template. This is done through the UserData property of the AWS::EC2::Instance resource. **WARNING** This template creates two Amazon EC2 instances and an IAM role. You will be billed for the AWS resources used if you create a stack from this template. Parameters: KeyName: Type: 'AWS::EC2::KeyPair::KeyName' Description: Name of an existing EC2 KeyPair to enable SSH access to the ECS instances. InstanceType: Description: EC2 instance type Type: String Default: t2.micro AllowedValues: - t2.micro - t2.small - t2.medium - t2.large - m3.medium - m3.large - m3.xlarge - m3.2xlarge - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m4.10xlarge - c4.large - c4.xlarge - c4.2xlarge - c4.4xlarge - c4.8xlarge - c3.large - c3.xlarge - c3.2xlarge - c3.4xlarge - c3.8xlarge - r3.large - r3.xlarge - r3.2xlarge - r3.4xlarge - r3.8xlarge - i2.xlarge - i2.2xlarge - i2.4xlarge - i2.8xlarge ConstraintDescription: Please choose a valid instance type. InstanceAZ: Description: EC2 AZ. Type: 'AWS::EC2::AvailabilityZone::Name' ConstraintDescription: Must be the name of an Availability Zone. WindowsAMIID: Description: >- The Latest Windows 2016 AMI taken from the public Systems Manager Parameter Store Type: 'AWS::SSM::Parameter::Value<String>' Default: /aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base LinuxAMIID: Description: >- The Latest Amazon Linux 2 AMI taken from the public Systems Manager Parameter Store Type: 'AWS::SSM::Parameter::Value<String>' Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 Resources: WindowsInstance: Type: 'AWS::EC2::Instance' Properties: ImageId: !Ref WindowsAMIID InstanceType: !Ref InstanceType AvailabilityZone: !Ref InstanceAZ IamInstanceProfile: !Ref InstanceProfile KeyName: !Ref KeyName UserData: !Base64 'Fn::Join': - '' - - | <powershell> - | try { - >- $AWS_AVAIL_ZONE=(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/placement/availability-zone' -UseBasicParsing).Content - |- $AWS_REGION=$AWS_AVAIL_ZONE.Substring(0,$AWS_AVAIL_ZONE.length-1) - >- $AWS_INSTANCE_ID=(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/instance-id' -UseBasicParsing).Content - >- $ROOT_VOLUME_IDS=((Get-EC2Instance -Region $AWS_REGION -InstanceId $AWS_INSTANCE_ID).Instances.BlockDeviceMappings | where-object DeviceName -match '/dev/sda1').Ebs.VolumeId - |- $tag = New-Object Amazon.EC2.Model.Tag - |- $tag.key = "MyRootTag" - |- $tag.value = "MyRootVolumesValue" - > New-EC2Tag -Resource $ROOT_VOLUME_IDS -Region $AWS_REGION -Tag $tag - | } - | catch { - | Write-Output $PSItem - | } - | </powershell> Tags: - Key: Name Value: !Ref 'AWS::StackName' BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: VolumeType: io1 Iops: '200' DeleteOnTermination: 'true' VolumeSize: '10' LinuxInstance: Type: 'AWS::EC2::Instance' Properties: ImageId: !Ref LinuxAMIID InstanceType: !Ref InstanceType AvailabilityZone: !Ref InstanceAZ IamInstanceProfile: !Ref InstanceProfile KeyName: !Ref KeyName UserData: !Base64 'Fn::Join': - '' - - | #!/bin/sh - > AWS_AVAIL_ZONE=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone) - | AWS_REGION=${AWS_AVAIL_ZONE::-1} - > AWS_INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id) - > ROOT_VOLUME_IDS=$(aws ec2 describe-instances --region $AWS_REGION --instance-id $AWS_INSTANCE_ID --output text --query Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId) - > aws ec2 create-tags --resources $ROOT_VOLUME_IDS --region $AWS_REGION --tags Key=MyRootTag,Value=MyRootVolumesValue Tags: - Key: Name Value: !Ref 'AWS::StackName' BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: VolumeType: io1 Iops: '200' DeleteOnTermination: 'true' VolumeSize: '10' InstanceRole: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - 'sts:AssumeRole' Path: / Policies: - PolicyName: taginstancepolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'ec2:Describe*' Resource: '*' - Effect: Allow Action: - 'ec2:CreateTags' Resource: - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:volume/*' - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' InstanceProfile: Type: 'AWS::IAM::InstanceProfile' Properties: Path: / Roles: - !Ref InstanceRole
6. I在模板的 UserData 部分中,更新 --tags Key=Name,Value=newAMI 以匹配您对 Linux 实例的要求。对于 Windows 实例,更新 $tag.key="MyRootTag" 和 $tag.value="MyRootVolumesValue"。请参阅 Linux 和 Windows 的以下 UserData 部分示例。
Linux 示例:
#Linux UserData UserData: Fn::Base64: !Sub | #!/bin/bash AWS_AVAIL_ZONE=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone) AWS_REGION="`echo \"$AWS_AVAIL_ZONE\" | sed 's/[a-z]$//'`" AWS_INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id) ROOT_VOLUME_IDS=$(aws ec2 describe-instances --region $AWS_REGION --instance-id $AWS_INSTANCE_ID --output text --query Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId) aws ec2 create-tags --resources $ROOT_VOLUME_IDS --region $AWS_REGION --tags Key=MyRootTag,Value=MyRootVolumesValue
Windows 示例:
#Windows UserData with standard Powershell commands (no AWS CLI installed) UserData: Fn::Base64: !Sub | <powershell> try { $AWS_AVAIL_ZONE=(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/placement/availability-zone' -UseBasicParsing).Content $AWS_REGION=$AWS_AVAIL_ZONE.Substring(0,$AWS_AVAIL_ZONE.length-1) $AWS_INSTANCE_ID=(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/instance-id' -UseBasicParsing).Content $ROOT_VOLUME_IDS=((Get-EC2Instance -Region $AWS_REGION -InstanceId $AWS_INSTANCE_ID).Instances.BlockDeviceMappings | where-object DeviceName -match '/dev/sda1').Ebs.VolumeId $tag = New-Object Amazon.EC2.Model.Tag $tag.key = "MyRootTag" $tag.value = "MyRootVolumesValue" New-EC2Tag -Resource $ROOT_VOLUME_IDS -Region $AWS_REGION -Tag $tag } catch { Write-Output $PSItem } </powershell>
**重要事项:**要对 UserData 使用 AWS CLI 命令,必须在 EC2 实例的亚马逊云机器镜像(AMI)中安装 AWS CLI。默认情况下,AWS CLI 安装在所有 Amazon Linux AMI 中。您还必须将实例配置文件附加到 EC2 实例。实例配置文件仅包含对 AWS 区域和账户内的 EC2 卷和实例调用 ec2:DescribeInstances 和 ec2:CreateTags API 的权限。
7. 选择创建堆栈图标。
8. 对于堆栈名称,输入堆栈的名称。
9. 在参数部分中,根据环境的需求输入相应的信息,包括实例类型、EC2 密钥对和 AMI。
10. 选择下一步。
11. 在选项部分中,输入堆栈的相应信息,然后选择下一步。
12. 要启用 CloudFormation 堆栈以创建 IAM 资源,请选中“我确认 AWS CloudFormation 可能会创建 IAM 资源”复选框。
13. 选择创建。
标记实例的根卷
1. 打开 Amazon EC2 控制台。
2. 在导航窗格的 Elastic Block Store 部分中,选择卷。
3. 在筛选器字段中,输入您在 CloudFormation 堆栈中设置的标签,以确认已标记卷。
相关内容
- AWS 官方已更新 4 个月前
- AWS 官方已更新 10 个月前
- AWS 官方已更新 10 个月前