【问题标题】:Is there a way to tag a root volume when initializing from the cloudformation template?从 cloudformation 模板初始化时,有没有办法标记根卷?
【发布时间】:2014-07-24 10:52:55
【问题描述】:

我正在通过云形成脚本创建一个实例。

我发现附加操作系统分区的唯一方法是通过“BlockDeviceMappings”属性。 (我之前尝试过使用“Volumes”属性,但是实例无法挂载,系统告诉我/dev/sda已经映射并回滚了实例创建)

这是我的模板的相关部分:

  "Resources" :
  {
    "Ec2Instance" :
    {
      "Type" : "AWS::EC2::Instance",
      "Properties" :
      {
        "BlockDeviceMappings" :
        [{
          "DeviceName" : "/dev/sda",
          "Ebs" :
          {
            "VolumeSize" : { "Ref" : "RootVolumeSize" },
            "SnapshotId" :
            { "Fn::FindInMap" : [ "RegionMap",
              { "Ref" : "AWS::Region" }, "RootVolumeSnapshotId" ]
            }
          }
        }],
        ...
       }
     }

我的问题是,如何使用“BlockDeviceMappings”属性标记我在这里创建的 Ebs 卷?我没有找到明显的解决方案。

谢谢。

【问题讨论】:

标签: amazon-web-services amazon-ec2 amazon-cloudformation


【解决方案1】:

能够通过 AWS CLI 界面、IAM 角色和 UserData 初始化使其工作。

将此添加到AWS::EC2::Instance:Properties:UserData

{ "Fn::Base64" : { "Fn::Join" : [ "\n", [
  "#!/bin/bash",
  "set -eux",
  "exec > >(tee /tmp/user-data.log | logger -t user-data -s 2>/dev/console) 2>&1",
  { "Fn::Join" : [ "", [
    "AWS_STACK_NAME='", { "Ref" : "AWS::StackName" }, "'"
  ]]},
  { "Fn::Join" : [ "", [
    "AWS_ROOT_VOLUME_SNAPSHOT_ID='",
      { "Fn::FindInMap" :
         [ "RegionMap", { "Ref" : "AWS::Region" }, "RootVolumeSnapshotId" ]},
      "'"
  ]]},
  "AWS_INSTANCE_ID=$( curl http://169.254.169.254/latest/meta-data/instance-id )",
  "",
  "AWS_HOME=/opt/aws",
  "AWS_BIN_DIR=\"${AWS_HOME}/bin\"",
  "export EC2_HOME=\"${AWS_HOME}/apitools/ec2\"",
  "export JAVA_HOME=/etc/alternatives/jre_1.7.0",
  "",
  "ROOT_DISK_ID=$(",
  "    \"${AWS_BIN_DIR}/ec2-describe-volumes\" \\",
  "        --filter \"attachment.instance-id=${AWS_INSTANCE_ID}\" \\",
  "        --show-empty-fields \\",
  "      | grep '^VOLUME' \\",
  "      | awk '{printf \"%s,%s\\n\", $4, $2}' \\",
  "      | grep '^${AWS_ROOT_VOLUME_SNAPSHOT_ID}' \\",
  "      | cut --delimiter=, --fields=2",
  "    exit ${PIPESTATUS[0]}",
  "  )",
  "\"${AWS_BIN_DIR}/ec2-create-tags \\",
  "  \"${ROOT_DISK_ID}\" \\",
  "  --tag \"Name=${AWS_STACK_NAME}-root\"",
  ""
]]}}

还必须添加对可以描述卷和创建标签的 IAM 角色的引用。

将此添加到“资源”部分:

"InstanceProfile" :
{
  "Type" : "AWS::IAM::InstanceProfile",
  "Properties" :
  {
    "Path" : "/",
    "Roles" : [ "ec2-tag-instance" ]
  }
}

Instance 资源中引用了此配置文件:

"Ec2Instance" :
{
  "Type" : "AWS::EC2::Instance",
  "Properties" :
  {
    ...
    "IamInstanceProfile" : {"Ref" : "InstanceProfile"},
    ...
  }
}

IAM UI 中创建一个名为ec2-tag-instance 的新角色,并分配此策略:

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

这就是说,如果BlockDeviceMappings:Ebs 支持Tags 元素会更好。

【讨论】:

  • FWIW,我创建了一个添加标记支持 BlockDeviceMappings:Ebs 的功能请求,它可能会帮助你做同样的事情。
  • @BillMan。您可以粘贴带有功能请求的链接吗?我会赞成的。
  • @BillMan 你有我们功能请求的链接吗?我很期待这个功能,因为它比上面带有“UserData”部分的解决方案要简单得多。
  • 对于某些用例,建议的 IAM 策略可能过于宽松,因为它允许创建或覆盖任何 EC2 资源标签。如果您的实例受到威胁,如果您将标签用于其他目的(例如管理 EC2 EBS 快照),它可能会造成严重破坏。
【解决方案2】:

如果您的 CloudFormation 堆栈已标记,并且您希望 EC2 附加卷复制堆栈中的标签,则可以使用以下 UserData 值。

Fn::Base64: !Sub |
    #!/bin/bash -xe
    exec > /tmp/part-001.log 2>&1
    # --==Tagging Attached Volumes==--
    TAGS=$(aws cloudformation describe-stacks --stack-name ${AWS::StackName} --query 'Stacks[0].Tags' --region ${AWS::Region})
    EC2_INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
    EBS_IDS=$(aws ec2 describe-volumes --filters Name=attachment.instance-id,Values="$EC2_INSTANCE_ID" --region ${AWS::Region} --query 'Volumes[*].[VolumeId]' --out text | tr "\n" " ")
    aws ec2 create-tags --resources $EBS_IDS --tags "$TAGS" --region ${AWS::Region}
    TAGS=$(echo $TAGS | tr "Key" "key" | tr "Value" "value")
    aws ecs tag-resource --resource-arn arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:cluster/${EcsClusterName} --tags "$TAGS"

  1. 将所有标准输出和标准错误写入文件进行调试:

    `exec > /tmp/part-001.log 2>&1

  2. (需要权限)从堆栈中获取标签:

    TAGS=$(aws cloudformation describe-stacks --stack-name ${AWS::StackName} --query 'Stacks[0].Tags' --region ${AWS::Region})

  3. 从元数据端点获取 EC2 实例 ID:

    EC2_INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)

  4. (需要许可)获取 EBS IDS:

    EBS_IDS=$(aws ec2 describe-volumes --filters Name=attachment.instance-id,Values="$EC2_INSTANCE_ID" --region ${AWS::Region} --query 'Volumes[*].[VolumeId]' --out text | tr "\n" " ")

  5. (需要权限)向 EBS 卷添加标签: aws ec2 create-tags --resources $EBS_IDS --tags "$TAGS" --region ${AWS::Region}

  6. ECS 标记的格式标记:

    TAGS=$(echo $TAGS | tr "Key" "key" | tr "Value" "value")

  7. (需要权限)标记ECS集群:

    aws ecs tag-resource --resource-arn arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:cluster/${EcsClusterName} --tags "$TAGS"

政策应如下所示:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:DeleteTags",
                "ec2:CreateTags",
                "ecs:TagResource", 
                "cloudformation:DescribeStacks"
            ],
            "Resource": "*"
        }
    ]
}

【讨论】:

    【解决方案3】:

    您可以使用 CloudFormation 模板创建 CloudWatch 事件规则和 Lambda 等资源。 lambda 调用不仅可以在有实例创建事件时触发,也可以在实例标签发生更新时触发。

    【讨论】:

      【解决方案4】:

      这就是我在我的 ec2 用户数据中所做的。我认为这比上面的答案要简单得多。

      Key=<Your Tag Name>
      Value=<Your Tag Value>
      Region=$(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | grep -oP "(?<=\"region\" : \")[^\"]+")
      
      aws ec2 create-tags --resources $(aws ec2 describe-instances --instance-ids $(curl -s http://169.254.169.254/latest/meta-data/instance-id) --region $Region | grep -oP "(?<=\"VolumeId\": \")[^\"]+") --tags Key=$Key,Value=$Value --region $Region
      

      【讨论】:

      • 问题是关于如何从 CloudFormation 模板执行此操作。如果您查看我的答案中的模板,您会发现它正是这样做的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-26
      • 2017-02-14
      • 2015-07-08
      • 2021-06-09
      • 2021-02-26
      • 2018-01-13
      • 1970-01-01
      相关资源
      最近更新 更多