Ubuntu Cloud Images で提供されている QCOW2 フォーマットのイメージを元に、Packer の QEMU Builder で OS イメージをビルドしたかったので、その手順をまとめます。
事前準備
今回は macOS Sierra 上でビルドするため、事前に Packer と QEMU をインストールしておきます。インストールには Homebrew を使用します。また、後述する一部の作業で Docker を使用するため、Docker for Mac もインストールしておきます。
$ brew install packer qemu
cloud-init の設定イメージの作成
Ubuntu Cloud Images で提供されているイメージは、cloud-init を利用して AWS などのクラウドプロバイダーから初期設定を起動時に取得することを前提とした作りになっています。しかし今回は Packer を使用して QEMU 上でビルドするため、cloud-init が初期設定の取得先を見つけることができず、正しく起動できません。
しかしながら cloud-localds
というツールを使用して初期設定を含むイメージを作成し、それを QEMU の起動時に指定しておくことで、クラウドプロバイダーの初期設定が無くとも cloud-init を正しく実行できます。今回はまずその設定イメージを作ります。
cloud-localds
を使用するには Linux が必要です。今回は Docker コンテナを使用して cloud-localds
をインストールして、設定イメージを作ることにします。まずは Ubuntu のコンテナを起動します。
$ docker run -it -v `pwd`:/tmp/host --rm ubuntu:16.04
Ubuntu コンテナが起動したら、cloud-utils パッケージをインストールします。
# apt update
# apt install -y vim cloud-utils
続いて、cloud-init の設定フォーマットに従い、初期設定を含んだ設定ファイルを作成します。以下の例ではデフォルトユーザーの初期パスワードを ubuntu に設定し、SSH 経由でのパスワードログインを有効化しています。
# vim cloud.cfg
#cloud-config
password: ubuntu
ssh_pwauth: true
chpasswd:
expire: false
設定ファイルを作成したら、cloud-localds
コマンドを使用してイメージに変換します。コンテナの外で使えるようにホストからマウントしたパスに書き出します。
# cloud-localds /tmp/host/cloud.img cloud.cfg
これで cloud-init の初期設定を含むイメージができました。
Packer でのビルド
続いて、Packer のテンプレートファイルを以下のように用意します。qemuargs キーの -fda オプションで先ほど作成した cloud-init の初期設定を含むイメージを指定します。この設定で先ほどのイメージがフロッピーディスクとして使用され、cloud-init がそこから初期設定を読み込むようになります。また、イメージからの起動には少し時間がかかるので ssh_wait_timeout キーの値も調整しておくのが良さそうです。
$ vim template.json
{
"builders":
[
{
"type": "qemu",
"iso_url": "ubuntu-16.04-server-cloudimg-amd64-disk1.img",
"iso_checksum": "3a4b7f6115ca074c4728e4628ca73160e6b7ef6995db3c382015545940568939",
"iso_checksum_type": "sha256",
"disk_image": true,
"output_directory": "output",
"disk_size": 5000,
"format": "qcow2",
"disk_compression": true,
"headless": true,
"accelerator": "none",
"ssh_username": "ubuntu",
"ssh_password": "ubuntu",
"ssh_port": 22,
"ssh_wait_timeout": "300s",
"vm_name": "ubuntu",
"use_default_display": true,
"qemuargs": [
["-m", "1024M"],
["-smp", "1"],
["-fda", "cloud.img"],
["-serial", "mon:stdio"]
]
}
]
}
これで Packer でのビルドの準備ができました。以下のように packer
コマンドを実行すれば Ubuntu Cloud Images を使った OS イメージが output ディレクトリに生成されます。
$ packer build template.json