• このエントリーをはてなブックマークに追加


メモ

Vagrant box な VM を作るのに,Packer を触ってみています.

で,一プロジェクトの中で,いくつかの Vagrant box な VM −− 例えば Webサーバなホスト用,DBサーバなホスト用,等々 — をこさえるときの,そのためのファイル群の管理をこんな感じにしてみました.というメモです.

ファイル構成

/path/to/myproj/packer
├── bin
│   ├── build
│   └── deploy
├── builders
│   └── preseed.cfg
├── iso
│   └── ubuntu-13.04-server-amd64.iso
├── provisioners
│   ├── _
│   │   ├── apt.sh
│   │   ├── cleanup.sh
│   │   ├── sudo.sh
│   │   └── vagrant.sh
│   ├── db
│   │   ├── apt.sh
│   │   └── mysql56.sh
│   └── www
│   │   ├── apt.sh
│   │   └── nginx.sh
├── templates
│   ├── db.json
│   └── www.json
└── vagrant-box

こんな感じにしておけば,種別ごとのテンプレートとか provisioner スクリプトとかでも管理するのがラクかな,と.

とりあえずキャッシュと大きなサイズのファイルは除外:

% cat .gitignore
/iso/
/vagrant-box/
/packer_cache/

iso は add しておいてもよいかも.

ビルド用スクリプト

#!/bin/bash
basedir=$(cd $(dirname $0)/.. && pwd)
mode=$1; shift
 
if [ ! -f $basedir/templates/$mode.json ]; then
    echo "template for \"$mode\" does not exist."
    exit 1
fi
 
cd $basedir
packer_build="packer build $@ $basedir/templates/$mode.json"
echo "$packer_build"
exec $packer_build

こんなスクリプトを準備しておけば,packer build を呼び出すのが少しだけ簡単になります:

% cd /path/to/myproj/packer
% ./bin/build www
packer build  /path/to/myproj/packer/templates/www.json
virtualbox-iso output will be in this color.
 
==> virtualbox-iso: Downloading or copying Guest additions checksums
    virtualbox-iso: Downloading or copying: http://download.virtualbox.org/virtualbox/4.3.8/SHA256SUMS
==> virtualbox-iso: Downloading or copying Guest additions
    virtualbox-iso: Downloading or copying: http://download.virtualbox.org/virtualbox/4.3.8/VBoxGuestAdditions_4.3.8.iso
==> virtualbox-iso: Downloading or copying ISO
    virtualbox-iso: Downloading or copying: file:///path/to/myproj/packer/iso/ubuntu-13.04-server-amd64.iso
==> virtualbox-iso: Starting HTTP server on port 8081
==> virtualbox-iso: Creating virtual machine...
==> virtualbox-iso: Creating hard drive...
==> virtualbox-iso: Creating forwarded port mapping for SSH (host port 3213)
==> virtualbox-iso: Executing custom VBoxManage commands...
    virtualbox-iso: Executing: modifyvm packer.myproj.www --memory 1024
    virtualbox-iso: Executing: modifyvm packer.myproj.www --cpus 2
==> virtualbox-iso: Starting the virtual machine...
==> virtualbox-iso: Waiting 5s for boot...
==> virtualbox-iso: Typing the boot command...
...

テンプレートファイル

こちら:

を参考に,次のようなものを書きました:

{
    "builders": [
        {
            "type": "virtualbox-iso",
            "vm_name": "packer.myproj.www",
            "boot_wait": "5s",
            "disk_size": 81920,
            "guest_os_type": "Ubuntu_64",
            "iso_url": "file:///path/to/myproj/packer/iso/ubuntu-13.04-server-amd64.iso",
            "iso_checksum": "2af1c223f586f59237212bb9c06ad774673c8952",
            "iso_checksum_type": "sha1",
            "ssh_username": "vagrant",
            "ssh_password": "vagrant",
            "ssh_port": 22,
            "ssh_wait_timeout": "10000s",
            "shutdown_command": "echo '/sbin/halt -h -p' > shutdown.sh; echo 'vagrant'|sudo -S sh 'shutdown.sh'",
            "guest_additions_path": "VBoxGuestAdditions_{{.Version}}.iso",
            "vboxmanage": [
                ["modifyvm", "{{.Name}}",
                 "--memory", "1024"
                ],
                ["modifyvm", "{{.Name}}",
                 "--cpus", "2"
                ]
            ],
            "http_directory": "./builders",
            "boot_command": [
                "<esc><esc><enter>",
                "        ",
                "/install/vmlinuz noapic preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
                "debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
                "hostname=myproj1 ",
                "fb=false debconf/frontend=noninteractive ",
                "keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=us keyboard-configuration/variant=us console-setup/ask_detect=false ",
                "initrd=/install/initrd.gz -- <enter>"
            ]
        }
    ],
 
    "provisioners": [
        {
            "type": "shell",
            "execute_command": "echo 'vagrant' | {{.Vars}} sudo -E -S sh '{{.Path}}'",
            "scripts": [
                "provisioners/_/sudo.sh",
                "provisioners/_/apt.sh",
                "provisioners/www/apt.sh",
                "provisioners/_/vagrant.sh",
                "provisioners/_/cleanup.sh"
            ]
        }
    ],
 
    "post-processors": [
        {
            "type": "vagrant",
            "output": "./vagrant-box/myproj.www.box"
        }
    ]
}

provisioners のスクリプト群については,veewee を触ってたときのファイルを基にしています.

で,provisioners/_ には各 VM 間で共通するだろう処理を,provisioners/www とか provisioners/db とかに,それぞれに特化した処理を,行うためのシェルスクリプトをおいている感じです.

builders.boot_command

当初,これも veewee を触ってた時のものを基に,次のようなものを準備しました:

[
    "<esc><esc><enter>",
    "/install/vmlinuz noapic preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
    "debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
    "hostname=myproj1 ",
    "fb=false debconf/frontend=noninteractive ",
    "keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=us keyboard-configuration/variant=us console-setup/ask_detect=false ",
    "initrd=/install/initrd.gz -- <enter>"
]

これでビルドを実行したところ,インストール処理が進まない現象が:

ss-1395630438

よく見ると,冒頭が /install/vmlinuz で始まっていないのがわかります:

ss-1395630574

<enter>/ がタイプされるまでの間隔」をもう少し開けたらよいのかな,と思い,スペースをいくつかタイプするようにしてみました:

[
    "<esc><esc><enter>",
    "        ",
    "/install/vmlinuz noapic preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
    "debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
    "hostname=myproj1 ",
    "fb=false debconf/frontend=noninteractive ",
    "keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=us keyboard-configuration/variant=us console-setup/ask_detect=false ",
    "initrd=/install/initrd.gz -- <enter>"
]

結果,タイプの冒頭が /install/vmlinuz ... となり,インストール作業も無事に走りました.

後々,virtualbox-iso に関するドキュメント:

を見てみると, <wait> を使えることがわかったので,次のようにすれば,ヘンな工夫も不要でした:

[
    "<esc><esc><enter><wait>",
    "/install/vmlinuz noapic preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
    "debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
    "hostname=myproj1 ",
    "fb=false debconf/frontend=noninteractive ",
    "keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=us keyboard-configuration/variant=us console-setup/ask_detect=false ",
    "initrd=/install/initrd.gz -- <enter>"
]

provisioners.execute_command

"echo 'vagrant' | {{.Vars}} sudo -E -S sh '{{.Path}}'"

provisioner の各スクリプトの中で毎度 sudo しなくて済みます.

box をデプロイするスクリプト

http://myrepos/vagrant-box/myproj.www.box とかでダウンロードできるようなところに rsync するだけです.必要に応じて変えていけばよいでしょう:

#!/bin/bash
basedir=$(cd $(dirname $0)/.. && pwd)
rsync="rsync -rtv $basedir/vagrant-box/*.box www@myrepos:/var/www/public/vagrant-box/ --progress $*"
echo "$rsync"
exec $rsync
% ./bin/deploy
rsync -rtv /path/to/myproj/packer/vagrant-box/*.box www@myrepos:/var/www/public/vagrant-box/ --progress
ending incremental file list
myproj.www.box
    19333120   1%    1.53MB/s    0:10:19

おわりに

昨日は Docker への理解が少しだけ進んでよかったです.