AWS

【CloudFormation】EC2のルートボリュームにタグを付与する方法

こんにちは!
クラウドエンジニアの湖山です。

CloudFormation は、一括で環境を構築することができるので非常に便利なのですが、EC2インスタンスのルートボリュームにNameタグを付けるには一工夫が必要です。

そのタグの付け方は何通りか存在するので、それぞれ説明と一番スマートな方法をご紹介します。

課題点

その前に、今回の課題点はどのようなものか確認していきます。

CloudFormationでEC2インスタンスを構築します。

AWSTemplateFormatVersion: 2010-09-09
Resources:
    MyInstance:
      Type: AWS::EC2::Instance
      Properties:
        ImageId: 'ami-0a1c2ec61571737db'
        InstanceType: 't2.micro'

出来上がったリソース(インスタンス)へアクセスします。

インスタンスのルートデバイスのEBSへアクセスします。

本来はこの部分にNameタグを付けて管理をしたいのですが、AWS::EC2::Instance リソースのプロパティの中にはEBSのNameタグを指定することはできません。

では、どのようにEBSのルートボリュームに対してNameタグを付けていくのでしょうか?

ルートボリュームのNameタグの付け方

【その1】CloudFormationでインスタンスを作成後、手動で付ける

まぁ妥協案ですよね。

CloudFormation実行後に作成されたインスタンスのルートボリュームを選択し、「タグの追加/編集」から手動でタグを付ける方法です。

簡単に対処できますが、
これだとせっかくのCloudFormationの利点が活かせていません

【その2】UserData プロパティを介してブートストラップ実行

AWSサポートからの回答はこの方法でした。

AWS CloudFormation が作成したインスタンスからルートボリュームにタグを付ける方法を教えてください。

要は、AWS::EC2::Instance リソースの UserData プロパティを利用し、インスタンス作成後に AWS Command Line Interface (AWS CLI) の commandsでブートストラップ実行を行います。

CloudFormation のテンプレートは以下のようになります。
※「169.254.169.254」はメタデータを戻すサーバのアドレスです。
 そのままコピペでご利用ください。

AWSTemplateFormatVersion: 2010-09-09
Resources:
  MyInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: 'ami-0a1c2ec61571737db'
      InstanceType: 't2.micro'
      IamInstanceProfile: !Ref InstanceProfile
      UserData: 
        Fn::Base64: |
          #!/bin/sh
          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=Name,Value=MyRootVolumeName
  
  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*'
              - 'ec2:CreateTags'
            Resource: '*'

  InstanceProfile:
    Type: 'AWS::IAM::InstanceProfile'
    Properties:
      Path: /
      Roles:
       - !Ref InstanceRole

16行目の
「–tags Key=Name,Value=MyRootVolumeName
の部分で付けたいタグを指定してください。

ただ、UserData プロパティを使用するとテンプレート内がごちゃごちゃして可読性が下がりますし、ゴリ押し感があるのであまりスマートな方法ではありません。

【その3】EC2 インスタンスの起動テンプレートを使用

こちらが一番スマートな方法になります!

Amazon EC2 インスタンスに起動テンプレートを指定します。

AWS::EC2::LaunchTemplate リソースには、インスタンスを起動するためのパラメータが含まれており、その中にルートボリュームのNameタグを付けるものが存在します。

AWSTemplateFormatVersion: 2010-09-09
Resources:
  MyInstance:
    Type: AWS::EC2::Instance
    Properties:
      LaunchTemplate: 
        LaunchTemplateId: !Ref MyLaunchTemplate
        Version: 1

  MyLaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties: 
      LaunchTemplateData: 
        ImageId: 'ami-0a1c2ec61571737db'
        InstanceType: 't2.micro'
        TagSpecifications:
          - ResourceType: volume
            Tags: 
              - Key: Name
                Value: MyRootVolumeNameLanTmp

16-20行目の部分で付けたいタグが指定できます。
17行目で「volume」を指定するとボリュームに対するタグ指定が可能となり、他にも「instance 」「key-pair」など様々なリソースに対応しております。

この方法が一番スマートに課題を解決することができます!

まとめ

CloudFormationで作成したEC2インスタンスのルートボリュームのNameタグの付け方を3通りご紹介しました。

  1. タグだけ手動で付ける
  2. UserDataプロパティを利用する
  3. 起動テンプレートを利用する(←オススメ)

CloudFormation は一度作成してしまえば使いまわすことができるので出来る限り綺麗にシンプルに記載したいものです。

もしも同様の課題でお困りの方がいらっしゃいましたら是非ご参考にしてみてください。

ABOUT ME
湖山 貴裕
はじめまして。 二児のお父さんプログラマーです。最近キャンプにも興味あり。夏には庭でキャンプしようともくろみ中。ボドゲ好き。チョコ好き。茶道経験者。 2012年大学卒業→IT企業就職 Java,VB.NET, C#, javascript等の企業向けシステム開発/主にバックエンドを担当/AWSを少しかじる→2020年フリーランスエンジニアへ転身 広島でAWS案件にて楽しく活動中