こんにちは!
クラウドエンジニアの湖山です。
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::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通りご紹介しました。
- タグだけ手動で付ける
- UserDataプロパティを利用する
- 起動テンプレートを利用する(←オススメ)
CloudFormation は一度作成してしまえば使いまわすことができるので出来る限り綺麗にシンプルに記載したいものです。
もしも同様の課題でお困りの方がいらっしゃいましたら是非ご参考にしてみてください。