この記事は NIFTY Cloud Advent Calendar 2015の 20 日目です。
ESXi上で動作するOSイメージを自動ビルドするのにPackerが使われています。
LinuxのOSイメージをPackerでビルドする事例はありますが、Windowsについてはまだまだ少ないと感じており、今回は、WindowsのOSイメージをPackerでビルドする方法を紹介します。
構成
- Packer 0.8.6
- Windows Server 2012 R2 (ビルド対象OS)
- Ubuntu 15.04 (作業OS)
- ESXi 5.5U3 (Nested)
- VMware Workstation 11.1.3
※Workstation上に、UbuntuとESXiを稼働させています。
インストール
Packerのインストール
まず、Packerのインストールを行います。
$ wget https://dl.bintray.com/mitchellh/packer/packer_0.8.6_linux_amd64.zip $ mkdir /usr/local/packer $ unzip -d /usr/local/packer packer_0.8.6_linux_amd64.zip $ echo 'export PATH="${PATH}:/usr/local/packer"' | sudo tee -a /etc/profile.d/packer.sh; source /etc/profile.d/packer.sh $ packer --version 0.8.6
Packer Template
Packerを使ってビルドするには、Packer用のテンプレートファイル(json形式)を作成する必要があります。GitHub上にいくつかプロジェクトがあり、設定ファイル一式を取得することができます。
ただし、上記の設定ファイルだけだと一部動作しないところもあり、環境に合わせて変更を行います。今回の環境に合わせて修正を行った設定ファイルを使います。
$ git clone https://github.com/hideakihal/packer-windows-esxi.git $ cd packer-windows-esxi
ISOイメージの配置
packer-windows-esxi/iso配下にWindows Server 2012 R2のOSイメージを配置します。
また、合わせてwindows_2012_r2.jsonのvariablesにISOファイルのファイル名とハッシュ値を入力します。
$ vi windows_2012_r2.json "variables": { "iso_url": "./iso/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_SERVER_EVAL_EN-US-IR3_SSS_X64FREE_EN-US_DV9.ISO", "iso_checksum_type": "md5", "iso_checksum": "5B5E08C490AD16B59B1D9FAB0DEF883A", :
ESXi の GuestIPHack の有効化
VMware Tools が起動していない仮想マシンの IP を取得するため、 GuestIPHack を有効にします。
ESXi に SSH でログインして、下記のコマンドを実行します。
esxcli system settings advanced set -o /Net/GuestIPHack -i 1
ビルド方法
上記の準備ができたところで、以下のコマンドを実行し、ビルドを行います。コマンドに PACKER_LOG=1 PACKER_LOG_PATH=build.log を追加すると、詳細なログを出力することができるのでデバッグに便利です。
PACKER_LOG=1 PACKER_LOG_PATH=build.log \ packer build \ -var 'remote_host=<ESXi の IP アドレス>' \ -var 'remote_datastore=<データストア名>' \ windows_2012_r2.json
Packer Templateの解説
ビルドの流れ
今回作成した設定ファイルは、以下の流れでビルドを行っています。
- buildersによるOSリソースの設定
- 応答ファイル(Autounattend.xml)によるOSインストール
- 言語設定(SetupUILanguage等)
- インストールエディション選択(ImageInstall>OSImage>InstallFrom)
- ディスク構成(DiskConfiguration)
- コンピュータ名(ComputerName)
- アカウント設定(UserAccounts)
- 初期設定スクリプト(FirstLogonCommands)
- 初期設定(init.bat)
- Windows Update(win-updates.ps1)
- WinRM有効化(winrm.bat)
- WinRMにてログインし、provisionersで設定した事後スクリプトを実行
Windows Updateについて
Windows Updateを行っていますが、応答ファイルを以下のように修正することで無効にすることもできます。
$ vi Autounattend.xml <!-- WITHOUT WINDOWS UPDATES --> <SynchronousCommand wcm:action="add"> <CommandLine>cmd.exe /c a:\winrm.bat</CommandLine> <Description>Fire-up winrm!</Description> <Order>99</Order> </SynchronousCommand> <!-- WITH WINDOWS UPDATES <SynchronousCommand wcm:action="add"> <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\win-updates.ps1 -DoneScript a:\winrm.bat</CommandLine> <Description>Run Windows Updates</Description> <Order>99</Order> <RequiresUserInput>true</RequiresUserInput> </SynchronousCommand> -->
参考までにビルド時間は、Windows Updateがある場合は3時間30分、Windows Updateがない場合は15分かかりました。そのため、デバッグ中はWindows Updateはオフにしたほうが良いかと思います。
また、応答ファイルをデバッグする場合は、Windows ADKをインストールし、Windows システム イメージ マネージャーを利用すると便利です。
Windowsのprovisionerについて
Windowsイメージをビルドする際に利用できる provisioner は、PowerShell(powershell) と Windows Shell(windows-shell) しかありません。
OpenSSHをインストールして、Shell provisioner(shell) を試してましたが動作しませんでした。(動かす方法があるかもしれませんが。)
powershellはpowershellスクリプトを実行でき、windows-shellはcmdによるコマンドを実行できます。
今回は以下のように、VMware ToolsのインストールとRDP有効化のために利用しています。他の設定を行いたい場合は、ここにスクリプトを追加するかたちになります。
$ vi windows_2012_r2.json "provisioners": [ { "type": "windows-shell", "scripts": [ "scripts/vm-guest-tools.bat", "scripts/enable-rdp.bat" ] } ],
ただし、powershellとwindows-shellを利用するためには、WinRMによる接続を行う必要があり、テンプレートファイルにWinRM接続の設定を定義しておく必要があります。
$ vi windows_2012_r2.json "communicator": "winrm", "winrm_username": "packer", "winrm_password": "packer", "winrm_timeout": "6h",