ラベル packer の投稿を表示しています。 すべての投稿を表示
ラベル packer の投稿を表示しています。 すべての投稿を表示

2017年10月22日日曜日

packer で Powershell を使って Windows サーバに DNS を設定する方法

概要

packer で WindowsServer2016 を構築する際にネットワークアダプタに DNS を設定する方法を紹介します
もし DHCP で IP を取得する場合だと大抵は DHCP サーバが DNS の情報も教えてくれますが、そうじゃない環境の場合には手動で DNS の向き先を変更する必要があります
そういった場合には使える手法だと思います

環境

  • ESXi 6.0.0 (Build 3620759)
  • Ubuntu 16.0.4
  • packer 1.0.4

Powershell スクリプト

DNS を Ethernet0 アダプタに設定する方法を紹介します

  • vim scripts/dns.ps1
Set-DnsClientServerAddress -InterfaceAlias "Ethernet0" -ServerAddresses 8.8.8.8

これを packer を使って WindowsServer 上で実行させます

テンプレートファイル修正

provisoners セクションに powershell を実行する設定を追加します

  • win2016.json
"provisioners": [
    {
        "type": "powershell",
        "execute_command": "{{ .Vars }} cmd /c C:/Windows/Temp/script.bat",
        "scripts": [
            "scripts/dns.ps1",
        ]
    }
]

type は powershell を指定します
windows-shell というタイプもありますが、それは .bat 用なので違います

execute_command はそのまま使いましょう
{{ .Vars }} は environment_vars という設定項目でセットした環境変数を参照するためのテンプレート変数です
今回は特に設定していないので何も入らないですが入れるのが基本らしいので入れておきます
そのあとの C:/Windows/Temp/script.bat ですが、これは scripts で指定した Powershell スクリプトが WindowsServer 側にアップロードされた際のパスを指定しています
remote_path という設定項目でアップロード先を指定できるのですが、今回は指定していません
指定を省略した場合はデフォルトの C:/Windows/Temp/script.bat が使われるため execute_command でもそのパスを指定する感じです

これで Powershell を呼び出すことができます

動作確認

実行して成功するか確認してみましょう
packer のログ的には以下のように表示されれば成功です

==> vmware-iso: Provisioning with Powershell...
==> vmware-iso: Provisioning with shell script: scripts/dns.ps1
    vmware-iso: #< CLIXML
    vmware-iso: <Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"><Obj S="progress" RefId="0"><TNRefId="0"><T>System.Management.Automation.PSCustomObject</T><T>System.Object</T></TN><MS><I64 N="SourceId">1</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS>
</Obj></Objs>

もし失敗するとしたら Powershell 内で指定している -InterfaceAlias "Ethernet0" の部分かと思います
ここで指定したネットワークアダプタ名がないとエラーになるので、自分の環境に合わせて変更してください

最後に

packer + Powershell で Windows サーバの DNS の設定を行ってみました
1 行で行えるので簡単でした

packer ビルド内でインターネットにアクセスするような処理がある場合に DNS で名前解決できない場合などで使えると思います
もしくは内部向けの DNS がないとイントラのホスト名を解決できない場合かなと思います

2017年10月21日土曜日

packer で WindowsServer2016 に vmware-tools をインストールしてみた

概要

packer はデフォルトだと vmware-tools のインストーラが入った圧縮ファイル windows.iso を Windows サーバ側にアップロードするところまでしかやってくれません
自動化する場合にはアップロードされた iso ファイルを解凍して setup.exe を実行するスクリプトを自分で作成する必要があります
今回はその方法を紹介したいと思います

環境

  • ESXi 6.0.0 (Build 3620759)
  • Ubuntu 16.0.4
  • packer 1.0.4

vmware-tools をインストールするバッチスクリプトの作成

ISO を展開して setup.exe を叩くバッチスクリプトです
下部で説明をしています

  • vim scripts/install_tools.bat
if not exist "C:\Windows\Temp\7z920-x64.msi" (
    powershell -Command "(New-Object System.Net.WebClient).DownloadFile('http://www.7-zip.org/a/7z920-x64.msi', 'C:\Windows\Temp\7z920-x64.msi')" <NUL
)
msiexec /qb /i C:\Windows\Temp\7z920-x64.msi

if not exist "C:\Windows\Temp\windows.iso" (
    powershell -Command "(New-Object System.Net.WebClient).DownloadFile('http://softwareupdate.vmware.com/cds/vmw-desktop/ws/12.0.0/2985596/windows/packages/tools-windows.tar', 'C:\Windows\Temp\vmware-tools.tar')" <NUL
    cmd /c ""C:\Program Files\7-Zip\7z.exe" x C:\Windows\Temp\vmware-tools.tar -oC:\Windows\Temp"
    FOR /r "C:\Windows\Temp" %%a in (VMware-tools-windows-*.iso) DO REN "%%~a" "windows.iso"
    rd /S /Q "C:\Program Files (x86)\VMWare"
)

cmd /c ""C:\Program Files\7-Zip\7z.exe" x "C:\Windows\Temp\windows.iso" -oC:\Windows\Temp\VMWare"
cmd /c C:\Windows\Temp\VMWare\setup.exe /S /v"/qn REBOOT=R\"

ちょっと長いですがやってることは単純です
まず 7z をインストールします
サイトからインストーラをダウンロードして msiexec コマンドでインストーラを実行してインストールします
7z をインストール理由は iso ファイルを展開するためです

そして次に vmware-tools が入っている iso をダウンロードし解凍します
C:\Windows\Temp\windows.iso に iso ファイルがあるかないか確認し、ない場合は VMware さんが公開している tools-windows.tar をダウンロードし解凍します
これで iso が取得できます

あとは iso を 7z で展開して vmware-tools のインストーラである setup.exe を実行しています
インストール処理はだいたい 30 分程度で終了します

テンプレートファイル修正

provisioners で上記のバッチスクリプトを実行します

  • vim win2016.json
"provisioners": [
    {
        "type": "windows-shell",
        "execute_command": "{{ .Vars }} cmd /c C:/Windows/Temp/script.bat",
        "scripts": [
            "scripts/install_tools.bat"
        ]
    }
]

まず type は windows-shell を指定します
他に shell というタイプもありますが、これは Linux 用のタイプなので違います
execute_command はこのまま使います
scripts で指定したバッチスクリプトは Windows サーバ側にアップロードされます
その際のアップロード先が C:/Windows/Temp/script.bat になります
これは remote_path でも設定できますが指定しない場合は上記のパスになります
あとは cmd で実行していくだけです

で実は以下の設定を builders に設定して実行していました

"tools_upload_flavor": "windows",
"tools_upload_path": "c:/Windows/Temp/windows.iso",

packer のドキュメントを見るとこれを指定すると ESXi 上にある windows.iso という vmware-tools が入った ISO を Windows サーバ側にアップロードしてくれるのですがどうもアップロードしてくれません
いろいろと調べるとこれ絡みの issue が見つかるのでバグの可能性もあるかもしれません (使い方が悪いだけかもしれません)

で本来はこれで Windows サーバ側に ISO がアップロードされるのでわざわざ VMware さんのサイトから tools-windows.tar をダウンロードする必要がなかったのですが、どうしてもアップロードできず泣く泣くダウンロード方式にしました
なので、本当はダウンロードする部分の処理はまるごと削除できます

動作確認

実行してみましょう
packer のログが長いので省略しますが iso が展開され setup.exe が実行されエラーがでなければ OK です

作成された vmx ファイルをデプロイして VM を起動すると vmware-tools がインストールされている状態で起動するのが確認できると思います

最後に

packer + WindowsServer2016 のビルドで vmware-tools の自動インストールを行ってみました
今回は vmware-toosl のインストーラを Web から取得する方式で行いました
またバッチスクリプトで実装していますが、まるっとそのまま Powershell に置き換えることもできると思います
provisioners 内にバッチやら Powershell やらいろいろと混在するのが嫌な方は書き直しても良いかと思います

ちなみに今回のバッチスクリプトは参考サイトにあるものを流用しているので、参考サイトにあるバッチスクリプトをそのまま使っても OK です

1 つアドバイスですが packer でプロビジョニング系のスクリプトを書く場合は一旦普通に動作している VM を作成するのをおすすめします
その VM でバッチやら Powershell やらを書いてそこで動作確認してから packer に組み込んだほうが効率が良いです
スクリプトを書き換えて毎回 packer build していると正直ビルド時間が非常にかかるので効率が悪いかなと思います

参考サイト

2017年10月18日水曜日

packer + WindowsServer2016 で vmxnet3 を使う

概要

前回 packer + esxi で WindowsServer2016 を自動構築してみました
しかし Windows2016 はデフォルトでネットワークドライバに vmxnet3 が使えません
packer ビルド時にドライバをインストールすれば使用することができたのでその方法を紹介します

環境

  • ESXi 6.0.0 (Build 3620759)
  • Ubuntu 16.0.4
  • packer 1.0.4

ドライバファイル

こちらです (GoogleDrive なので wget などはできません、手動でダウンロードしてサーバにアップロードしてください)
この中に inf ファイルが含まれています
WindowsServer2016 はこのファイルを自動実行してくれます
そうすることでビルド時にドライバを自動インストールします

テンプレートの修正

ほぼ同じなので一部だけ紹介します
ダウンロードした zip ファイルを展開して drivers 配下に配置します
そしてテンプレートファイル内の floppy_files に含めるようにします

zip ファイルのまま drivers 配下においても inf ファイルが見つからず自動で実行されないので、ちゃんと解凍したファイルたち (.dll や .inf ファイルなど) を drivers 配下に配置してください

"floppy_files": [
    "answer_files/Autounattend.xml",
    "drivers/",
    "scripts/winrm.ps1"
]

動作確認

これでビルドしてみましょう
もちろん Autounattend.xml や winrm.ps1 などもちゃんと配置して実行してください
うまくいくと vmxnet3 のドライバで動作する WindowsServer2016 が作成されると思います

最後に

packer + esxi + WindowsServer2016 で vmxnet3 ドライバを使用する方法を紹介しました
ドライバは以下の参考サイトで紹介されているものをそのまま使用しています
なくなっても問題ないようにキャッシュとして残しているだけなので、Github から持ってきても OK です
おそらく同様にストレージドライバなどをインストールすれば PVSCSI などを利用することもできると思います

参考サイト

2017年10月17日火曜日

packer を使って ESXi 上で WindowsServer2016 を自動構築してみた

概要

前回 Virtualbox 上で Windows Server 2016 の自動構築を行いました
今回は VMware ESXi 上でビルドして vmx + vmdk ファイルを作成してみたいと思います

環境

  • ESXi 6.0.0 (Build 3620759)
  • Ubuntu 16.0.4
  • packer 1.0.4

事前準備

Windows Server 2016 の ISO は事前にダウンロードしておいてください
過去にダウンロードの仕方を紹介しているので参考にしてください
packer を実行するマシン (今回であれば Ubuntu を使っています) 上に配置してください

前回同様 Windows の自動構築の仕組みは Autounattend.xml を使います
これは前回使用したものをそのまま流用できます

Autounattend.xml は Windows の OS 自動インストールを行うための仕組みなので Virtualbox であろうが ESXi であろうが同じものが使えて当然です
そして、内部で使用している WinRM を有効にする Powershell スクリプトも前回と同じものを流用します

テンプレートファイルの準備

ESXi 上で実行するテンプレートファイルを新規で作成します

  • win2016.json
{
    "builders": [{
        "type": "vmware-iso",
        "vm_name": "win2016",
        "guest_os_type": "windows8srv-64",
        "vmx_data": {
            "gui.fitguestusingnativedisplayresolution": "FALSE",
            "memsize": "2048",
            "numvcpus": "2",
            "virtualHW.version": "10",
            "scsi0.virtualDev": "lsisas1068",
            "ethernet0.networkName": "VM Network",
            "ethernet0.virtualDev": "e1000",
            "ethernet0.present": "TRUE",
            "ethernet0.connectionType": "custom",
            "ethernet0.vnet": "vmnet8",
            "ethernet0.startConnected": "TRUE"
        },
        "disk_size": 81920,
        "disk_type_id": "thin",
        "remote_type": "esx5",
        "remote_host": "192.168.100.101",
        "remote_datastore": "datastore12",
        "remote_username": "esxi_user",
        "remote_password": "esxi_password",
        "headless": "false",
        "iso_url": "/vol/win2016.ISO",
        "iso_checksum": "18a4f00a675b0338f3c7c93c4f131beb",
        "iso_checksum_type": "none",
        "communicator": "winrm",
        "winrm_username": "winuser1",
        "winrm_password": "winpass123",
        "winrm_timeout": "12h",
        "floppy_files": [
            "answer_files/Autounattend.xml",
            "scripts/winrm.ps1"
        ]
    }]
}

VirtualBox 時のテンプレートファイルと比較してポイントをいくつか説明します

まず type は vmware-iso を指定します
こうすることで VMware 環境 (今回は ESXi) 上でビルドを行うことができます
ESXi の情報は remote_type, remote_host, remote_datastore, remote_username, remote_password で設定しています

guest_os_type は Windodws8 のものを使用しています
とりあえずこれでも動作します

vmx_data で VM の構成を設定します
ここが一番のポイントです
まず scsi0.virtualDevlsisas1068 を指定してください
これは LSI Logic SAS というドライバなのですが、これでないとハードディスクをうまく認識することができません
これ以外のドライバを使いたい場合は別途ドライバをインストールする必要があります
次に ethernet0.virtualDeve1000 を指定してください
これも e1000 にしないとネットワークアダプタがうまく認識されず IP アドレスが取得できません
IP アドレスが取得できないと WinRM で接続もできないためビルドが失敗します

あとは "iso_checksum_type": "none" ですが、こうすることで ISO のアップロードを毎回行わないようにします
VirtualBox 時は md5 で指定していたのですが、md5 にするとなぜか ESXi に ISO を毎回アップロードしてしまいます
本来であればチェックサムの値が同じであれば既にアップロードしてある ESXi のデータストアにキャッシュされた ISO を使うのですが、なぜか使ってくれません
なので、ワークアラウンド的に none を指定しています

それ以外の項目に関しては前回の VirtualBox で使用したテンプレートとほぼ同じです

実行する

  • packer build win2016.json

で実行しましょう
問題なくビルドが完了すると指定したデータストア上に「output-vmware-iso」というディレクトリが作成されその配下に vmx ファイルと vmdk ファイルが保存されます
packer_vmware_win2016.jpg

今回のテンプレートの設定だとビルドが完了するとサーバは削除されてしまいます

最後に

packer を使って ESXi 上で Windows2016 をビルドしてみました
ハマったのは使用するドライバをテンプレートで指定する箇所で vmxnet3 や VMware Paravirtual (PVSCSI) を使用するとうまくデバイスが認識されませんでした

少し上記で述べましたが vmxnet3 にしていると Windows がネットワークアダプタを認識できず WinRM を使って packer から接続できずにビルドエラーとなります

ちなみに PVSCSI にしていると OS インストール時に Windows could not apply the unattend answer file's <DiskConfiguration> setting というエラーが発生します
うまくハードディスクが認識されないためパーティションの作成と設定に失敗しています
packer_vmware_win2016_2.jpg

この問題も頑張れば解決することができるらしいので解決できたらその方法を紹介したいと思います

2017年10月9日月曜日

packer + VirtualBox で Windows Server 2016 を自動構築してみた

概要

前回 VirtualBox 上に Windows Server 2016 を構築してみました
その際に OS のインストールは手動で行いました
Windows には OS を自動でインストールする仕組みとして Autounattend.xml を使う方法があります
今回は packer と Autounattend.xml を組み合わせて Windows Server 2016 のインストールの自動化を行ってみました

環境

  • macOS X 10.12.6
  • VirtualBox 5.1.26 r117224 (Qt5.6.2)
  • packer 1.0.4

テンプレートファイルの準備

まずは Json テンプレートを作成します
今回はプロビジョニングはせず OS をインストールの基本設定だけを自動化します
テンプレートの全容は以下の通りです

  • vim win2016.json
{
  "builders": [
    {
      "type": "virtualbox-iso",
      "vboxmanage": [
        [ "modifyvm", "{{.Name}}", "--memory", "2048" ],
        [ "modifyvm", "{{.Name}}", "--vram", "48" ],
        [ "modifyvm", "{{.Name}}", "--cpus", "2" ]
      ],
      "guest_additions_mode": "{{ user `guest_additions_mode` }}",
      "guest_os_type": "Windows2016_64",
      "headless": "{{ user `headless` }}",
      "iso_url": "{{ user `iso_url` }}",
      "iso_checksum": "{{ user `iso_checksum` }}",
      "iso_checksum_type": "md5",
      "communicator": "winrm",
      "winrm_username": "winuser1",
      "winrm_password": "winpass123",
      "winrm_timeout": "12h",
      "floppy_files": [
        "answer_files/Autounattend.xml",
        "scripts/winrm.ps1"
      ]
    }
  ],
  "variables": {
    "guest_additions_mode": "attach",
    "headless": "true",
    "iso_checksum": "18a4f00a675b0338f3c7c93c4f131beb",
    "iso_url": "/path/to/win2016.ISO"
  }
}

ISO はファイルは前回ダウンロードした ISO をそのまま使います
すでにローカルにあるのでローカルのパスを指定しています
もちろんここに URL を指定しても OK です

xml と ps1 ファイルはこのあと説明します

Autounattend.xml の準備

今回の肝になります
この XML ファイルを作成することで OS のインストールを自動化します
Linux で言うところの kickstart ファイルです
かなり長いですが全容は以下の通りです

<?xml version="1.0" encoding="UTF-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
   <settings pass="windowsPE">
      <!-- look for drivers on floppy -->
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <DriverPaths>
            <PathAndCredentials wcm:keyValue="1" wcm:action="add">
               <Path>A:\</Path>
            </PathAndCredentials>
         </DriverPaths>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <SetupUILanguage>
            <UILanguage>en-US</UILanguage>
         </SetupUILanguage>
         <InputLocale>en-US</InputLocale>
         <SystemLocale>en-US</SystemLocale>
         <UILanguage>en-US</UILanguage>
         <UILanguageFallback>en-US</UILanguageFallback>
         <UserLocale>en-US</UserLocale>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <DiskConfiguration>
            <Disk wcm:action="add">
               <CreatePartitions>
                  <CreatePartition wcm:action="add">
                     <Type>Primary</Type>
                     <Order>1</Order>
                     <Size>350</Size>
                  </CreatePartition>
                  <CreatePartition wcm:action="add">
                     <Order>2</Order>
                     <Type>Primary</Type>
                     <Extend>true</Extend>
                  </CreatePartition>
               </CreatePartitions>
               <ModifyPartitions>
                  <ModifyPartition wcm:action="add">
                     <Active>true</Active>
                     <Format>NTFS</Format>
                     <Label>boot</Label>
                     <Order>1</Order>
                     <PartitionID>1</PartitionID>
                  </ModifyPartition>
                  <ModifyPartition wcm:action="add">
                     <Format>NTFS</Format>
                     <Label>Windows 2016</Label>
                     <Letter>C</Letter>
                     <Order>2</Order>
                     <PartitionID>2</PartitionID>
                  </ModifyPartition>
               </ModifyPartitions>
               <DiskID>0</DiskID>
               <WillWipeDisk>true</WillWipeDisk>
            </Disk>
         </DiskConfiguration>
         <ImageInstall>
            <OSImage>
               <InstallFrom>
                  <MetaData wcm:action="add">
                     <Key>/IMAGE/NAME</Key>
                     <Value>Windows Server 2016 SERVERDATACENTER</Value>
                  </MetaData>
               </InstallFrom>
               <InstallTo>
                  <DiskID>0</DiskID>
                  <PartitionID>2</PartitionID>
               </InstallTo>
            </OSImage>
         </ImageInstall>
         <UserData>
            <ProductKey>
               <WillShowUI>OnError</WillShowUI>
            </ProductKey>
            <AcceptEula>true</AcceptEula>
            <FullName>winuser1</FullName>
            <Organization>winuser</Organization>
         </UserData>
      </component>
   </settings>
   <settings pass="generalize">
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <SkipRearm>1</SkipRearm>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-PnpSysprep" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <PersistAllDeviceInstalls>false</PersistAllDeviceInstalls>
         <DoNotCleanUpNonPresentDevices>false</DoNotCleanUpNonPresentDevices>
      </component>
   </settings>
   <settings pass="oobeSystem">
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <InputLocale>en-US</InputLocale>
         <SystemLocale>en-US</SystemLocale>
         <UILanguage>en-US</UILanguage>
         <UserLocale>en-US</UserLocale>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <OOBE>
            <HideEULAPage>true</HideEULAPage>
            <HideLocalAccountScreen>true</HideLocalAccountScreen>
            <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
            <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
            <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
            <NetworkLocation>Home</NetworkLocation>
            <ProtectYourPC>1</ProtectYourPC>
         </OOBE>
         <TimeZone>UTC</TimeZone>
         <UserAccounts>
            <AdministratorPassword>
               <Value>adminpass</Value>
               <PlainText>true</PlainText>
            </AdministratorPassword>
            <LocalAccounts>
               <LocalAccount wcm:action="add">
                  <Password>
                     <Value>winpass123</Value>
                     <PlainText>true</PlainText>
                  </Password>
                  <Group>administrators</Group>
                  <DisplayName>winuser1</DisplayName>
                  <Name>winuser1</Name>
                  <Description>Windows User 1</Description>
               </LocalAccount>
            </LocalAccounts>
         </UserAccounts>
         <AutoLogon>
            <Password>
               <Value>winpass123</Value>
               <PlainText>true</PlainText>
            </Password>
            <Enabled>true</Enabled>
            <Username>winuser1</Username>
         </AutoLogon>
         <FirstLogonCommands>
            <SynchronousCommand wcm:action="add">
               <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\winrm.ps1</CommandLine>
               <Order>1</Order>
            </SynchronousCommand>
         </FirstLogonCommands>
      </component>
   </settings>
   <settings pass="specialize">
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-ServerManager-SvrMgrNc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-IE-ESC" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <IEHardenAdmin>false</IEHardenAdmin>
         <IEHardenUser>false</IEHardenUser>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-OutOfBoxExperience" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon>
      </component>
   </settings>
</unattend>

自分もすべてを把握しているわけではないですが主に行っているのは

  • Administrator のパスワードの設定
  • 新規ユーザの作成 (winuser1/winpass123)
  • OS をインストールするパーティションの設定
  • winuser1 での Windows への自動ログイン
  • タイムゾーンの設定
  • 言語の設定
  • OOBE (Out-Of-Box Experience) の設定
  • フロッピーにマウントした WinRM を有効にするスクリプトの実行

になります
詳細はそれぞれの XML のタグ名で検索すれば出ると思います

ちょっと余談ですがこんなクソ長い XML を手動で作成するわけにはいきません
普通は Windows System Image Manager と ISO を使って XML を生成するみたいです
でもその手順はかなり面倒なので、調べてみたら Web 上で XML を生成できるサービスがありました

ただ、すべてを網羅しているわけではないのでちゃんと作成するのであれば結局公式のドキュメントを見ながら頑張るしかないと思います

ちなみに自分は参考サイトにある Github のリポジトリから引っ張ってきました

WinRM を有効にする PowerShell の準備

WinRM を有効にするのは packer でプロビジョニングしない場合でも必須です

  • mkdir scripts
  • vim scripts/winrm.ps1
netsh advfirewall firewall add rule name="WinRM-HTTP" dir=in localport=5985 protocol=TCP action=allow
winrm set winrm/config/service/auth '@{Basic="true"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'

Windows ファイアウォールに WinRM で通信できる穴を開けています
これは先ほども説明したように Autounattend.xml 内で実行しています

実行

準備完了です
実行してみましょう

  • packer build win2016.json

成功すると以下のようになります

virtualbox-iso output will be in this color.

Warnings for build 'virtualbox-iso':

* A shutdown_command was not specified. Without a shutdown command, Packer
will forcibly halt the virtual machine, which may result in data loss.

==> virtualbox-iso: Downloading or copying Guest additions
    virtualbox-iso: Downloading or copying: file:///Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso
==> virtualbox-iso: Downloading or copying ISO
    virtualbox-iso: Downloading or copying: file:///Users/hawksnowlog/Documents/work/packer/windows/win2016.ISO
==> virtualbox-iso: Creating floppy disk...
    virtualbox-iso: Copying files flatly from floppy_files
    virtualbox-iso: Copying file: answer_files/Autounattend.xml
    virtualbox-iso: Copying file: scripts/winrm.ps1
    virtualbox-iso: Done copying files from floppy_files
    virtualbox-iso: Collecting paths from floppy_dirs
    virtualbox-iso: Resulting paths from floppy_dirs : []
    virtualbox-iso: Done copying paths from floppy_dirs
==> virtualbox-iso: Creating virtual machine...
==> virtualbox-iso: Creating hard drive...
==> virtualbox-iso: Attaching floppy disk...
==> virtualbox-iso: Creating forwarded port mapping for communicator (SSH, WinRM, etc) (host port 3950)
==> virtualbox-iso: Executing custom VBoxManage commands...
    virtualbox-iso: Executing: modifyvm packer-virtualbox-iso-1507116947 --memory 2048
    virtualbox-iso: Executing: modifyvm packer-virtualbox-iso-1507116947 --vram 48
    virtualbox-iso: Executing: modifyvm packer-virtualbox-iso-1507116947 --cpus 2
==> virtualbox-iso: Starting the virtual machine...
    virtualbox-iso: The VM will be run headless, without a GUI. If you want to
    virtualbox-iso: view the screen of the VM, connect via VRDP without a password to
    virtualbox-iso: rdp://127.0.0.1:5959
==> virtualbox-iso: Waiting 10s for boot...
==> virtualbox-iso: Typing the boot command...
==> virtualbox-iso: Waiting for WinRM to become available...
==> virtualbox-iso: Connected to WinRM!
==> virtualbox-iso: Uploading VirtualBox version info (5.1.26)
==> virtualbox-iso: Halting the virtual machine...
    virtualbox-iso: Removing floppy drive...
    virtualbox-iso: Removing guest additions drive...
==> virtualbox-iso: Preparing to export machine...
    virtualbox-iso: Deleting forwarded port mapping for the communicator (SSH, WinRM, etc) (host port 3950)
==> virtualbox-iso: Exporting virtual machine...
    virtualbox-iso: Executing: export packer-virtualbox-iso-1507116947 --output output-virtualbox-iso/packer-virtualbox-iso-150711
6947.ovf
==> virtualbox-iso: Unregistering and deleting virtual machine...
Build 'virtualbox-iso' finished.

==> Builds finished. The artifacts of successful builds are:
--> virtualbox-iso: VM files in directory: output-virtualbox-iso

作成される成果物は以下の通りです
ovf と vmdk が出来上がりました

  • ls -ltr output-virtualbox-iso/
total 9132296
-rw-------  1 hawksnowlog  staff        7076 10  4 20:43 packer-virtualbox-iso-1507116947.ovf
-rw-------  1 hawksnowlog  staff  4675725312 10  4 20:50 packer-virtualbox-iso-1507116947-disk001.vmdk

試しに ovf を VirtualBox に展開してみると良いと思います
winuser1/winpass123 でログインして Windows Server 2016 が立ち上がってくるのが確認できると思います
ちなみに今回の Windows Server は「Datacenter Evaluation」として構築されます

最後に

packer + Autounattend.xml で Windows Server 2016 の OS インストールを自動化してみました
本当はこのあと chef なり powershell を使ってミドルウェアや OS 上のプロビジョニングを行います
プロビジョニングは結局 WinRM を使うので今回のビルドが成功すればプロビジョニングまではすぐにいくと思います

Github にあるサンプルは chef-solo を使っています
chef-solo を選択すると Windows サーバ上に chef-solo コマンドがインストールされてしまうので注意が必要です

またプロビジョニング用のスクリプトを作成するときは一旦 Windows を立ててその中で try & error を繰り返したほうが効率が良いと思います

参考サイト

2017年9月26日火曜日

user: could not determine current user from environment

概要

packer でプラグインを docker 上で動作させる際に発生しました
原因と対処方法を紹介します

環境

  • Ubuntu 16.04.2
  • docker 17.03.0-ce
  • packer 1.1.0

原因

まず原因ですが、USER 環境変数が設定されていないのが原因です
docker コンテナの場合 USER 環境変数はデフォルトで設定されていません
これが殻の場合以下の部分でエラーになります
https://github.com/hashicorp/packer/blob/master/provisioner/ansible/provisioner.go#L146

対処方法

単純に USER を設定してあげれば OK です
Dockerfile ないのどこかで以下を追加してあげましょう

ENV USER root

これで docker コンテナ上でも packer のプラグインが使えるようになります
正直これでいいのかは何ともですがとりあえず今回のエラーを回避したい場合には使えると思います

2017年9月24日日曜日

packer + kickstart でフロッピーを使う方法

概要

過去に CentOS7 を kickstart ファイルを使ってビルドしました
その際に kickstart ファイルは http でホスティングして取得しました
今回は kickstart ファイルをフロッピーに格納して、フロッピー上の kickstart ファイルを指定する方法を紹介します

環境

  • Ubuntu Ubuntu 16.04.2
  • packer 1.0.4
  • VMware ESXi 6.0.0
  • CentOS 7 (ビルド対象)

テンプレートファイル

  • vim centos7_with_floppy.json
{
    "builders": [
    {
        "name": "centos7",
        "type": "vmware-iso",

        "vm_name": "centos7_from_packer",
        "guest_os_type": "rhel7-64",
        "ssh_username": "root",
        "ssh_password": "vm_password",
        "ssh_timeout": "15m",

        "iso_url": "http://ftp.jaist.ac.jp/pub/Linux/CentOS/7/isos/x86_64/CentOS-7-x86_64-Minimal-1708.iso",
        "iso_checksum": "bba314624956961a2ea31dd460cd860a77911c1e0a56e4820a12b9c5dad363f5",
        "iso_checksum_type": "sha256",

        "shutdown_command": "echo 'shutdown -P now' > shutdown.sh; echo 'vm_password'|sudo -S sh 'shutdown.sh'",
        "boot_command": [
        "<tab> text ks=hd:fd0:/centos7.ks<enter><wait>"
        ],
        "floppy_files": [
            "centos7.ks"
        ],
        "tools_upload_flavor": "linux",
        "headless": false,
        "keep_registered": true,

        "remote_type": "esx5",
        "remote_host": "192.168.100.105",
        "remote_datastore": "datastore1",
        "remote_username": "root",
        "remote_password": "esxi_password",
        "disk_type_id": "thin",
        "vmx_data": {
        "ethernet0.networkName": "VM Network"
        },

        "vnc_port_min": "5900",
        "vnc_port_max": "5911",
        "vnc_bind_address": "0.0.0.0",
        "vnc_disable_password": "true"
    }
    ]
}

ほとんど前回と変わっていないようですが変わっているのは以下の部分です

"boot_command": [
"<tab> text ks=hd:fd0:/centos7.ks<enter><wait>"
],
"floppy_files": [
    "centos7.ks"
],

centos7.ks はこちらの内容です
ローカルに配置した centos7.ks ファイルを ESXi にアップロードしてそのままフロッピーにマウントすることで VM から参照できるようにしています

あとは実行するだけです
このほうがわざわざ http を立てる必要がないので良さそうです

そしてフロッピードライブはビルドが終了するとちゃんと vmx ファイルからアンマウントしてくれるため VM として登録するときにもフロッピーディスクがないのが嬉しい点です

最後に

CentOS7 の自動インストール時に kickstart ファイルをフロッピードライブから参照する方法を紹介しました
最終的に同じものができあがるのを考えるとフロッピーを使ったほうが何かと便利そうな気がします

特に Docker 連携をする際に良さそう (IP を気にしなくていいので)
packer を docker 上で動かす方法もわかったら紹介したいと思います

参考サイト

2017年9月22日金曜日

packer のビルドフロー中に serverspec でテストする方法

概要

packer の provisioners でインストールしたパッケージなどを serverspec でテストしたということはよくあると思います
イメージなどを作成後に VM として起動して serverspec を実行する手法はよくあると思いますが少し面倒くさいです
今回は packer build 内で serverspec を実行する方法を紹介したいと思います

環境

  • macOS X 10.12.6
  • packer 1.0.4
  • go 1.8
  • serverspec 2.40.0

serverspec 準備

今回は serverspec のテストも 1 から作成してみたいと思います

  • bundle init
  • vim Gemfile
gem "serverspec"
  • bundle install
  • serverspec-init
  1) UN*X
  2) Windows

Select number: 1

Select a backend type:

  1) SSH
  2) Exec (local)

Select number: 2

 + spec/
 + spec/localhost/
 + spec/localhost/sample_spec.rb
 + spec/spec_helper.rb
 + Rakefile
 + .rspec

ここで 1 つポイントですが実行するホストは localhost にしましょう
要するにビルド中に作成された VM (localhost) に対して実行するようにします

  • vim spec/localhost/sample_spec.rb
require 'spec_helper'

describe package('httpd'), :if => os[:family] == 'redhat' do
  it { should be_installed }
end
  • vim spec/spec_helper.rb
require 'serverspec'
require 'net/ssh'

options = Net::SSH::Config.for(host, [])
options[:user] = ENV['TARGET_USER']
options[:keys] = ENV['TARGET_KEY']
options[:host_name] = ENV['TARGET_HOST']
options[:port] = ENV['TARGET_PORT']
options[:paranoid] = false unless ENV['SERVERSPEC_HOST_KEY_CHECKING'] =~ (/^(true|t|yes|y|1)$/i)

set :host,         options[:host_name]
set :ssh_options,  options
set :backend,      :ssh
set :display_sudo, true
set :request_pty,  true

sample_spec.rb と spec_helper.rb はとりあえず上記をそのまま利用してください

プラグインのインストール

今回 Github で公開されている packer-provisioner-serverspec を使います

  • go get github.com/unifio/packer-provisioner-serverspec
  • mkdir $HOME/.packer.d/plugins
  • cp $GOPATH/bin/packer-provisioner-serverspec $HOME/.packer.d/plugins

で OK です

テンプレートファイルの作成

  • vim centos7_with_serverspec.json
{
    "builders": [
    {
        "type": "virtualbox-iso",
        "vboxmanage": [
        [ "modifyvm", "{{.Name}}", "--memory", "2048" ],
        [ "modifyvm", "{{.Name}}", "--nic1", "nat" ],
        [ "modifyvm", "{{.Name}}", "--nic2", "hostonly" ],
        [ "modifyvm", "{{.Name}}", "--hostonlyadapter2", "vboxnet0"]
        ],
        "iso_checksum": "27bd866242ee058b7a5754e83d8ee8403e216b93d130d800852a96f41c34d86a",
        "iso_checksum_type": "sha256",
        "iso_url": "http://ftp.riken.jp/Linux/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-1611.iso",
        "ssh_username": "root",
        "ssh_password": "password",
        "ssh_wait_timeout": "40m",
        "disk_size": "8000",
        "guest_os_type": "RedHat_64",
        "shutdown_command": "/sbin/shutdown -h now",
        "shutdown_timeout": "20s",
        "vm_name": "centos7_from_packer",
        "boot_command": [
        "<tab> text ks=http://192.168.56.101/centos.ks<enter><wait>"
        ]
    }
    ],
    "provisioners": [
    {
        "type": "shell",
        "inline": ["yum install -y vim httpd"]
    },
    {
        "type": "serverspec",
        "rake_file": "Rakefile",
        "rake_task": "spec:all",
        "rake_env_vars": "$BUNDLE_GEMFILE=Gemfile"
    }
    ]
}

基本は過去に CentOS7 をビルドしたテンプレートを使っています
またテンプレートを作成する場所は serverspec-init を実行したパスと同じ場所に配置してください

ポイントは provisioners に "type": "serverspec" が追加されている点です
プラグインをインストールすることでこのタイプが使えるようになります

また、今回は OS のインストールも自動化することを想定しているので kickstart サーバも使っています
kickstart サーバの構築に関してはこちらを御覧ください

動作確認

  • packer build centos7_with_serverspec.json

でいろいろとログが流れます
長いので割愛しますが流れとしては

ISO 取得 -> VM 起動 -> OS インストール -> SSH 接続 -> provisioner 実行 (yum) -> provisioner 実行 (serverspec)

になります
最終的に serverspec が実行されてエラーが出なければ成功です

試しに作成されたイメージを一度起動して VM の中を確認してみましょう
(今回は Virtualbox を使っているので仮想アプライアンスのインポートから作成された ovf を選択すれば OK です)
今回の場合であれば httpd がインストールされていれば OK となります
また、今回の手順の場合作成されたイメージないに serverspec コマンドはインストールされません
packer_with_serverspec1.png

最後に

プラグインを使って packer + serverspec でビルド中にイメージのテストを実施してみました
こっちのほうが手順としても packer build 1 回で済むのでスマートかなと思います

いろいろと調べてみると packer + serverspec を連携する方法は出てきますがビルドするイメージ内に serverspec をインストールする方法が結構多いです
それでも特に問題はないですが ruby など使わないのであれば、あまり入れたいとは思いません
今回の手順はイメージ内に serverspec をインストール必要がないのも嬉しい点かなと思います

少し心配な点があるとすれば今回使ったプラグインがあまりメンテナンスされていない点でしょうか、、、

参考サイト

2017年9月19日火曜日

packer + esxi で CentOS7 の ISO から vmx と vmdk ファイルを作成してみた

概要

前回 Ubuntu で試しました
今回は CentOS で試したので JSON テンプレートの紹介をしたいと思います

環境

  • Ubuntu Ubuntu 16.04.2
  • packer 1.0.4
  • VMware ESXi 6.0.0

事前準備

JSON テンプレート

  • vim centos7.json
{
    "builders": [
    {
        "name": "centos7",
        "type": "vmware-iso",

        "vm_name": "centos7_from_packer",
        "guest_os_type": "rhel7-64",
        "ssh_username": "root",
        "ssh_password": "vm_password",
        "ssh_timeout": "15m",

        "iso_url": "http://ftp.jaist.ac.jp/pub/Linux/CentOS/7/isos/x86_64/CentOS-7-x86_64-Minimal-1708.iso",
        "iso_checksum": "bba314624956961a2ea31dd460cd860a77911c1e0a56e4820a12b9c5dad363f5",
        "iso_checksum_type": "sha256",

        "shutdown_command": "echo 'shutdown -P now' > shutdown.sh; echo 'vm_password'|sudo -S sh 'shutdown.sh'",
        "boot_command": [
        "<tab> text ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos7.ks<enter><wait>"
        ],
        "http_directory": "./",
        "tools_upload_flavor": "linux",
        "headless": false,
        "keep_registered": true,

        "remote_type": "esx5",
        "remote_host": "192.168.100.105",
        "remote_datastore": "datastore1",
        "remote_username": "root",
        "remote_password": "esxi_password",
        "disk_type_id": "thin",
        "vmx_data": {
        "ethernet0.networkName": "VM Network"
        },

        "vnc_port_min": "5900",
        "vnc_port_max": "5911",
        "vnc_bind_address": "0.0.0.0",
        "vnc_disable_password": "true"
    }
    ]
}

詳細に説明

メタデータ

  • name・・・このビルドの名称、packer は並列ビルドが可能でどのビルドかをこの name で識別します
  • type・・・どのビルドタイプを使うか指定します、今回は「vmware-iso」を使いましたが他にも docker や amazon-ebs などたくさんのビルドタイプがあります、今回のタイプはダウンロードした ISO を ESXi でビルドし vSphere 環境で動作する vmx ファイルと vmdk ファイルを作成するためのタイプです

作成する VM の情報

  • vm_name・・・VM の名前
  • guest_os_type・・・vSphere 環境で扱われる OS のタイプを指定します、今回は RedHat 系の OS なので「rhel7-64」を指定しています、他にも ubuntu-64 や other などがあります
  • ssh_username・・・プロビジョニングするために作成した VM に SSH ログインするためのユーザ名です、OS インストール時に作成したユーザ名と同じにする必要があります
  • ssh_password・・・プロビジョニングするために作成した VM に SSH ログインするためのパスワードです、OS インストール時と設定したパスワードと同じにする必要があります
  • ssh_timeout・・・SSH のタイムアウト時間です、この時間内に VM と SSH のコネクションが確立されないとビルドエラーとなります

ISO 情報

  • iso_url・・・ダウンロードする ISO の URLです、ここで指定した ISO をダウンロードして packer はビルドします
  • iso_checksum・・・ダウンロードする ISO のチェックサムです、チェックサムが間違っているとビルドエラーとなります
  • iso_checksum_type・・・チェックサムのタイプを指定します

ビルドオプション

  • shutdown_command・・・すべてのプロビジョニングが完了した後に実行するシャットダウンコマンドを指定します
  • boot_command・・・ISO から OS をインストールする際のオプションを指定します、GRUB 画面を直接制御することができる特殊なコマンドが用意されており、ここで kickstart サーバを指定します
  • http_directory・・・これを指定することで packer 自信が HTTP サーバになることができます、HTTP サーバとして立ち上がった際のバインドされる IP とポートはそれぞれ {{ .HTTPIP }}{{ .HTTPPort }} に格納されます、このオプションでは HTTP サーバの DocumentRoot となるパスを指定します
  • tools_upload_flavor・・・VMware tools のタイプを指定します、他に windows や darwin が指定できます
  • headless・・・ビルド時にコンソールを使うか使わないか指定できます、今回の場合は kickstart を使って OS をインストールするため true でも問題ないです、false にすることでコンソールを確認すると OS のインストール画面が確認できるのでデバッグに役立ちます
  • keep_registered・・・ビルド完了後にサーバを削除するかしないか指定できます、true にするとサーバはシャットダウン後削除されません

ESXi 情報

  • remote_type・・・「esx5」を絶対指定しましょう、それ以外の指定ではエラーとなります
  • remote_host・・・ビルドする ESXi の IP を指定します
  • remote_datastore・・・ダウンロードする ISO を格納したり、成果物となる vmx や vmdk を格納する ESXi のデータストアを指定します
  • remote_password・・・ESXi に SSH ログインするための root パスワードを指定します
  • disk_type_id・・・VM を作成する際のディスクタイプを指定します、thin の場合はシンプロビジョニングが適用されます、他には zeroedthick, eagerzeroedthick などが指定できます、0 - 5 の数字でも指定できます
  • vmx_data・・・VM の構成を細かく設定することができます、CPU やメモリネットワークや接続する外部記憶デバイスを指定することができます、指定するフォーマットは VMware に準拠するため詳細は VMware のドキュメントを確認する必要があります、ethernet0.networkName は 1 枚目の NIC を指定することができます

VNC 関係

  • vnc_port_min・・・ビルド時に作成される VM が LISTEN する VNC サーバに使用される最小ポート番号を指定します
  • vnc_port_max・・・ビルド時に作成される VM が LISTEN する VNC サーバに使用される最大ポート番号を指定します、今回の場合 VM は 5900 から 5911 番の間で VNC サーバを LISTEN します
  • vnc_bind_address・・・ビルド時に作成される VM が LISTEN する VNC サーバのバインド IP を指定します
  • vnc_disable_password・・・VNC サーバのパスワード認証を使うか使わないか指定します、true の場合認証を使いません

VNC に関して少し補足として vSphere 環境に作成される VM にはオプションで VNC サーバを立ち上げることができます
もし VM に VNC を立ち上げるとコンソールの情報を VNC でも確認することができます
packer はデフォルトで VNC 接続を使うので VNC 関連のオプションを指定する必要があります

ビルド

  • packer build centos7.json

成果物の保存場所

  • ls /vmfs/volumes/datastore12/output-centos7

ちなみに再度ビルドする場合 output-centos7 フォルダがあるとビルドエラーになるので事前に削除しておきましょう

最後に

packer + esxi で CentOS をビルドしてみました
基本的な操作を確認したかったので、変数の展開やプロビジョニングはしませんでした
興味があればドキュメントを確認しながら実施すれば簡単にできると思います

参考サイト

2017年9月13日水曜日

packer と kickstart を連携して OS のインストールを自動化してみた

概要

前回 packer + Virtualbox を使って ISO から ovf + vmdk ファイルを作成してみました
その中で OS のインストールは手動でやらなければいけないという問題がありました
実は以前 Virtualbox 上に kickstart サーバを構築しており今回はこの kickstart サーバを使って OS のインストール作業も自動化してみました

環境

  • macOS X 10.12.6
  • packer 1.0.4
  • Virtualbox 5.1.26 r117224 (Qt5.6.2)

kickstart サーバの構築

これは過去の記事を参考にしてください
今回の記事では過去に作成した kickstart サーバをそのまま流用します

テンプレートファイルの編集

packer には boot_command という機能がありこれを使うことで VM が起動した際の GRUB の画面などを操作することができます

これを使って OS インストール時に kickstart サーバを指定します

  • vim centos7_with_ks.json
{
  "builders": [
    {
      "type": "virtualbox-iso",
      "vboxmanage": [
        [ "modifyvm", "{{.Name}}", "--memory", "2048" ],
        [ "modifyvm", "{{.Name}}", "--nic1", "nat" ],
        [ "modifyvm", "{{.Name}}", "--nic2", "hostonly" ],
        [ "modifyvm", "{{.Name}}", "--hostonlyadapter2", "vboxnet0"]
      ],
      "iso_checksum": "27bd866242ee058b7a5754e83d8ee8403e216b93d130d800852a96f41c34d86a",
      "iso_checksum_type": "sha256",
      "iso_url": "http://ftp.riken.jp/Linux/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-1611.iso",
      "ssh_username": "root",
      "ssh_password": "password",
      "ssh_wait_timeout": "40m",
      "disk_size": "8000",
      "guest_os_type": "RedHat_64",
      "shutdown_command": "/sbin/shutdown -h now",
      "shutdown_timeout": "20s",
      "vm_name": "centos7_from_packer",
      "boot_command": [
        "<tab> text ks=http://192.168.56.101/centos.ks<enter><wait>"
      ]
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "inline": [
        "nmcli con mod enp0s3 connection.autoconnect 'yes'",
        "systemctl restart NetworkManager",
        "systemctl restart network"
      ]
    },
    {
      "type": "shell",
      "inline": ["yum install -y vim"]
    }
  ]
}

ポイントは boot_command の部分です

"boot_command": [
  "<tab> text ks=http://192.168.56.101/centos.ks<enter><wait>"
]

boot_command では特殊なタグを使用してカーソルの移動やキーストロークを行います
今回は Tab キーを一度押した後「ks=http://192.168.56.101/centos.ks」というテキストを打ち込み、Enter を入力して待つという処理を行わせています
実際に Virtualbox のコンソールを眺めているとわかるのですが自動で入力されているのがわかると思います

CentOS7 の Minimal ISO の場合、OS インストール時のデフォルトのカーソルがイメージのテストをしてからインストールという流れになっているので一度 <up> してからコマンドを打ち込んでも良いかなと思います

実行

  • packer build centos7_with_ks.json

実行すると ISO のダウンロード -> VM の作成 -> 起動 (Virtualbox のコンソールも起動) という流れで VM の作成が始まります
今回は kickstart サーバを指定しているので、OS のインストール画面も自動で進みます

OS のインストールが完了すると自動で再起動されます (これは kicksatrt で指定しています)
そして再起動後 IP が取得できるとプロビジョニングの処理がはじまり SSH を開始します
そしてプロビジョニングも問題なく終了すると output-virtualbox-iso 配下に vmdk と ovf ができあがっています

最後に

packer と kicksatrt を連携して ISO から ovf の作成の流れを完全に自動化してみました
今回は本当に単純な処理しかしていないので、時間も 20 分から 30 分程度で終了します
が、プロビジョニングが長かったりダウンロードする ISO が非常に大きかったりすると 1 回のビルドで 1 時間や 2 時間平気でかかってくると思います
その辺はかなり辛いポイントかなと思います

結局 packer もトライアンドエラーを繰り返してテンプレートを作成していく感じになると思うので、次のトライまでに数時間待たないといけないとなると作業効率も下がってくるかなと思います

OS のインストール処理が絡んでくるのでどうしても長くなりがちなので仕方ないと言えば仕方ないのかもしれませんが、、、

参考サイト

2017年9月12日火曜日

packer + Virtualbox で ISO から ovf ファイルを作成してみる

概要

Virtualbox で VM を作成する場合 ISO が必要になります
そして Virtualbox 上で作成した VM は ovf 形式にエクスポートすることができます
この流れは Virtualbox だけでも可能ですが packer を使うことで一連の流れを自動化することができます

環境

  • macOS X 10.12.6
  • packer 1.0.4

事前準備

packer のインストール Virtualbox のインストールを行っておいてください
自分は Mac 上でビルドするので packer は homebrew と Virtualbox は公式のインストーラを使ってインストールしました

テンプレート Json の作成

今回は CentOS7 の ovf ファイルを最終的に作成します
CentOS7 のインストール用 ISO をダウンロードしてそこから ovf を作成します

  • vim centos7.json
{
    "builders": [{
        "type": "virtualbox-iso",
        "vboxmanage": [
            ["modifyvm", "{{.Name}}", "--memory", "2048"],
            ["modifyvm", "{{.Name}}", "--nic1", "nat"],
            ["modifyvm", "{{.Name}}", "--nic2", "hostonly"],
            ["modifyvm", "{{.Name}}", "--hostonlyadapter2", "vboxnet0"]
        ],
        "iso_checksum": "27bd866242ee058b7a5754e83d8ee8403e216b93d130d800852a96f41c34d86a",
        "iso_checksum_type": "sha256",
        "iso_url": "http://ftp.riken.jp/Linux/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-1611.iso",
        "ssh_username": "root",
        "ssh_password": "password",
        "ssh_wait_timeout": "40m",
        "disk_size": "8000",
        "guest_os_type": "RedHat_64",
        "shutdown_command": "/sbin/shutdown -h now",
        "shutdown_timeout": "20s",
        "vm_name": "centos7_from_packer"
    }],
    "provisioners": [{
        "type": "shell",
        "inline": ["yum install -y vim"]
    }]
}

簡単な解説

builder の type に virtualbox-iso を指定することで Virtualbox 上で ISO から VM を作成し ovf を作成することができます
ISO はネットからダウンロードできる Minimal の ISO を使います
ダウンロードされた ISO は packer のキャッシュとして以下のディレクトリに保存されます

./packer_cache/c01a0f674526c96fe4c941774a9f761f6c51e5346004457aa50aa802d978a772.iso

vboxmanage を使って Virtualbox 上に作成される VM の設定を変更する必要があります
今回 yum install をするので VM がインターネットに接続できる必要があります
かつ、packer を実行している Mac から VM に対して SSH 接続できる必要があります
なので「nat」と「hostonly」のネットワークを接続しています

あと、ssh_username と ssh_password はこのあと設定する OS のインストールで使用します
CentOS7 のインストールの設定の際に root ユーザのパスワードを決める必要がありますが、それをテンプレート内と同じ値にしないと VM に SSH できなくなるので気をつけてください

実行してみる

では実行してみます

packer build

  • packer build centos7.json

実行するとまず ISO のダウンロードが始まります
ダウンロードが完了すると Virtualbox 上に VM が作成されて OS のインストール画面が起動します

手動で OS のインストールを行う

今回の場合、残念ながらここはどうしても手動で行う必要があります
この手動の作業を自動化したい場合は別途 kickstart サーバを用意する必要があります
packer + kickstart を連携して OS のインストールを自動化する方法は別記事で紹介したいと思います

今回の場合、手動で設定する項目もそれほど多くないのでちゃちゃっと手動で設定してしまいましょう
設定するのはシステムのインストール先のパーティションと root パスワードとネットワーク設定になります 
ただ、特に注意しなければならないのはネットワークの設定です
デフォルトだと追加した 2 つのネットワークは切断状態になっています
そのため再起動後に SSH 経由で実行するプロビジョニングが失敗してしまいます
なので、OS インストール時の設定で接続した 2 つのネットワークは必ず接続するようにしてください

※どうしても SSH できない、ネットワークが上がらない場合は再起動して VM が上がったらコンソールからログインして接続してあげましょう

自動でプロビジョニングが始まるのを確認する

OS のインストールが完了し VM を手動で再起動したらプロビジョニングが始まります
今回は簡単な yum install だけなのですぐ終わると思います

確認のため終わったら VM を起動して SSH でログインしてみましょう
packer のテンプレートで指定した yum install -y vim がちゃんと実行されているはずです

成果物 (ovf) を確認する

packer build が完了したら目的の ovf + vmdk ができあがっているはずです

  • ls -ltr output-virtualbox-iso/
total 1157712
-rw-------  1 hawksnowlog  staff       7878  9 11 16:38 centos7_from_packer.ovf
-rw-------  1 hawksnowlog  staff  592738304  9 11 16:39 centos7_from_packer-disk001.vmdk

あとはこれを Virtualbox や vSpehre 環境にデプロイすれば VM として使うことができます

最後に

packer + Virtualbox を使って vmdk + ovf ファイルを作成してみました
自分がいちばん躓いたのはプロビジョニングのところで OS インストールし再起動後 VM に接続できない現象にハマリました
なぜかネットワークが disconnected になってしまったので最後はコンソールからログインして SSH のタイムアウトになる前にネットワークを起動しました

次回は今回の構成に kickstart サーバを連携して OS のインストール部分を自動化してみたいと思います

参考サイト