[アップデート] EC2のインスタンスメタデータから「タグ」の設定値を参照できるようになりました!

今まで出来なかったのが意外でした・・・
2022.01.07

みなさん、こんにちは!
福岡オフィスの青柳です。

Amazon EC2のインスタンスメタデータを使うと、インスタンス内 (OS上) からインスタンスに関する様々な情報を取得することができます。

今回ご紹介するアップデートで、インスタンスメタデータを通して「インスタンスに設定されている『タグ』の設定値」を読み取ることが可能になりました。

Instance Tags now available on the Amazon EC2 Instance Metadata Service

これまでは

インスタンス内 (OS上) からインスタンスのタグを参照するには、以下のような方法を取っていました。

  • AWS CLIコマンドaws ec2 describe-instancesを実行してタグの値を抽出する
  • AWS SDKでタグを参照するメソッド・関数を呼び出す

これらはいずれも、インスタンス内からAWSのAPIをコールして自分自身のインスタンスの情報を外側から取得することによって実現していました。

したがって、予めEC2インスタンスへのアクセス権限 (例えばec2:DescribeTagsなど) を付与したIAMロールを用意して、インスタンスプロファイルを使ってインスタンスへIAMロールを割り当てておく必要がありました。

インスタンスメタデータを参照する方法ですと、このようにEC2インスタンスへIAMの権限を与える必要がありません。

利用手順

準備

デフォルトでは、インスタンスメタデータを使って「タグ」を参照することは許可されていません

事前に、インスタンス単位で「インスタンスメタデータの『タグ』情報へのアクセス許可」を有効化しておく必要があります。

新規インスタンスの場合

マネジメントコンソールを使用する場合は、インスタンス起動ウィザード画面の「ステップ 3: インスタンスの詳細の設定」で、「高度な詳細」に「Allow tags in metadata」という項目が追加されているので、こちらを確認・設定します。

デフォルトでは「無効」になっていますので、「有効」に変更します。

有効にすると「Allow tags in metadata enabled」と警告めいた表示がされますが、単にアクセス許可についての注意喚起であるため無視して構いません。

この設定を行ったうえでインスタンスを作成すると、インスタンスメタデータを通してタグの値を参照することができるようになります。

AWS CLIを使う場合は、aws ec2 run-instancesコマンドで--metadata-options "InstanceMetadataTags=enabled"オプションを指定してください。

既存インスタンスの場合

マネジメントコンソールでインスタンスの「詳細」タブを選択します。

「インスタンスの詳細」に「インスタンスメタデータのタグを許可する」という項目が追加されているため、表示を確認します。

表示が「無効」になっている場合は、有効化する必要があります。

インスタンスを選択した状態で「アクション」→「インスタンスの設定」→「インスタンスメタデータのタグを許可する」の順に選択します。

「許可」にチェックを入れて、設定を保存します。

これで、インスタンスメタデータを通してタグの値を参照することができるようになります。

AWS CLIを使う場合は、aws ec2 modify-instance-metadata-optionsコマンドで--instance-metadata-tags enabledオプションを指定してください。

インスタンスメタデータを使って「タグ」の設定値を参照する

インスタンスメタデータの参照方法は、他のメタデータ情報の参照の場合と変わりません。

Linuxインスタンスの場合を例に説明します。

IMDSv1の場合

インスタンスメタデータにおいて、タグの情報は以下のパスの配下に格納されています。

http://169.254.169.254/latest/meta-data/tags/instance

タグの一覧を表示してみます。

$ curl http://169.254.169.254/latest/meta-data/tags/instance
Environment
Name
System

各タグの設定値を参照するには、以下のようにします。

$ curl http://169.254.169.254/latest/meta-data/tags/instance/Name
test-instance

$ curl http://169.254.169.254/latest/meta-data/tags/instance/System
example

$ curl http://169.254.169.254/latest/meta-data/tags/instance/Environment
dev

IMDSv2の場合

インスタンスメタデータを参照する際は、セキュリティ観点から「IMDSv2」を使用することが推奨されています。

IMDSv2では、事前に「トークン」を取得しておき、情報を参照する際にはトークンを渡す必要があります。

$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    56  100    56    0     0  56000      0 --:--:-- --:--:-- --:--:-- 56000

$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/tags/instance
Environment
Name
System

$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/tags/instance/Name
test-instance

$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/tags/instance/System
example

$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/tags/instance/Environment
dev

応用編

Windowsインスタンスの「コンピューター名」を自動設定する

Windowsインスタンスの作成時、「コンピューター名」をインスタンスの「Nameタグ」に合わせて自動設定する仕組みを作ってみます。

インスタンスのUserDataに以下のスクリプトを記述します。

<powershell>
$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
$compname = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/tags/instance/Name
Rename-Computer -NewName $compname -Force
Restart-Computer
</powershell>

WindowsインスタンスですのでPowerShellとなっていますが、内容は前述のLinuxインスタンスの場合と同じ考え方です。

<powersell>に続く2行で、インスタンスメタデータから「Nameタグ」の設定値を読み出しています。
3行目でコンピューター名を変更して、4行目で再起動を行います。

実際に設定してみましょう。

マネジメントコンソールのインスタンス起動ウィザード画面でUserDataを設定します。

タグを設定します。

インスタンス起動後にコンピューター名を確認します。

コンピューター名が「Nameタグ」の設定値になっていることが確認できました。

おわりに

インスタンスに設定した「タグ」の値を利用することで、いろいろなことができそうです。

  • 「Environment」タグの設定値を参照して、本番・検証・開発の各環境に応じて処理内容を変える
  • 特定のタグを確認することで、インスタンスがどのように作成されたのかをインスタンス内部で判定する
    • CloudFormationで作成された
    • ECSクラスターのコンテナインスタンスとして作成された
    • etc.

皆さんも是非お試しください。