この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
AWSを愛する皆さま、こんにちは。コンサルティング部の西野(@xiyegen)です。
CloudFormationでEC2インスタンスを作成する際はAWS::EC2::Instanceというリソースを指定します。
このAWS::EC2::Instance
にはルートボリュームのタグ付けを担うプロパティが存在しません。
それでもなんとかしてインスタンス作成時にこのタグ付けを実施できないか調べていたところ、公式のナレッジを発見しました。
AWS CloudFormation が作成したインスタンスからルートボリュームにタグを付ける方法を教えてください。
当該ページで紹介されているテンプレートが大きめだったので、あっさり味に加工した自作テンプレートとともに仕組みを紹介したいと思います。
目次
3行まとめ
テンプレート内で行われている処理は単純です。
- UserDataによりインスタンスメタデータからリージョン情報およびインスタンスIDを取得する。
- UserDataからAWS CLIを使用しタグ付け対象ボリュームのID取得&タグ付けを実行する(
aws ec2 describe-instances
&aws ec2 create-tags
)。 - 上記のコマンドを実行するために
ec2:Describe*
とec2:CreateTags
の権限をインスタンスへ付与する。
注意
AWSのリソースタグは、IAMによるアクセス制御やAmazon DLMによるスナップショットターゲットの指定など、様々な用途に用いられます。
リソースタグのユースケースによってはec2:CreateTags
権限の付与が意図せぬ結果をまねくことがあります。あらかじめご留意ください。
テンプレート
前提条件
- AWS CLIが必要なのでAmazon Linux 2の最新版AMI(2020/02/26時点)を使用しています。
- 説明の簡便化のためテンプレートから
Parameters
セクションを省いてあります。 - ルートボリュームにNameタグ
MySweetRootVolume
を設定するテンプレートです。 *1
本体
AWSTemplateFormatVersion: 2010-09-09
Resources:
LinuxInstance:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: ami-0af1df87db7b650f4
InstanceType: t2.micro
AvailabilityZone: ap-northeast-1a
SubnetId: subnet-XXXXXXXXXXXXXXXXX
IamInstanceProfile: !Ref InstanceProfile
KeyName: wo-de-yaoshi
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=MySweetRootVolume
Tags:
- Key: Name
Value: MySweetInstance
BlockDeviceMappings:
- DeviceName: "/dev/xvda"
Ebs:
VolumeSize: 8
VolumeType: "gp2"
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
解説
UserData
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=MySweetRootVolume
ルートボリュームへのタグ付けの肝となるのは本テンプレートのUserData部分です。
- 必要となるパラメータ(
$AWS_REGION
と$AWS_INSTANCE_ID
)をインスタンスメタデータから取得 aws ec2 describe-instances
でルートボリュームのIDを取得aws ec2 create-tags
でタグ付けを実行(Key=Name,Value=MySweetRootVolume)
という流れで処理を行っています。
IAMロールとインスタンスプロファイル
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
ボリュームのID取得とタグ付けに必要なec2:Describe*
とec2:CreateTags
の権限を持つポリシーを作成し、作成対象のインスタンスに付与しています。
やってみた
先述したテンプレートでスタックを作成します。
EC2インスタンスができています。
ルートボリュームを見てみると……。
しっかりNameタグを付与できています。
終わりに
このブログがほんの少しでも世界を良くできれば嬉しいです。 コンサルティング部の西野(@xiyegen)がお送りしました。
脚注
- aws ec2 create-tagsコマンドの--tagsオプションでKeyおよびValueを指定することにより任意のタグを付与できます。 ↩