EC2 user-data を使ってNAME Tagを設定する(Windows)
AWS,EC2,OperatingSystem,WindowsServer
Contents
前提条件
- 前回に引き続き、EC2のName Tag をOSのスクリプトから設定する方法を紹介します。お待たせしました! 今回は、PowerShellによるWindows Server が対象となります。
- 想定されるシチュエーションとしては、AMIからEC2 起動時にuser-data にスクリプトを組み込むことで一意のName Tag を設定します。
- Windows Server 2012 R2 の実行結果を元に記載しております。aws cli が使用できる環境が前提です。
- 前回まとめたLinux版は、下記の記事を参照ください。
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でメタデータを読み込む方法は、下記の記事を参考にしてください。
AWS,EC2,OperatingSystem,WindowsServer
Posted by takaaki