EC2 Image BuilderでWindows Server OSを日本語化するコンポーネントを作ってみた – Ver.2
しばたです。
以前の記事でWindows Server 2019専用でUIを日本語化するコンポーネントを作成しました。
今回はWindows Server 2022版の作成を検討しコンポーネントの仕組みを見直してみました。
Windows Server 2022の問題
前の記事を公開した直後は単純に「Windows Server 2022用に言語パックのURLを変えるだけで大丈夫だろう。」と考えていたのですが、どうもWindows Serverの言語パックは原則非公開でWindows Server 2019だけが例外的な扱いの様でした。
(通常はGUIの設定画面からダウンロード、オフライン環境ではボリュームライセンスサービスセンター等の契約者向けサイトからダウンロードする前提の模様)
このためWindow Server 2022においても言語パック単体の公開はしておらず、オンラインでは評価版ISOファイルを代替として使える様でした。
この ISO は Windows Server 2022 上でのみ利用可能であり、これまで別々に提供されていたオンデマンド機能 (FOD) と言語パックの ISO をひとつにまとめたものです。これを FOD と言語パックのリポジトリとして使用することができます。
ただ、この評価版ISOファイルは約6GBあり、流石に都度ダウンロードするには重すぎると判断しました。
そこで今回は事前にS3バケットに言語パックのCABファイル(Microsoft-Windows-Server-Language-Pack_x64_ja-jp.cab
)をアップロードしておき、S3からCABファイルをダウンロードする形に方式を変えることにしました。
併せてWindows Server 2019でも使える様に処理の共通化も図りました。
作ったコンポーネント (Ver.2.1)
以下が更新したコンポーネント定義です。
今回はWindows Server 2022およびWindows Server 2019を対象としています。
動作確認はしてませんがWindows Server 2016でも動くと思います。
今回は利用者環境のS3バケットから言語パックのCABファイルを直接ダウンロードする仕組みに変えため、コンポーネントのパラメーターで「S3バケット名」「CABファイルのパス」を指定する形になっています。
name: windows-server-setup-japanese-ui
description: Install Japanese Language pack and Update UI configurations.
schemaVersion: 1.0
parameters:
- S3BucketName:
type: string
default: 'your-bucket-name'
description: Set your S3 bucket name.
- S3BucketPath:
type: string
default: 'LanguagePack/WindowsServer2022/Microsoft-Windows-Server-Language-Pack_x64_ja-jp.cab'
description: Set your S3 key path for language packe .cab file.
phases:
- name: build
steps:
- name: DownloadLanguagePackStep
action: S3Download
inputs:
- source: s3://{{ S3BucketName }}/{{ S3BucketPath }}
destination: C:\Windows\TEMP\Microsoft-Windows-Server-Language-Pack_x64_ja-jp.cab
overwrite: true
- name: InstallLanguagePackStep
action: ExecutePowerShell
inputs:
commands:
- |
# Set configurations
$jpCabPath = 'C:\Windows\TEMP\Microsoft-Windows-Server-Language-Pack_x64_ja-jp.cab'
# Check if file exists
if (-not (Test-Path -LiteralPath $jpCabPath)) {
Write-Error ('Failed to download {0}.' -f $jpCabPath)
return
}
# Install language pack
try {
Write-Output 'Insall Language pack cab file...'
Write-Output (' {0}' -f $jpCabPath)
Add-WindowsPackage -Online -PackagePath $jpCabPath -LogPath (Join-Path -Path $env:TEMP 'dism.log')
} catch {
Write-Error $_
return
} finally {
# Remove .cab
if (Test-Path -LiteralPath $jpCabPath) {
Write-Output 'Remove Language pack cab file...'
Remove-Item -LiteralPath $jpCabPath
}
}
# Set UI Language Settings
Write-Output 'Update language list...'
Set-WinUserLanguageList -LanguageList ja-JP, en-US -Force
# Set System local
Write-Output 'Update system locale...'
Set-WinSystemLocale -SystemLocale ja-JP
- name: RebootAfterLanguagePackInstalled
action: Reboot
inputs:
delaySeconds: 10
- name: UpdateUIConfigurationsStep
action: ExecutePowerShell
inputs:
commands:
- |
# Update UI Language Settings
Write-Output 'Update UI language...'
Set-WinUILanguageOverride -Language ja-JP
Write-Output 'Update Input method...'
Set-WinDefaultInputMethodOverride -InputTip '0411:00000411'
# Set Location settings
Write-Output 'Set Location...'
Set-WinHomeLocation -GeoId 122
Set-WinCultureFromLanguageListOptOut -OptOut $False
# Set Timezone
Write-Output 'Set Timezone...'
Set-TimeZone -Id 'Tokyo Standard Time'
- name: UpdateSysprepCconfigsStep
action: ExecutePowerShell
inputs:
commands:
- |
$xmlFiles = @()
# EC2 Launch v2
if (Test-Path -LiteralPath 'C:\ProgramData\Amazon\EC2Launch\sysprep\unattend.xml') {
$xmlFiles += 'C:\ProgramData\Amazon\EC2Launch\sysprep\unattend.xml'
}
# EC2 Launch v1
if (Test-Path -LiteralPath 'C:\ProgramData\Amazon\EC2-Windows\Launch\Sysprep\Unattend.xml') {
$xmlFiles += 'C:\ProgramData\Amazon\EC2-Windows\Launch\Sysprep\Unattend.xml'
}
foreach ($x in $xmlFiles) {
Write-Output ('Update {0}...' -f $x)
# Backup Unattend.xml
Copy-Item -LiteralPath $x -Destination "${x}.orig" -Force
# Update Unattend.xml
$xmlDoc = [ xml](Get-Content -LiteralPath $x -Raw)
# Update Timezone
$xmlDoc.unattend.settings.component | Where-Object { $_.name -eq 'Microsoft-Windows-Shell-Setup' } | ForEach-Object {
$_.TimeZone = 'Tokyo Standard Time'
}
# Update Launguage, Locale
$xmlDoc.unattend.settings.component | Where-Object { $_.name -eq 'Microsoft-Windows-International-Core' } | ForEach-Object {
$_.InputLocale = 'ja-JP'
$_.SystemLocale = 'ja-JP'
$_.UILanguage = 'ja-JP'
$_.UserLocale = 'ja-JP'
}
$xmlDoc.Save($x)
}
- name: ApplyWindowsUpdateStep
action: UpdateOS
コードの解説
前回からの変更点を中心にコードの解説をしておきます。
1. 言語パックのダウンロード (DownloadLanguagePackStep)
記事公開後にAWS組み込みのアクションS3Download
があることに気が付き処理を見直しています。
このアクションを使いS3バケットに配備した言語パック(CABファイル)をC:\Windows\TEMP\
にダウンロードする様にしています。
S3バケット名とCABファイルのパスはパラメーターで指定可能にしてあり、デフォルト値は
S3BucketName
=your-bucket-name
S3BucketPath
=LanguagePack/WindowsServer2022/Microsoft-Windows-Server-Language-Pack_x64_ja-jp.cab
としています。
S3アクセスをするためImage Builderで使うIAMロールに対象S3バケット・オブジェクトへの読み取り権限を与えておく必要があります。
2. 言語パックのインストール (InstallLanguagePackStep)
言語パックのインストール処理は前回と変わりありません。
ダウンロード処理をAWS組み込みアクションにしたことで処理がすっきりしました。
3. 再起動 (RebootAfterLanguagePackInstalled)
追加した日本語にUIを変更する(具体的にはSet-WinUILanguageOverride
コマンドの実行)には一度再起動する必要があるためImage BuilderのReboot
アクションを使ってOSを再起動します。
併せてこの再起動でシステムロケールの変更も反映させています。
ここは前回と変わりありません。
4. 言語設定の変更 (UpdateUIConfigurationsStep)
再起動後はUI言語の変更(Set-WinUILanguageOverride
)をはじめ各種設定変更コマンドを実行しており、ざっくり
- UI言語を日本語に変更
- 「地域」のを日本に変更
- タイムゾーンをJSTに変更
をやっています。
ここも前回同様であり、Windows Server 2019、Windows Server 2022で同じ処理が使えます。
このステップでOSの設定変更は完了です。
5. Sysprep設定の変更 (UpdateSysprepCconfigsStep)
Image BuilderでAMIを作成する際はSysprep
による一般化が行われるためUnattend.xml
ファイルを変更してやる必要があるのも前回と同じです。
ただし、Unattend.xml
ファイルの配置場所はOS毎(正確にはEC2 Launchのバージョン毎)によって変わるため更新対象ファイルのチェックを追加しています。
6. Windows Updateの実施 (ApplyWindowsUpdateStep)
言語パックをインストールした後はWindows Updateをした方が良いのでAWS組み込みアクションUpdateOS
を追加しました。
- 参考 : 言語パックインストール時のご留意点
この作業により言語パックファイル作成時点以降の更新に対する言語リソースの適用などを行います。
試してみる
ここから実際にこのコンポーネントを試していきます。
今回も私の検証AWSアカウントの東京リージョンを使用しています。
0. S3バケットの準備
まずは事前準備として任意のS3バケットにCABファイルをアップロードしておきます。
今回は私の個人用バケットのLanguagePack/WindowsServer2022/Microsoft-Windows-Server-Language-Pack_x64_ja-jp.cab
にアップロードしています。
ちなみに元データはWindows Server 2022評価版ISOファイルのLanguagesAndOptionalFeatures
フォルダに存在しています。
ISOファイルのダウンロードおよびS3のアップロード手順については割愛します。
1. コンポーネントの作成
続けてマネジメントコンソールから新規にコンポーネントを作成します。
タイプは「ビルド」でwindows-server-setup-japanese-ui
という名前にしています。
コンポーネントバージョンは何でも構わないのですが、前回からのバージョンアップの意味を込めて2.0.0
としています。
そして、互換性のあるOSバージョンはWindows Server 2019とWindows Server 2022にしています。
コンポーネント定義は前掲のコードをそのまま転記します。
その他設定は必要があれば行ってください。
エラー無く作成できればOKです。
2. レシピの作成
あとは通常の流れ通りレシピを作りパイプラインを実行していく形となります。
今回は前回作ったmy-japanese-windows-image
レシピをVer.2.0.0に更新する形にしました。
主要な点だけ解説すると、対象OSを「Windows Server 2022」に更新し、
ビルドコンポーネントをwindows-server-setup-japanese-ui
に切り替えて、S3BucketName
とS3BucketPath
の2パラメーターを事前準備で用意した環境に合わせた値にしてやります。
作成結果はこんな感じです。
3. パイプラインの作成
パイプラインも前回作ったbuild-my-japanese-windows-image
を更新する形にしました。
レシピをmy-japanese-windows-image
Ver.2.0.0に更新します。
インフラストラクチャ設定およびディストリビューション設定は新規に作成するか環境に応じたものにしてください。
今回のコンポーネントを利用するのに必要な前提条件は
- ビルド時に要インターネットアクセス (S3へのアクセスのため)
- VPC Endpointで代用可能
- 当該S3バケットおよびオブジェクトに対する読み取り権限
- IAMロールに権限を追加してください
となるため、S3バケットへのアクセス権が必要となります。
今回は横着してIAMロールにAmazonS3ReadOnlyAccess
をアタッチしていますが、本番環境ではちゃんと対象バケットを制限する様にしてください。
(事前に用意しているImage Builder用IAMロール。構築手順は割愛)
4. パイプラインの実行
これで準備ができたので、最後にパイプラインを実行して作成されるイメージがちゃんと日本語化されているか確認していきます。
実行結果はこんな感じでami-09c06b1953b961f3c
というAMIが作成されました。
このAMIから確認用のEC2インスタンスを起動してやり、日本語化されていることを確認します。
最後に
以上となります。
S3へのアクセス権が必要になったものの対応OSも増え処理としてはだいぶ汎用的なものになったと思います。
需要がどれだけあるかは怪しいですが誰かの役に立てば幸いです。