CloudFormation によって作成されたインスタンスからルートボリュームにタグを付けるにはどうすればよいですか?

所要時間7分
0

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リソースの[ユーザーデータ]プロパティを介して行われます。ブートストラップを実行するには、インスタンスの作成後に 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.    テンプレートの [ユーザーデータ]セクションで、Linux インスタンスの要件に合わせて --tags Key=Name,Value=newAMI を更新します。Windows インスタンスの場合は、$tag.key="MyRootTag"$tag.value="MyRootVolumesValue" を更新してください。Linux と Windows の次の[ユーザーデータ]セクションの例を参照してください。

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 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 インスタンスの Amazon マシンイメージ (AMI) に AWS CLI をインストールする必要があります。AWS CLI はすべての Amazon Linux AMI にデフォルトでインストールされます。また、EC2 インスタンスにインスタンスプロファイルをアタッチする必要があります。インスタンスプロファイルには、AWS リージョンとアカウント内の EC2 ボリュームとインスタンスのみで ec2:DescribeInstancesec2: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公式
AWS公式更新しました 2年前