前提条件

  • 前回に引き続き、EC2のName Tag をOSのスクリプトから設定する方法を紹介します。お待たせしました! 今回は、PowerShellによるWindows Serverが対象となります。
  • 想定されるシチュエーションとしては、AMIからEC2 起動時にuser-data にスクリプトを組み込むことで一意のName Tag を設定します。
  • Windows Server 2012 R2 の実行結果を元に記載しております。aws cli が使用できる環境が前提です。
  • 前回まとめたLinux版は、下記の記事を参照ください。
前提条件今回は、EC2のName Tag をOSのスクリプトから設定する方法を紹介します。想定されるシチュエーションとしては、AMIからEC2 起動時にuser-data にスクリプトを組み込むことで一意のName Tag を設定します。スクリプトサンプルはLinux 版となります。aws cli ...

Windowsの場合

user-dataの設定方法

  • Windows のPowerShellをAdministratorで起動し、PowerShellのスクリプトが動作することを確認します。
  • 次に、EC2インスタンス作成時の「インスタンスの詳細の設定」にて「高度な詳細」のユーザーデータに貼り付けます。
    Windowsの場合、ポイントは<script>~</script>あるいは<powershell>~</powershell>のタグでスクリプトを囲むことです。

ハマったこと!

  • WindowsのPowerShell は経験が浅いこともあり、ハマりました。
  • PowerShell単体で実行できることを確認しましたが、意図した通りに実行されません。ログファイルを調査したところ、下記のエラーを発見しました。
  • 当初、Internet Explorerの設定やレースコンディションを疑いました。スクリプトの始めにsleep を追加、curl、catのエイリアスをInvoke-WebRequest、Get-Contentに置き換えましたが、解決しません。
  • 試行錯誤した結果、エラーメッセージに記載されている「-UseBasicParsing」オプションを付加することで解決しました!
2019-09-24T05:46:43.560Z: Ec2HandleUserData: Message: The errors from user scripts: curl : The response content cannot be parsed because the Internet Explorer 
engine is not available, or Internet Explorer's first-launch configuration is 
not complete. Specify the UseBasicParsing parameter and try again. 
At C:\Program Files\Amazon\Ec2ConfigService\Scripts\UserScript.ps1:3 char:14
+ $instanceid=(curl 'http://169.254.169.254/latest/meta-data/instance-id')
+              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotImplemented: (:) [Invoke-WebRequest], NotSupp 
   ortedException
    + FullyQualifiedErrorId : WebCmdletIEDomNotSupportedException,Microsoft.Po 
   werShell.Commands.InvokeWebRequestCommand
 
curl : The response content cannot be parsed because the Internet Explorer 
engine is not available, or Internet Explorer's first-launch configuration is 
not complete. Specify the UseBasicParsing parameter and try again. 
At C:\Program Files\Amazon\Ec2ConfigService\Scripts\UserScript.ps1:7 char:11
+ $localip=(curl 'http://169.254.169.254/latest/meta-data/local-ipv4')
+           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotImplemented: (:) [Invoke-WebRequest], NotSupp 
   ortedException
    + FullyQualifiedErrorId : WebCmdletIEDomNotSupportedException,Microsoft.Po 
   werShell.Commands.InvokeWebRequestCommand
 

An error occurred (MissingParameter) when calling the CreateTags operation: The request must contain the parameter resourceIdSet

スクリプトサンプル(user-data: NG)

  • 以下は、PowerShell単体では実行できますが、user-dataに設定した場合は意図した通りに実行されません。
# Instance IDを取得する
$instanceid=(curl 'http://169.254.169.254/latest/meta-data/instance-id')

# Private IPを取得する
$localip=(curl 'http://169.254.169.254/latest/meta-data/local-ipv4')

# NAME Tagを取得する
$hostname=(cat "C:\tmp\ec2_name.txt")

# 変更後のNAME Tagを作成する
$newhostname="$hostname-$localip"

# NAME Tagを更新する
aws ec2 create-tags --resources $instanceid --tags "Key=Name,Value=$newhostname" --region ap-northeast-1

スクリプトサンプル(user-data: OK)

  • Linuxの場合は、jqコマンドを使用してNAME Tagを取得しましたが、Windowsの場合はjqコマンドがインストールされていないため、ローカルファイルにNAME Tagの値を持たせることにしました。EC2起動時に、プライベートIPを取得し、NAMT Tagに追加しています。
  • 下記スクリプトは省略していますが、<powershell>~</powershell>のタグを忘れないようにしてください。
# Instance IDを取得する
$instanceid=(Invoke-WebRequest 'http://169.254.169.254/latest/meta-data/instance-id' -UseBasicParsing)

# Private IPを取得する
$localip=(Invoke-WebRequest 'http://169.254.169.254/latest/meta-data/local-ipv4' -UseBasicParsing)

# NAME Tagを取得する
$hostname=(Get-Content "C:\tmp\ec2_name.txt")

# 変更後のNAME Tagを作成する
$newhostname="$hostname-$localip"

# NAME Tagを更新する
aws ec2 create-tags --resources $instanceid --tags "Key=Name,Value=$newhostname" --region ap-northeast-1

user-dataが意図した通りに実行されない場合

  • 先ず、PowerShell単体でエラーなく、実行できることを確認します。PowerShellはAdministratorとして起動して、テストします。
  • user-dataのスクリプトに<script>~</script>あるいは<powershell>~</powershell>のタグが付加されていることを確認します。
  • EC2のroleに、EC2のFullAccess権限があることを確認します。(NAME Tagを更新するため)
  • ユーザーデータは初回起動時のみ実行されます。もし、起動するAMIがsysprepした後に取得したイメージでなければ、スクリプトに<persist>true</persist>を追記し、テストします。このオプションは初回起動時だけでなく、起動時に必ずuser-dataを実行するオプションです。
  • EC2起動後、下記ログファイルを確認し、エラーの有無や調査の手がかりを見つけます。
    • C:\Program Files\Amazon\Ec2ConfigService\Logs\Ec2ConfigLog.txt

参考資料

  • 今回のスクリプトでは、EC2のメタデータを読み込み、EC2のInstance IDやPrivate IPを取得しています。LinuxおよびWindowsでメタデータを読み込む方法は、下記の記事を参考にしてください。
概要EC2のインスタンスメタデータ(meta-data)およびユーザーデータ(user-data)は、インスタンス内からのみアクセス可能なインスタンスに関するデータです。インスタンスにアクセスできるユーザーなら誰でもそのメタデータおよびユーザーデータを参照できます。そ...
起動時に Windows インスタンスでコマンドを実行する方法について説明します。

元記事はこちら

EC2 user-data を使ってNAME Tagを設定する(Windows)