EC2Launch v2環境でユーザーデータを扱う方法
しばたです。
先日から利用可能になったWindows Server 2022 AMIではデフォルトでEC2Launch v2が組み込まれています。
このEC2Launch v2では以前のバージョンに対しユーザーデータの扱い方が変わっているため本記事で解説します。
Windows Server EC2のユーザーデータ
EC2ではインスタンスの起動時に「ユーザーデータ」に記述した独自のスクリプトを実行できます。
このユーザーデータはLinuxインスタンスにおいてはcloud-init
、WindowsインスタンスにおいてはEC2Config
(Windows Server 2016以前)およびEC2Launch
(Windows Server 2016以降)によって実行されます。
ここでEC2Config
とEC2Launch (v1)
においては以下の様な簡素なタグを使った構文でユーザーデータを記載できました。
バッチファイルを実行する場合 (コマンドプロンプト)
<script>
echo Current date and time >> %SystemRoot%\Temp\test.log
echo %DATE% %TIME% >> %SystemRoot%\Temp\test.log
</script>
ユーザーデータを起動のたびに実行する場合は<persist>
タグを付けます。
<script>
echo Current date and time >> %SystemRoot%\Temp\test.log
echo %DATE% %TIME% >> %SystemRoot%\Temp\test.log
</script>
<persist>true</persist>
PowerShellスクリプトを実行する場合 (Windows PowerShell)
<powershell>
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
</powershell>
こちらもユーザーデータを起動のたびに実行する場合は<persist>
タグを付けます。
<powershell>
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
</powershell>
<persist>true</persist>
EC2Launch v2環境でのユーザーデータ
ここまでが従来の構文ですが、EC2Launch v2
環境では上記記法に加え以下の様なYAML形式の構文が追加されました。
version: 1.0
tasks:
- task: executeScript
inputs:
- frequency: always
type: powershell
runAs: localSystem
content: |-
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
この構文はEC2Launch v2の設定ファイルagent-config.yml
を設定する際に使用するものと同じになります。
agent-config.yml
では各種設定を実行するタイミングをstage
に記述し、このstage
は
- Boot
- Network
- PreReady
- PostReady
- UserData
の5つの段階があるのですが5. UserData
だけは設定ファイルでなくユーザーデータに直接記載する形となります。
これは「5. UserData
だけは別の設定ファイルがありagent-config.yml
の後に実行される」ようなものと考えるのが理解しやすいと思います。
(私はこの記事を書くまでこのステージの扱いをずっと誤認してました...)
この様にEC2Launch v2におけるユーザーデータはagent-config.yml
の拡張の様な形となっているため、単純にスクリプトを実行する以外にEC2Launch v2自体の機能も呼び出すことが可能となっています。
各タスクのドキュメントにあるAllowedStages
(実行可能ステージ)にUserData
が記載されているものであればどれでも実行可能です。
たとえば追加EBSボリュームの初期フォーマットを行うinitializeVolume
タスクはAllowedStages
が[PostReady, UserData]
であるためユーザーデータに
version: 1.0
tasks:
- task: initializeVolume
inputs:
initialize: all
と記載すればEC2起動時に追加ボリュームのフォーマットを同時にやってくれます。
この場合のEC2Launchのログを確認すると以下の様な感じです。
PostReadyステージの後にユーザーデータが実行されている事がわかりますね。
・・・前略・・・
2021-09-26 01:04:25 Info: Stage: postReadyLocalData execution completed
2021-09-26 01:04:25 Info: Getting user-data
2021-09-26 01:04:25 Info:
version: 1.0
tasks:
- task: initializeVolume
inputs:
initialize: all
2021-09-26 01:04:25 Info: Try parsing user-data in yaml format
2021-09-26 01:04:25 Info: Initializing user-data state
2021-09-26 01:04:25 Info: User-data state initialized successfully
2021-09-26 01:04:25 Info: Executing initialize volume.
2021-09-26 01:04:26 Info: Running ebsnvme-id.exe: Disk Number: 0
Volume ID: vol-0c229eb058629c42b
Device Name: sda1
Disk Number: 1
Volume ID: vol-0d68c67a1a66c54a8
Device Name: xvdb
2021-09-26 01:04:28 Info: Successfully initialized device xvdb with drive letter D:
2021-09-26 01:04:28 Info: Stage: postReadyUserData execution completed
・・・後略・・・
ユーザーデータに記述可能なタスクは
enableJumboFrames
: ジャンボフレームの有効化enableOpenSsh
: OpenSSHサーバーの自動構築 (参考)executeProgram
: 指定プログラムの実行executeScript
: 指定スクリプトの実行initializeVolume
: 追加EBSボリュームのフォーマット、ドライブレターマッピングoptimizeEna
: ENA最適化の設定setHostName
: ホスト名設定setWallpaper
: デスクトップ壁紙の設定startSsm
: SSM Agentサービスの起動sysprep
: Sysprepの実行writeFile
: 指定ファイルの書き込み
となりますので必要に応じて使い分けてください。
補足1. タスクの実行頻度に関して
補足として各タスクの実行頻度はFrequency
に記載されています。
スクリプト実行のexecuteScript
タスクであれば自分でOnce
かAlways
を選べるので問題ないのですが変更できないタスクも存在します。
たとえば先述のinitializeVolume
の場合Always
のみでありユーザーで変更できません。
このタスクは常にサーバー起動のたびに実行されることになります。
このため一度だけの実行で十分であればユーザーデータ自体を編集して削除してやるといった対処が必要になりますのでご注意ください。
↓
(ユーザーデータを何度も実行したくない場合は直接編集しなければならないケースもある)
補足2. 既存形式の実行
EC2Launch v2では下位互換のため既存形式のユーザーデータもサポートされています。
記事の最初に出した例もそのまま実行することが可能です。
この場合の実行ログは以下の様になり、最初にYAML形式での解析を試み失敗した場合従来のフォーマットでの解析を試みているのが見て取れます。
・・・前略・・・
2021-09-26 01:53:24 Info: Stage: postReadyLocalData execution completed
2021-09-26 01:53:24 Info: Getting user-data
2021-09-26 01:53:24 Info:
<powershell>
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
</powershell>
2021-09-26 01:53:24 Info: Try parsing user-data in yaml format
2021-09-26 01:53:24 Info: Parsing failed, fall back to legacy format
2021-09-26 01:53:24 Info: Converting user-data to yaml format
2021-09-26 01:53:24 Info: Frequency is set to: once
2021-09-26 01:53:24 Info: Run as user is set to: admin
2021-09-26 01:53:24 Info: Script is set to run as a detached process
2021-09-26 01:53:24 Info: PowerShell content detected
2021-09-26 01:53:24 Info: Userdata conversion completed
2021-09-26 01:53:24 Info: Initializing user-data state
・・・中略・・・
2021-09-26 01:53:25 Info: Stage: postReadyUserData execution completed
・・・後略・・・
最後に
以上となります。
恥ずかしながら去年EC2Launch v2の調査をした時点からずっとこのユーザーデータの仕様を誤認してました...
分かってしまえばシンプルな話ですしユーザーデータの表現力も大幅に増しておりとても便利になっています。
Windows Server 2022以外の環境でもEC2Launch v1からv2に移行することは可能です。
ユーザーデータで複雑なことを求められる場合はEC2Launchのバージョン自体を上げてしまうのも一つの方法としてアリでしょう。