Packer を使って Vagrant のディスク容量を拡張する

開発環境を Vagrant で立てている中で,多くのミドルウェアを1個の仮想環境に押し込めてしまっている関係上,ディスク容量が足りなくてツライという状況があった.

プロセッサーとメモリは Vagrantfile に書くと拡張できるが,ディスクは簡単には拡張できず,VMDK や VDI に手を加えていかなければダメで,1度試したけど面倒で諦めた背景がある.

config.vm.provider 'virtualbox' do |v|
  v.memory = 1024
  v.cpus = 2
end

もし試すなら以下の記事が参考になる.

改善策としての Packer

改善策として Packer を試してみた.

なお,ディスクを拡張する目的だけではなくて,今まで Vagrant 環境を立てるときに毎回 Chef を実行してプロビジョニングする必要もあって,アプリケーション開発者からするとオールインワンの Box を立ち上げるだけの方が圧倒的に効率が良いと考えた.まぁ vagrant package で Box をエクスポートすることもできるが,Packer で iso から手続き的に Box をビルドできることにメリットがある.

www.packer.io

github.com

構成

先に構成をまとめておく.

ディレクトリ階層

.
├── http
│   └── ks.cfg
├── packer_scripts
│   └── vagrant.sh
├── template.json

.gitignore

不要なファイルをコミットしないようにした.

# Packer
packer_cache/
*.box

template.json

今回は CentOS 6.7 をベースにしている.

{
  "builders": [
    {
      "type": "virtualbox-iso",
      "boot_command": [
        "<tab> text ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg<enter><wait>"
      ],
      "boot_wait": "10s",
      "disk_size": 30000,
      "guest_os_type": "RedHat_64",
      "http_directory": "http",
      "iso_checksum": "2ed5ea551dffc3e4b82847b3cee1f6cd748e8071",
      "iso_checksum_type": "sha1",
      "iso_url": "http://mirror.hmc.edu/centos/6/isos/x86_64/CentOS-6.7-x86_64-minimal.iso",
      "ssh_username": "vagrant",
      "ssh_password": "vagrant",
      "ssh_port": 22,
      "ssh_wait_timeout": "10000s",
      "shutdown_command": "echo '/sbin/halt -h -p' > /tmp/shutdown.sh; echo 'vagrant' | sudo -S sh '/tmp/shutdown.sh'",
      "virtualbox_version_file": ".vbox_version",
      "vboxmanage": [
        [ "modifyvm", "{{ .Name }}", "--memory", "1024" ],
        [ "modifyvm", "{{ .Name }}", "--cpus", "2" ]
      ],
      "headless": true
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "override": {
        "virtualbox-iso": {
          "scripts": [
            "packer_scripts/vagrant.sh"
          ]
        }
      }
    },
    {
      "type": "chef-solo",
      "cookbook_paths": ["./cookbooks", "./site-cookbooks"],
      "run_list": [
        "base",
        "user",
        "nginx",
        "mysql"
      ]
    }
  ],
  "post-processors": [
    {
      "type": "vagrant",
      "compression_level": 9,
      "override": {
        "virtualbox": {
          "output": "packer-app.box"
        }
      }
    }
  ]
}

ks.cfg と vagrant.sh

CentOS の kickstart ファイルと vagrant ssh をできるようにするための vagrant.sh は,以下のリポジトリで公開されているものをそのまま使った.

github.com

構成ポイント

基本的に公式ドキュメントを読みながら template.json を書いたが,ポイントになりそうな点を残しておこうと思う.

builders

www.packer.io

boot_command と http_directory

Linux を自動構築する手順を ks.cfg に定義して,それを http_directory に指定すると裏側でウェブサーバが起動して,http でアクセスできるようになる.それを boot_command から読み込んで実行するような流れになる.

"boot_command": [
  "<tab> text ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg<enter><wait>"
],

disk_size

disk_size に MB を指定することで,ディスク容量を初期状態でマウントすることができる.デフォルトだと 40GB になっている.よって,この設定でディスク容量の課題は解消できる.

shutdown_command

プロビジョニングした状態を正常に保存するために graceful に shutdown する必要がある.ドキュメントにも重要な設定だと書かれていた.

It is important to add a shutdown_command. By default Packer halts the virtual machine and the file system may not be sync'd. Thus, changes made in a provisioner might not be saved.

headless

ks.cfg に従って Linux が自動構築されていくのを眺めるのも楽しいけど,何度も繰り返していると飽きてくるので,headless でバックグラウンド実行させている.

provisioners

www.packer.io

www.packer.io

shell

プロビジョニングは全て Chef に任せるとして,vagrant ssh できるようにするための鍵設定を shell で流している.ドキュメントに the execute_command is puzzling. と書かれてて笑ったけど,環境によっては sudo でプロンプトが出てしまうため,パスワードをパイプして渡してあげるなどの工夫が必要と書いてあった.今回は特に考慮しなかった.

To many new users, the execute_command is puzzling. However, it provides an important function: customization of how the command is executed. The most common use case for this is dealing with sudo password prompts. You may also need to customize this if you use a non-POSIX shell, such as tcsh on FreeBSD.

chef-solo

run_list はサンプルだけど,今までの Chef と同様に書くとプロビジョニングできた.

{
  "type": "chef-solo",
  "cookbook_paths": ["./cookbooks", "./site-cookbooks"],
  "run_list": [
    "base",
    "user",
    "nginx",
    "mysql"
  ]
}

post-processors

www.packer.io

compression_level

compression_level で圧縮レベルを指定することができる.デフォルトは 6 になっている.まぁBox サイズは小さくて困ることはないと思うし,今回は最大圧縮レベルの 9 にした.

An integer representing the compression level to use when creating the Vagrant box. Valid values range from 0 to 9, with 0 being no compression and 9 being the best compression. By default, compression is enabled at level 6.

ただし,実際に 0 と 9 で比較してみたけど,今回のケースだとほとんど圧縮されてなかった.

$ ls -l *.box
-rw-r--r--  1 kakakakakku  CATK\Domain Users  1368710144  4 19 11:17 packer-app_compression_0.box
-rw-r--r--  1 kakakakakku  CATK\Domain Users  1339162491  4 19 10:53 packer-app_compression_9.box

まとめ

Packer の最大のメリットは AWS / DigitalOcean / Docker などと連携してマシンイメージをビルドできる点かもしれないけど,シンプルに Vagrant 連携として使うだけでも,大きなメリットを感じることができた.実際に開発環境構築のコストが極限まで下がったのは嬉しい.

引き続き Packer を使ってくぞ!

Packer を使うアイデアを教えて頂いた @ariarijp に感謝!🎉