[アップデート] Windows Server EC2の初回起動速度を最適化するオプションが追加されました
しばたです。
先日AWSより「Windows Server EC2インスタンスの(初回)起動速度を最大65%高速化する機能を追加した。」とのアナウンスがありました。
こちら非常にシンプルな説明がされているものの、その実体は結構ややこしいので本記事で解説します。
どういうことなの?
まず最初にWindows Server EC2の基本について説明する必要があります。
通常のWindows Server EC2インスタンスはテンプレートとなるOSイメージ(AMI)から生成され、初回起動時には以下の初期処理が行われています。
- SysprepによるWindows OSの初期化処理
- EC2Config および EC2Launch による初期化処理
Sysprepによりテンプレートイメージの単純コピーとならない様にするためのOS初期化処理が行われ、その後EC2Config および EC2LaunchによりAdministratorの初期パスワードの生成などのEC2固有の初期化処理を行います。
通常のWindows Server EC2では初回起動時この2つの初期化処理をセットで行うのですが、このうちSysprepによる初期化だけを事前に実施しておくことで起動速度を上げようというのがこのオプションの基本路線となります。
当然ですがWindows OS標準の仕組みでSysprepだけを事前実施しておくということはできません。[1]
このためAWSでは若干トリッキーな方法を使っており、AWSアカウントにはじめから用意されているDefault VPC
を使い「Default VPC上で仮のEC2インスタンスを生成しSysprepによる初期化処理を実行、その後EBSをスナップショットに保存、利用者がEC2インスタンスを作成するときにこのSysprep実施済みEBSスナップショットを使う」といった事をします。
ざっくり図にするとこんな感じです。
事前に保持するSysprep済みEBSスナップショットの数は設定で変更可能であり、EC2インスタンスを作成して使用される都度補充されます。
またDefault VPCのEC2インスタンスはEBSスナップショットを生成したら直ちに削除されます。
前提条件、制約など
この様にトリッキーな実装となっているためこの機能の利用に際して求められる前提条件や制約が結構あります。
詳細は以下のドキュメントを確認して頂きたいですがいくつかかいつまんで説明します。
まず最初にEBSスナップショット生成のためにDefault VPCを使うため「EC2-Classic環境が無くDefault VPCが存在する」必要があります。
次にベースとなるAMIは自己所有のものである必要がありAWSで公開されているAMIを直接使うことはできません。[2]
このため必ずカスタムAMIをベースにする必要があります。
そしてこのベースAMIを作る際はかならず「Sysprepしてシャットダウン(次回起動時にSysprepが実行される)」状態にしてください。
Sysprepを実行しないでシャットダウンされた状態のAMIは現状サポートされていません。
また、ドキュメントに記載されていないもののSysprepをDefault VPCで行う以上「Sysprepに環境依存のカスタマイズ」をしている場合は期待した動作にならないはずです。
加えて、仕組みとして厳密にSysprepによる初期化とEC2Config および EC2Launch による初期化が分けられておらず以下の様になります。
- Default VPCで仮のEC2インスタンスを起動するとき
- SysprepによるWindows OSの初期化処理を実行
- EC2Config および EC2Launch による初期化処理を実行
- 次回起動時に「EC2Config および EC2Launch による初期化処理を実行」する様設定
- ユーザーがEC2インスタンスを起動するとき
- EC2Config および EC2Launch による初期化処理を実行
このため実際にはEC2Config および EC2Launch による初期化が2回実行されます。
EC2Config および EC2Launch による初期化をカスタマイズし1回だけ実行されることを期待としている場合は意図に反した動作となるのでご注意ください。
試してみた
この様にかなり前提条件の多い仕組みですが、とりあえず実際の動作を確認していきます。
今回は私の検証用AWSアカウントの東京リージョンで試します。
Default VPCの他に別途検証用VPCを用意済みです。
1. カスタムAMIの準備
最初にベースとなる自己所有のカスタムAMIを用意します。
今回は本日時点で最新の日本語版Windows Server 2019 AMI (ami-012e5e983e1bd9bb1 Windows_Server-2019-Japanese-Full-Base-2022.01.12
)からAMIを作ります。
カスタムAMIの作り方はこちらの記事を参考にしてください。
今回は特にカスタマイズを入れずインスタンス起動後ただちに「Sysprepしてシャットダウン」しました。
これで次回起動時にSysprepを実行する状態でインスタンスが停止しましたので、ここからAMI(test-fast-image
)を作成します。
このAMIと紐づいているEBSスナップショットはこんな感じです。
2. 最適化オプションの指定
これで前準備ができましたのでここから最適化オプションを設定します。
対象AMIを選択した状態で右クリックし、メニューから「イメージ最適化を管理」を選びます。
すると設定画面に遷移しますので、「Enable windows faster launching」にチェックを付けると最適化が有効になります。
画面下部にある「Set anticipated image launch frequency」欄は、細かい記述は無視して「Sysprep済みEBSスナップショットの保持数[3]」と考えてください。
「変更を保存」をクリックすると設定が有効になり、Default VPCにただちに一時インスタンスが生成されます。
しばらく待つとこの一時インスタンスは削除され、最終的には所定の数のSysprep済みEBSスナップショットが残ります。
今回は設定どおり5つのEBSスナップショットが元のAMI(ami-01bfbc64afa1e4bb3
)から生成されていることがわかります。
ちなみにいくつかのタグに構成情報が記載されているもののaws:
始まりの予約タグでは無い感じです。
3. EC2インスタンスの起動
これで最適化の準備が整いましたので実際にEC2インスタンスを作成してみます。
今回は普通にマネジメントコンソールからインスタンスを作っていきます。
AMIにベースとなるイメージ(test-fast-image
)を選び、あとは環境に合わせてよしなにウィザードを進めます。
ちなみに、ストレージ設定で表示されるEBSスナップショットは元のAMIに紐づくものとなっていました。
これでEC2インスタンスを作成すればあとは普通に使えます。
具体的な時間計測が難しかったのであくまで体感ですが、確かにRDP接続出来る様になるまでの時間は短縮されていました。
この時点で事前に作成されていた5つのEBSスナップショットが一つ消費され4つになります。
そして少し経つと再びDefault VPCに一時インスタンスが作成されSysprep済みEBSスナップショットの数を5つに補充しようとします。
以上で完了となります。
4. 最適化オプションを止める場合
最適化オプションを止める場合は「Enable windows faster launching」のチェックを外して更新するだけです。
更新後Sysprep済みEBSスナップショットはすべて削除されます。
補足1 : Default VPCを削除した場合
補足としてDefault VPCを削除した状態で最適化オプションを有効にした場合どの様になるのか確認してみたところ普通にエラーになりました。
ami-xxxxxxxxxx の高速起動を有効にできませんでした。API エラー : Cannot enable faster launching. Run instances dry run failed for enabling faster launching. No default VPC for this user. GroupName is only supported for EC2-Classic and default VPC.
Default VPCの無い環境でこのオプションを使いたい場合は「デフォルトVPCを作成」してください。
補足2 : 実装に関して
また、追加で本オプションの実装面についていくつか補足します。
AWSServiceRoleForEC2FastLaunch ロール
本機能を有効にするとAWSServiceRoleForEC2FastLaunch
という名前のService Lined Roleが自動生成されます。
このロールにEC2操作のための諸々の権限が割り当てられています。
もしこのオプションの挙動がおかしい場合はこのロールに異常がないかチェックすると良いでしょう。
自動生成される起動テンプレート
Default VPCに一時EC2インスタンスを作成するのは自動生成される起動テンプレートから行われています。
起動テンプレートはEC2FastLaunchDefaultResourceCreation-
で始まる名前で自動生成される様です。
機能を無効にしても起動テンプレートは削除されなかったのでこれは手動で削除すると良いでしょう。
一時EC2インスタンスのUserData
Default VPCに一時EC2インスタンスを作成するとSysprepとEC2ConfigおよびEC2Launchによる初期化処理が実行され、通常であれば以後一切初期化処理が行われない様になってしまうはずです。
本機能ではこの点をUserDataに仕込みを入れることで解決しています。
<powershell>
if (Get-Service Ec2Config) {
$EC2SettingsFile = "$env:ProgramFiles\Amazon\Ec2ConfigService\Settings\Config.xml"
$xml = [xml](get-content $EC2SettingsFile)
$xmlElement = $xml.get_DocumentElement()
$xmlElementToModify = $xmlElement.Plugins
foreach ($element in $xmlElementToModify.Plugin) {
if ($element.name -eq 'Ec2SetPassword') { $element.State = 'Enabled' }
elseif ($element.name -eq 'Ec2HandleUserData') { $element.State = 'Enabled' }
elseif ($element.name -eq 'Ec2DynamicBootVolumeSize') { $element.State = 'Enabled' }
}
$xml.Save($EC2SettingsFile)
} elseif (Get-Service 'Amazon EC2Launch') {
& "$env:ProgramFiles\Amazon\EC2Launch\ec2launch.exe" reset -c
} else {
& "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy Bypass -File "$env:ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1" -Schedule
}
New-Item -Path HKLM:\Software\Amazon -Name WarmBoot
Invoke-Expression -Command:'shutdown.exe /s /t 0'
while ($true) {
}
</powershell>
上記コードをみればすぐわかりますが、サーバー環境にインストールされているツール(EC2Config、EC2Launch v2、EC2Launch v1)をチェックし、それぞれのツールのリセット処理(次回起動時に初期化処理を実行する設定)を実施してます。
これによりSysprep済みでありながら次回起動時にEC2CconfigおよびEC2Launchによる初期化処理を行う環境を実現しているわけです。
ちなみに用途は一切不明なのですが空のレジストリキーHKLM:\Software\Amazon\WarmBoot
を作成しています。
EC2CconfigやEC2Launchをカスタマイズしている環境でDefault VPCでの初回起動とユーザー環境での初回起動を区別したい場合はこのキーの有無をチェックすると良さそうです。
(ドキュメントに記載されてない設定なので突然仕様変更される可能性はありますが...)
最後に
以上となります。
ここまでの説明でこのオプションが単純に導入出来るものでは無いことがお分かりいただけたかと思います。
このオプションは例えばAuto Scaling Groupで大量のWindows Serverを自動生成する環境においてより高速にインスタンスを起動するためのものであり、個別のEC2インスタンスを作成するときに使うものではありません。[4]
万人向けのものではありませんが大量にWindows Serverを使う環境では導入を検討する価値があると思います。