Packerを使ったISOイメージからの仮想マシン自動デプロイ

PackerにはVirtualBoxやQEMU(KVMおよびXen)などの仮想マシンイメージを作成する機能が用意されており、仮想マシン作成を自動化できる。今回は、Packerを使ってVirtualBoxおよびQEMU(KVM)用の仮想マシンにOSをインストールしてディスクイメージを作成する例を紹介する。

Packerを使って各種仮想マシン用のディスクイメージを作る

前回記事ではPackerを使ってDocker用のイメージを作成する方法を紹介した。今回はそれに続き、別の仮想化ソフトウェア向けのイメージを作成する方法を紹介していこう。

Packerではさまざまな仮想マシンやクラウドインフラ向けのディスクイメージを作成できるが、今回はCentOS 7のインストールISOイメージを元に、VirtualBoxとQEMU(KVM)向けのディスクイメージを作成する流れを紹介する。

VirtualBox向けのディスクイメージを作成する

まずはVirtualBox向けのディスクイメージの作成について説明しよう。PackerではVirtualBox向けのbuilderとして、「virtualbox-iso」と「virtualbox-ovf」の2つが用意されている。

virtualbox-ovfは前回紹介したDocker向けbuilderと似たような動作を行うもので、既存のVirtualBox用の仮想マシンファイル(OVFファイル)やディスクイメージを使って仮想マシンを起動し、指定されたprovisionerでプロビジョニングを実行したのち仮想マシンをエクスポートする、というものだ。

いっぽう、virtualbox-isoは次のような一連の流れを自動的に実行するものになる。

1. 新規に仮想マシンを作成する
2. 指定されたインストールCD/DVDのISOイメージファイルからインストーラを起動してインストールを行う
3. プロビジョニングを実行する
4.プロビジョニング後の環境を仮想マシンファイルとしてエクスポートする

ただし、インストーラによる作業についてはPackerでは自動化できない。もしこれらの作業を完全に自動したい場合、kickstartなどの自動インストール機能を別途利用する必要がある。

今回は、このvirtualbox-iso builderを使ってVirtualBox向けの仮想ファイルを作成することにする。なお、virtualbox-isoもしくはvirtualbox-ovf builderを利用する場合、Packerを実行するマシン上にVirtualBoxがインストールされている必要がある。また、後述するheadlessインストールを行わない場合は、VirtualBoxのGUIが利用できるようになっている必要もある。それぞれ事前に準備をしておこう。

VirtualBox用ディスクイメージを作成する設定を追加する

それでは、まずはvirtualbox-iso builder用の設定を前回作成した設定ファイルに追加していこう。今回追加したのは、下記の太字で示している部分だ。

{
  "builders": [
    {
      "type": "docker",
      "image": "centos:centos7",
      "export_path": "packer-centos7-docker.tar"
    },
    {
      ↓「virtualbox-iso」builderの設定であることを宣言する
      "type": "virtualbox-iso",
      ↓使用するISOイメージのチェックサム
      "iso_checksum": "96de4f38a2f07da51831153549c8bd0c",
      ↓使用するチェックサムの形式
      "iso_checksum_type": "md5",
      ↓ISOイメージのダウンロード元URL
      "iso_url": "http://test01.office.osdn.jp/packer/CentOS-7.0-1406-x86_64-NetInstall.iso",
      ↓プロビジョニングに使用するユーザー名
      "ssh_username": "root",
      ↓プロビジョニング実行時に仮想マシンにログインするために使用するパスワード
      "ssh_password": "SSH_Password",
      ↓インストール作業のタイムアウト時間
      "ssh_wait_timeout": "40m",
      ↓作成する仮想マシンのディスクサイズ
      "disk_size": "8000",
      ↓作成する仮想マシンのタイプ
      "guest_os_type": "RedHat_64",
      ↓仮想マシンをシャットダウンする際に使用するコマンド
      "shutdown_command": "/sbin/shutdown -h now",
      ↓シャットダウンコマンドを実行してから完了するまでの待機時間
      "shutdown_timeout": "20s",
      ↓作成する仮想マシンの名称
      "vm_name": "packer-centos7-vbox"
    },
  ],
  "provisioners": [
    {
      "type": "shell",
      "inline": ["yum install -y hostname"]
    },
    {
      "type": "chef-solo",
      "cookbook_paths": ["cookbooks"],
      "run_list": ["webserver"],
      "prevent_sudo": true
    }
  ]
}

追加したそれぞれのパラメータについてはPackerのドキュメントを参照してほしいが、ここでは「iso_url」パラメータでインストール用ISOファイルのダウンロード元を指定している。ISOイメージを配布しているミラーサーバーなどのURLを直接指定しても良いのだが、今回はダウンロードを高速化するため、ローカルネットワーク(office.osdn.jp)内にあるサーバーにISOイメージファイルを置き、そこからダウンロードを行っている。「iso_checksum」および「iso_checksum_type」パラメータはそのISOイメージファイルのチェックサムとその形式を指定するものだ。チェックサムについては多くの場合ISOイメージの配布元で公開されている。たとえばCentOSの場合、md5sum.txtにMD5形式のチェックサムを確認できる。

「ssh_username」および「ssh_password」はインストールの完了後にPackerがプロビジョニングに使用するアカウント名とそのログインパスワードを指定するものだ。今回はrootユーザーでプロビジョニングを実行するように設定した。

また、注意したいのが「ssh_wait_timeout」設定だ。Packerは仮想マシンを実行後、「ssh_username」で指定したアカウントを使って仮想マシンに対しログインを試みる。インストール作業中は当然ながらログインを行えないため、Packerは定期的に仮想マシンに対してログインを試行し続け、ログインに成功したら仮想マシンへのインストールが完了したと判断する仕組みになっている。このとき、ログインに成功しないまま「ssh_wait_timeout」で指定した時間が経過すると、Packerはインストール時に問題が発生したと判断して作業を中断してしまう。そのため、ここでは十分な時間を指定しておく必要がある。今回は「40m」(40分)を指定している。

設定ファイルの編集後にpacker buildコマンドを実行すると、図1のようにVirtualBoxが起動し、インストール画面が表示される。

$ ~/packer/packer build --only=virtualbox-iso centos7.json
図1 packer buildコマンドを実行するとVirtualBoxが起動する

ここでは「--only=virtualbox-iso」を新たに追加しているが、これは使用するbuilderを選択するためのオプションだ。今回は「virtualbox-iso」を指定している。このオプションが省略された場合、Packerは設定ファイル内のすべてのbuilderを順に実行してイメージの作成を実行する。

さて、今回はインストールの自動化に関する設定は行っていないので、ここではインストーラの起動画面のみが表示され、その後はなにも起こらない。そのため、続けて手動でインストーラを操作し、インストール作業を進めていく。このときrootパスワードにはPackerの設定ファイル内で「ssh_password」として指定したものを設定することに注意したい。

インストールの完了後に仮想マシンを再起動すると、PackerがSSHで仮想マシンにログインし、プロビジョニング作業を実行する(図2)。

図2 インストール後に仮想マシンを再起動すると、プロビジョニング処理が開始される

プロビジョニング作業が正常に修了すると、イメージファイルのエクスポートが行われ、「output-virtualbox-iso」というディレクトリ内に保存される。「.vmdk」という拡張子のものがディスクイメージ、「.ovf」のものが仮想マシンの設定ファイルだ。

$ ls output-virtualbox-iso/
packer-centos7-vbox-disk1.vmdk  packer-centos7-vbox.ovf

kickstartを使ったインストール作業の自動化

さて、Packerを使ってVirtualBox用のディスクイメージを作成することはできたが、この例ではOSのインストール作業自体は手動で行っており、イメージを作り直すたびに同様の作業を行わなければならない。そこで、続いてはCentOSなどRed Hat Linux系ディストリビューションで利用できる自動インストール機能「kickstart」を使ってインストール作業を自動化してみよう。

kickstartは、インストール内容を記述した設定ファイルを指定してインストーラを起動することで、自動的にインストール作業を進める機能だ。Red Hat Linux系ディストリビューションでは、OSのインストール後にkickstart用の設定ファイル(kickstartファイル)を「/root/anaconda-ks.cfg」という名前で保存する。このファイルを利用することで、それと同じ環境を自動インストールできるようになる。また、このファイルを編集することで、インストール内容をカスタマイズすることも可能だ。

今回はPacker作成されたanaconda-ks.cfgファイルを若干修正して使用した。使用した設定ファイルは次のとおりで、修正した個所は太字で示している。

#version=RHEL7
# System authorization information
auth --enableshadow --passalgo=sha512

# Use network installation
url --url="http://ftp.jaist.ac.jp/pub/Linux/CentOS/7/os/x86_64/"
# Run the Setup Agent on first boot
#firstboot --enable
ignoredisk --only-use=sda
# Keyboard layouts
keyboard --vckeymap=jp106 --xlayouts='jp'
# System language
lang ja_JP.UTF-8

# Network information
network  --bootproto=dhcp --device=enp0s3 --ipv6=auto --activate
network  --hostname=localhost.localdomain
# Root password
rootpw --iscrypted <ハッシュ化されたパスワード>
# System timezone
timezone Asia/Tokyo --isUtc
user --groups=wheel --name=hylom --password=<ハッシュ化されたパスワード> --iscrypted --gecos="hylom"
# System bootloader configuration
bootloader --location=mbr --boot-drive=sda
autopart --type=lvm
# Partition clearing information
clearpart --none --initlabel 
# Skip EULA
eula --agreed
# auto reboot
reboot

%packages
@core

%end

具体的な修正個所は以下の3点だ。

  • インストール後に初めて起動した際に設定画面を表示する「firstboot」を無効する(「firstboot --enable」をコメントアウト)
  • ソフトウェア利用許諾契約(EULA)についての同意画面を表示させず、自動的に同意したことにする(「eula --agreed」)
  • インストール完了後、自動的に再起動を行う(「reboot」)

これらを指定することで、インストーラの起動後に入力を行うことなくインストール作業を進行させることが可能になる。

また、今回作成したファイルはPackerの設定ファイルと同じディレクトリ内に「kickstart」というディレクトリを作成し、そこに「anaconda-ks.cfg」というファイル名で保存している。

続いて、用意したkickstartファイルをインストーラに読み込ませるための設定を行う。こちらについては、Packerの設定ファイルに記述する。具体的に必要となる設定項目は次の2つだ。

  • HTTP経由でインストーラにkickstartファイルを渡すための「http_directory」
  • ブート時にインストーラに文字列を渡すための「boot_command」と「boot_wait」

kickstartを使ってインストールを行うには、作成したkickstartファイルを何らかの形でインストーラに渡す必要がある。これにはいくつかの手段が利用できるが、Packerには内部的にHTTPサーバーを起動して指定したディレクトリ内のファイルを公開する機能があり、これを利用するのが簡単だ。この機能を利用するには、「http_directory」という設定項目を追加し、その値に公開するファイルが含まれるディレクトリを指定すれば良い。今回は「kickstart」というディレクトリ内にkickstartファイルを格納しているので「./kickstart/」という値を指定する。

また、kickstartを使って自動インストールを行う場合、インストーラを起動した後にインストールオプションとしてkickstarterファイルを指定する必要がある。この入力処理を自動で行うためのオプションが「boot_command」と「boot_wait」オプションだ。これらのオプションを指定すると、仮想マシンを起動してからboot_waitオプションで指定した時間だけ待機し、続いてboot_commandオプションで指定した文字列を仮想マシンに対しキーボードイベントとして送信する、という処理が実行される。

今回は、先に作成した設定ファイルにさらに次のような項目を追加した。

"boot_command": [
" text ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/anaconda-ks.cfg "
],
"boot_wait": "10s",
"http_directory": "./kickstart/"

ここで指定している「{{ .HTTPIP }}」および「{{ .HTTPPort }}」という文字列はそれぞれ「HTTPIP」および「HTTPPort」という変数を参照することを示しており、これらはPackerの起動後、HTTPサーバーのIPアドレスとポート番号に自動的に置き換えられる。

これらの設定を追加した後に同じようにしてpacker buildコマンドを実行すると、仮想マシンの起動やインストーラの起動、インストール、プロビジョニングといった作業が全自動で行われてディスクイメージが生成される。

なお、この場合VirtualBoxの画面がデスクトップ上に表示されてしまうが、Packerの設定ファイル内に「"headless": "true"」という設定項目を追加することで、画面を表示せずにインストール作業を実行することも可能になる。これは「headlessインストール」と呼ばれており、リモートのマシンにSSHでログインして作業を行う場合などに便利だ。ただしこの場合エラーが発生した場合に何が起こっているのか判別しにくくなるので、利用前にインストール作業が正しく行えるかをチェックしてから使うことをおすすめする。

QEMU用のディスクイメージを作成する

続いては、QEMU用のディスクイメージファイルを作成してみよう。QEMUはオープンソースの仮想化ソフトウェアだが、KVMやXenと組み合わせて利用する例が多い。たとえばRed Hat Enterprise LinuxやFedora、CentOSなどで採用されている仮想環境管理ツールであるlibvirtではKVMを利用する場合、QEMUと組み合わせて利用するようになっている。Dockerでは、「qemu」builderを利用することでKVMおよびXen用の仮想マシンイメージを作成できる。

qemu builderではvirtualbox-iso builderと同様、インストールCD/DVDのISOイメージから仮想マシンイメージを作成できる。必要な設定項目もvirtualbox-iso builderとほぼ同じなので、virtualbox-iso builderの設定を流用することが可能だ。

必要な設定項目について詳細はqemu buildのドキュメントを参照してほしいが、今回は次のような設定を追加した。これは先のvirtualbox-iso向け設定項目とほぼ同じで、追加/変更したのは太字の部分のみだ。

{
  "builders": [
 
 
    {
      "type": "qemu",
      "iso_checksum": "96de4f38a2f07da51831153549c8bd0c",
      "iso_checksum_type": "md5",
      "iso_url": "http://test01.office.osdn.jp/packer/CentOS-7.0-1406-x86_64-NetInstall.iso",
      "ssh_username": "root",
      "ssh_password": "TakeTheTime",
      "ssh_wait_timeout": "40m",
      "disk_size": "8000",
      "shutdown_command": "/sbin/shutdown -h now",
      "shutdown_timeout": "20s",
      "vm_name": "packer-centos7-qemu",
      "boot_command": [
        "<tab> text ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/anaconda-ks-qemu.cfg <enter>"
      ],
      "boot_wait": "10s",
      "http_directory": "./kickstart/",
      ↓仮想化エンジンとしてKVMを使用
      "accelerator": "kvm",
      ↓使用する仮想ネットワークデバイスを指定
      "net_device": "virtio-net",
      ↓使用する仮想ディスクデバイスを指定
      "disk_interface": "virtio",
      ↓使用するQEMUコマンドの実行ファイルを指定
      "qemu_binary": "/usr/local/bin/qemu-system-x86_64",
      ↓QUIを使用しない
      "headless": true,
       ↓QEMUに与える引数を指定
      "qemuargs": [
        [ "-m", "512M"]
      ]
    }
  ],
 
 

kickstart用の設定ファイルについてはvirtualbox-iso builderで使ったもの(anaconda.cfg)とは異なるファイル(anaconda-ks-qemu.cfg)を指定している。具体的には、anaconda.cfg内でディスクデバイス関連の設定項目で指定されている「sda」という値を、すべて「vda」に置き換えている。QEMU+KVMの環境でディスクドライバにvirtioを利用する場合、仮想マシン上のOSからはディスクデバイスが「/dev/sda」ではなく「/dev/vda」として認識されるという違いがあるためだ。

また、今回はCentOS 6.5環境上でテストを行っているが、CentOS 6.5において標準で提供されているQEMUはバージョンが古く、そのままではPackerで利用できなかった。そのため、本記事執筆時点での最新安定版であるQEMU 2.1.0をソースコードからビルドして導入し使用している。

設定ファイルを用意した後に次のようにpacker buildコマンドを実行すると、virtualbox-iso builderを利用した場合と同様に仮想マシンの作成やインストール、プロビジョニングが実行されて仮想マシンイメージが出力される。

$ ~/packer/packer build -only=qemu centos7.json

利用には各仮想化技術に対する一定の知識が必要

さて、2回にわたってPackerについて紹介してきたが、Packerの設定ファイル作成などの際には対象とする仮想化ソフトウェアやコンテナ管理ツール、プロビジョニングツールなどについての知識が必要で、必ずしも「お手軽」なツールではない。ただ、一度設定ファイルを作成できてしまえば、それらを容易に使い回せるため、その後の管理作業については簡単になる。

複数の仮想化ソフトウェアやコンテナ管理ツールを併用している場合や、プロビジョンツールを使っている場合などは活用する価値があるのではないだろうか。

おしらせ