Ubuntu Weekly Recipe

第154回さくらVPSへのネットブートインストールをPreseedingで自動化する

成人の日も過ぎて新年気分も一段落し、皆様いかがお過ごしでしょうか。おそらく、年末の大掃除できれいになったご家庭やお勤め先では、新しい気持ちで事に取り組まれているものと思います。⁠きれいになった部屋にはきれいな作業環境を」ということで、今回はUbuntuインストールに関する話題です。

昨年、さくらインターネットがKVMを使ったVPSサービスとしてさくらのVPSの提供を開始し、低価格に対して自由度の高さや日本語サポートという魅力も相まって各所で話題となりました。Recipeでも第142回では「カスタムOSインストール」機能を使ってUbuntu 10.04やそのデスクトップ環境をインストールする方法を紹介しています。

しかしながら、カスタムOSインストール機能はUbuntuだと今のところ10.04しかインストールできません。また、標準のCentOSと異なりインストール時に手動で設定が必要になります。テスト目的で新しいバージョンを使いたかったり、環境を何度も再インストールする場合、これは少し不便です。幸い、さくらのVPSの場合、ブラウザからシリアルコンソールアクセスが可能なので、ネットブートインストールを使えば任意のバージョンのUbuntuをインストールできます[1]⁠。また、PreseedingやKickstartを使ってインストール自体を自動化することもできます。

そこで今回はこの二つを組み合わせることで、⁠OS再インストール」機能を使ってCentOSを入れ直す時ほどではないにしろ、簡単にUbuntu環境をリフレッシュする方法をご紹介します。

インストールの前に

手動でインストールする場合は、ネットワーク設定なども自前で行わなくてはなりません。そこで、あらかじめ設定値を確認しておきましょう。具体的には、ifconfig、hostnameコマンドなどで、IPv4のIPアドレス、ネットマスク、ゲートウェイアドレス、ホスト名を控えておくと良いでしょう。

ネットブートインストール

ネットブートインストールとは、ディスクもしくはインターネット上に置いたインストール機能を持った最低限のイメージを使ってインストールする方法です。通常のインストールと違ってCD-ROMドライブを必要としません。また、今回の方法はイメージを仮想マシン側のディスク上に置くため、TFTPブートのときのように外部サーバを用意する必要もありません。ただし、インストール対象のブートローダの設定ができること、インストール中にアーカイブサーバへアクセスできることが必要になります[2]⁠。

インストーラのダウンロード

まずはネットブートインストール用のイメージをダウンロードします。CDイメージのアーカイブサイトに、リリース/アーキテクチャ毎のインストールイメージのリンクが掲載されていますので、各自の環境にあわせたものをダウンロードしてください。ここでは、仮想マシン上に10.10(Maverick)のamd64版をダウンロードしています。

$ wget http://archive.ubuntu.com/ubuntu/dists/maverick/main/installer-amd64/current/images/netboot/netboot.tar.gz

すべての設定ファイルが入ったnetboot.tar.gzをダウンロードしていますが、今回必要なのはlinuxとinitrd.gzの二つだけです。これらをブートローダから見える場所(以下の例では/boot/ubuntu)にコピーします。

$ tar zxvf netboot.tar.gz
$ cd ubuntu-installer/amd64
$ sudo mkdir /boot/ubuntu
$ sudo cp linux initrd.gz /boot/ubuntu

GRUBの設定

先ほどコピーしたイメージから起動するよう、GRUBを設定します。リモートコンソールを使っている場合は起動時に、ESCキーを押すことでも起動エントリを直接編集・選択できます[3]が、今回は設定ファイルを編集してあらかじめ起動エントリを作っておく方法を紹介します。なお、GRUB LegacyとGRUB 2とでは設定方法が異なりますので、ここでは両方を記載しておきます。

標準インストールされているCentOSはGRUB Legacyを使っているので仮想マシンの設定ファイル(/boot/grub/grub.conf)を編集します[4]⁠。このファイルに以下のコードを追加してください。

title Ubuntu Netboot Install
root (hd0,0)
kernel /boot/ubuntu/linux ro root=LABEL=/ console=tty0 console=ttyS0,115200n8r
initrd /boot/ubuntu/initrd.gz

カスタムOSインストールなどで、Ubuntu 9.10以降をインストールした場合は、GRUB 2が入っています。その場合は、仮想マシン上の/etc/grub.d/40_customを/etc/grub.d/09_netbootとしてコピーした上で、以下のような内容になるよう編集します。09にしているのは、10_linuxのエントリより前に持ってくることで、標準で選択されるエントリにするためです。

!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.

menuentry "Ubuntu Netboot Install" {
        set root (hd0,0)
        linux /boot/ubuntu/linux ro root=LABEL=/ console=tty0 console=ttyS0,115200n8r
        initrd /boot/ubuntu/initrd.gz
}

GRUB 2の場合は編集後、update-grubを実行して、設定内容が/boot/grub.cfgに反映されていることを確認してください。

$ sudo update-grub

実際にインストールしてみる

GRUB Legacy/2いずれの場合も、前節までの設定が終わったら仮想マシンを再起動します。リモートコンソールから、コンソールログインしrebootコマンドで再起動すればその後のインストール作業も続けて行えるので便利です。GRUB Legacyの場合は起動画面になったらESCキーを押してGRUB画面に移行し、"Ubuntu Netboot Install"を選択します。GRUB 2の場合は、上記設定をしているなら自動で"Ubuntu Netboot Install"が選択されるはずです[5]⁠。

インストール画面は、カスタムOSインストールガイドにあるそれとほぼ変わりません。テキストベースのインストールの流れを体験しておくと、後述のPreseedingの設定時に理解しやすくなりますので、テスト目的も兼ねて一度試しておくと良いでしょう。なお、SSHログインを行いたい場合は、"Choose software to install"で"OpenSSH server"を選択してください。

インストールが完了したら、ログインして動作確認します。なお、同じアドレスにSSHログインしていた場合は、仮想マシンにあるSSHサーバの鍵が変わっていますので、ローカル側の鍵を削除しておく必要があります。

$ ssh-keygen -R (仮想マシンのIPアドレス and/or ホスト名)

確認するポイントとしてはログイン自体ができるかどうか、ネットワーク設定も正しく行われておりインターネットに接続できるかどうかなどになります。うまくインストールできたのなら、次はインストールの自動化に進みます。

インストールの自動化

Debian-InstallerをベースにしたUbuntuのインストーラは、Debian-Installerと同様にPreseedingやKickstartに準じた「事前設定ファイル」を使うことで、インストールを自動化できます。ここでは、Preseedingを使った自動化方法をご紹介します。Kickstartを使った方法については、Ubuntuのインストールガイドを参照してください。

Preseedingは、あらかじめインストール中に尋ねられる質問への回答をpreseed.cfgという事前設定ファイルを記述しておいて、それをインストーラに渡すことで自動化を行います。インストーラに渡す方法には主に以下の3種類があります。

  1. インストーラがあるメディアにファイルとして保存した上で、インストーラ起動時にそのファイルパスを指定する
  2. インストーラ起動時に事前設定ファイルがあるネットワーク上のURLを指定する
  3. インストーラのイメージファイル(initrd.gz)に組み込む

今回はネットブートインストールを使っているために、1番目の方法は使用できません。また、2番目の方法はインストール対象のマシンと事前設定ファイルを配布するマシンが共に信頼できる経路でつながっていることが前提となっているため、インターネット越しにやるには不向きです。よって、3番目のinitrd.gzを編集する方法を採用します。

なお、preseed.cfgとinitrd.gzは満足のいく設定になるまでトライアンドエラーを繰り返しながら修正していくことになります。よって、今後の作業は、インストールのたびにフォーマットされる仮想マシン上ではなく、作業内容が保存されるローカルマシン上で行うと良いでしょう。最後に、initrd.gzのみをscpなどで仮想マシンにコピーして、あとは前節のようにGRUBの設定を行います。

事前設定ファイルを作成する

まず最初に、インストールガイドにあるひな形をダウンロードしてpreseed.cfgという名前で保存します。

$ wget -O preseed.cfg https://help.ubuntu.com/10.10/installation-guide/example-preseed.txt

もし、既に自動化したい環境と同じ状態のマシンがあるなら、debconf-utilsパッケージにあるコマンドを使うことで、インストールされたDebianパッケージの設定値一覧を出力できます。事前設定ファイルを作成する場合の参考になるでしょう。

$ sudo apt-get update
$ sudo apt-get install debconf-utils
$ sudo debconf-get-selections --installer > sample.seed

上記ひな形を元に、preseed.cfgを修正します。設定値や書式については、preseed.cfgのコメントやドキュメントを参考にしてもらうことにして、ここでは自動化という観点で初期設定値から変更すべき項目などをリストアップします。設定内容自体は、各自の環境にあわせて適切なものを指定してください。

# キーボードを設定します(以下は日本語キーボードの場合)
d-i console-setup/layoutcode string jp

# DHCPによるIPアドレス取得を無効化します
d-i netcfg/disable_dhcp boolean true

# IPアドレスを静的に設定します(最初にCentOSで取得した値を使います)
# ネームサーバのアドレス: http://support.sakura.ad.jp/support/vps/tips_ossetup.shtml
d-i netcfg/get_nameservers string 210.188.224.10 210.188.224.1
d-i netcfg/get_ipaddress string (ifconfigで取得した値)
d-i netcfg/get_netmask string (ifconfigで取得した値)
d-i netcfg/get_gateway string (ifconfigで取得した値)

# ホスト名、ドメイン名を設定します(最初にCentOSで取得した値を使います)
d-i netcfg/get_hostname string ("wwwNNNNu"など)
d-i netcfg/get_domain string sakura.ne.jp

# アーカイブサーバを日本のミラーサーバに設定します
d-i mirror/country string JP
d-i mirror/http/hostname string jp.archive.ubuntu.com
d-i mirror/http/directory string /ubuntu/
d-i mirror/http/proxy string
d-i mirror/http/mirror select jp.archive.ubuntu.com

# タイムゾーンを東京に設定します
d-i time/zone string Asia/Tokyo

# インストール中の時刻補正を行うためのNTPサーバを指定します
# 参考: http://support.sakura.ad.jp/support/vps/tips_ossetup.shtml
d-i clock-setup/ntp-server string ntp1.sakura.ad.jp

# パーティショニングは次節を参照してください

# アカウントを設定します
d-i passwd/user-fullname string (フルネーム)
d-i passwd/username string (ログインID)
d-i passwd/user-password-crypted password "パスワードのMD5ハッシュ値"

# restricted/universeコンポーネントを有効化します(必須ではありません)
d-i apt-setup/restricted boolean true
d-i apt-setup/universe boolean true

# 標準でインストールするタスクとして基本システムに加えて、
# openssh-serverを選択します
tasksel tasksel/first multiselect standard, openssh-server

# 必要に応じて、標準でインストールしたいパッケージを選択します
# d-i pkgsel/include string byobu vim ntp

# アップデートポリシーを設定します
d-i pkgsel/update-policy select none

"パスワードのMD5ハッシュ値"はmkpasswdパッケージをインストールした上で、以下のコマンドを実行すれば得られます。

$ mkpasswd -m MD5 パスワード文字列

MD5ハッシュ値を使っているとは言え、パスワードに関する情報が記載されることになりますので、preseed.cfgファイルの取扱いには十分注意してください。

パーティショニング

パーティショニングにはpartmanを使うのですが、パーティションサイズの指定方法が少し特殊です。Debian-Installerのドキュメントには詳しい書式やアルゴリズムが説明されていますので、詳細な設定を行いたい場合はそちらを参照してください。簡単に説明すると、以下のような流れで決定されます。

  1. サイズには"minimal size"、"priority"、"maximal size"の3種類がある
  2. すべてのパーティションは"maximal size"を越えることはない
  3. すべてのパーティションは"minimal size"を下回ることはない
  4. ディスクの総量から"minimal size"の和を差し引いた残りの容量を、"priority"の比を元に、各パーティションに少しずつ割り振っていく
  5. 4をやっていく上で、サイズが変更されないパーティションが現れたら、割り振り終了

このため、本当に固定値にしたい場合は、"minmal size = priority"にしておくと良いでしょう。さくらVPSの場合、20GBの領域が用意されているのでこれを振り分けます。以下は、実メモリを活用できることを期待してスワップは2GBほどを確保した上で、残りを/に割り振った例です。最後のピリオドを忘れないように注意してください。

d-i partman-auto/method string regular
d-i partman-auto/expert_recipe string                         \
      boot-root ::                                            \
              15000 17000 -1 ext4                             \
                      $primary{ } $bootable{ }                \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ / }                         \
              .                                               \
              2048 2048 400% linux-swap                       \
                      method{ swap } format{ }                \
              .

インストールイメージの作成

最後にこのpreseed.cfgをinitrd.gzに組み込みます。とはいっても、一度initrd.gzの中身を展開して、一番上のディレクトリにpreseed.cfgを入れて、再度梱包しなおすだけです。

$ mkdir initrd-tmp; cd initrd-tmp
$ gzip -dc ../initrd.gz | sudo cpio -id
$ sudo cp ../preseed.cfg .
$ find . | sudo cpio --quiet -o -H newc | sudo gzip -9 > ../initrd.gz

この新しくできたinitrd.gzを、⁠GRUBの設定」のときと同様に仮想マシンでGRUBから読み込むように設定すれば、インストーラ起動時にpreseed.cfgが読み込まれ、自動インストールが行われるようになります。

ポストインストールスクリプト

Preseedingにはlate_commandという、インストール完了後再起動前にスクリプトを実行できる機構が存在します[6]⁠。これを使えば、インストール後に毎回行っている設定ファイルの編集なども、インストール時に一緒に行えます。例えば、インストール時にopenssh-serverを指定しているが、sshd_configはあらかじめ用意したものを使いたいといった場合は、設定済みsshd_configとそれをインストール後の環境に反映するスクリプトをinitrd.gzに入れておくことで、インストール完了後には新しいsshd_configが反映されているといった具合に使えます。

例えば、設定を反映するスクリプトの名前をinstall.shにして、以下の内容で保存したとします。

#!/bin/sh

# backup original /etc/ssh/sshd_config
cp /target/etc/ssh/sshd_config /target/etc/ssh/sshd_config.orig

# overwrite sshd_config
cp /sshd_config /target/etc/ssh/

ここで、"/target/"はインストーラから見たインストール後のルートディレクトリになります[7]⁠。上記では、設定済みのsshd_configをinitrd.gzのルートディレクトリに保存しています。さらに、preseed.cfgの最後の方にあるように、late_commandを使ってこのinstall.shを実行するよう設定します。

# インストールの最後で実行するコマンドの指定します
d-i preseed/late_command string /install.sh

インストールイメージを作成する場合は、これらのスクリプトや設定ファイルも一緒に組み込むようにします。

$ mkdir initrd-tmp; cd initrd-tmp
$ gzip -dc ../initrd.gz | sudo cpio -id
$ sudo cp ../preseed.cfg .
$ sudo cp ../install.sh .
$ sudo chmod 755 install.sh
$ sudo cp -r ../sshd_config .
$ find . | sudo cpio --quiet -o -H newc | sudo gzip -9 > ../new-initrd.gz

上記以外にも、インストール時に自動生成されるSSHサーバの鍵をこれまでと同じものにしたい、複数のユーザを生成したいといった要望にも使えます。

まとめ

今回はインストールという観点からPreseedingを紹介しました。Preseedingは、Debianパッケージの設定ツールであるdebconfを使った設定集であり、その設定方法はすべてのDebianパッケージに応用できます。さらに「ポストインストールスクリプト」で紹介したように、任意のスクリプトを走らせることもできるため、とても柔軟にサーバ構築の自動化が行えるのです。もちろん一度作ったpreseed.cfgは他のマシンでも使用できますので、同じ構成の複数のマシンをセットアップしたい時には強力な威力を発揮します。

ちなみに、Debian-Installerのサイトには、Preseednigを使ったDebianシステムの構築例がいくつか掲載されています。また、Debianのインストールガイドであれば、Preseedingの設定についても日本語で読むことができますので、いずれも自分に適したpreseed.cfgを作る上で大変参考になるでしょう。

おすすめ記事

記事・ニュース一覧