さくらのクラウドには「アーカイブ」というのがあって、プレインストールされた様々なOSのディスクイメージが用意されている。代表的なOSや各種ディストリビューションが選べるようになっていて、選択してインストールするだけですぐに利用できるようになっている。ラインナップされたものを利用するだけならば、これで特に不満はないが、さくらが用意していないOSや、設定を変えたい(たとえばパーティショニングに不満があるとか)場合には、自分でインストールをし直すなどの手間暇をかける必要がある。
もちろんそのための手段は全部用意されている。具体的には、インストールISOイメージを用意してそこからVMをブートし、好きなようにインストールしてからディスクイメージを「マイアーカイブ」としてセーブしてしまえばいい。そこから作るサーバは自分のお好みの設定になっているという訳だ。
しかし、インストーラを使った作業というのは、ボタンをポチポチ押すのが面倒だ。インストール作業そのものは、そんなにしょっちゅうやることではないが、一度取り組むとピタリと狙ったものを作るまでに何度も作業を繰り返すことになったりする。そのたびに設定を変えながら繰り返し実行するのは面倒くさい。そこで設定をファイル化して、なるべくバッチ化・自動化したい。
そこで本稿では、インストール作業を自動化するKickstartの使い方を説明する。
Kickstart
KickstartはFedora/Redhat/CentOSで利用できるインストール自動化ツールだ。利用の流れを大雑把に説明するとこんな感じだ。
- 設定ファイルを用意しておく
- インストールメディアでブート
- 通常のインストールではなく、Kickstart設定ファイルを指定
- あとは完了するのを待つだけ
通常のインストールでは、GUIで様々な項目を指定・設定していくが、Kickstartの設定ファイルを書けば、ほぼすべての項目が設定できる。またKickstart内ではスクリプトも書けるし、対象マシンがネットに繋がっていれば外からデータも引っ張ってこられるので、事実上何でもできる。初期インストールでどこまでやるかはお好みの問題なので、ここでは必要最低限ということにしておき、例としてfail2banだけ追加する。さもないとsshポートにわんさかscanが来てしまうからだ。
設定ファイルをどう書くか
さてKickstartの設定ファイルをどう書けばよいだろうか。参考になる情報が2つある。ひとつは、手動でインストールしたときに生成される /root/anaconda-ks.cfg
だ。実はこのファイルはKickstartの設定ファイルになっているので、これを調整すればお好みの設定にするのは比較的簡単だ。
もうひとつは、さくらインターネットが公開している「アーカイブを作成したときに使ったKickstart設定ファイル」だ。
これらを参考に、必要なものを入れ、不要なものを削除するというのがよいかもしれない。
Fedora 30用Kickstart
それではまず、現時点の最新であるFedora 30をインストールするKickstartを示そう。
#version=DEVEL ignoredisk --only-use=vda # System bootloader configuration bootloader # Clear the Master Boot Record zerombr # License agreement eula --agreed # Use text mode install text # Use CDROM installation media cdrom # Keyboard layouts keyboard --vckeymap=us --xlayouts='us' # System language lang en_US.UTF-8 # Firewall configuration firewall --enabled # Network information network --hostname=localhost.localdomain # Root password rootpw --iscrypted $6$otaxm.aCZGDxBs9R$bhSlTM8CTfne6kHYwITK3xKgO0Ow33eZbREzfzKCjcVh0iS74.B6bVFR2lOMQJCi7xFuncOokYWkGR0WEDxuN0 # SELinux configuration selinux --disabled # Run the Setup Agent on first boot firstboot --enable # Do not configure the X Window System skipx # System services services --enabled="chronyd" # System timezone timezone Asia/Tokyo --isUtc --ntpservers=ntp1.sakura.ad.jp # Disk partitioning information part biosboot --fstype="biosboot" --onpart=vda1 part swap --fstype="swap" --onpart=vda2 part / --fstype="xfs" --onpart=vda3 --label=root %pre sgdisk -Z -n 1::+1M -n 2::+4G -n 3:: -t 1:ef02 -t 2::8200 -c 1:"BIOS boot partition" -c 2:"Linux swap" -c 3:"Linux filesystem" /dev/vda %end %post --log=/root/post-ks.cfg set -x dnf -y update # fail2ban dnf -y install fail2ban cat <<EOL >/etc/fail2ban/jail.local [sshd] enabled = true EOL systemctl enable fail2ban # network cat <<EOL >/etc/sysconfig/network NETWORKING=yes HOSTNAME=localhost.localdomain EOL cat <<EOL >/etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 BOOTPROTO="dhcp" ONBOOT="yes" EOL cat <<EOL >/etc/resolv.conf nameserver 133.242.0.3 nameserver 133.242.0.4 EOL # grub sed -i '/^GRUB_CMDLINE_LINUX/s/rhgb quiet/consoleblank=0 net.ifnames=0 biosdevname=0/' /etc/default/grub grub2-mkconfig -o /etc/grub2.cfg # sysctl cat <<EOL >> /etc/sysctl.conf # Do not accept RA net.ipv6.conf.default.accept_ra=0 net.ipv6.conf.all.accept_ra=0 net.ipv6.conf.eth0.accept_ra=0 EOL # cleanup batch cat <<EOL > /root/clean.sh rm -rf ../tmp/* rm -rf ../var/log/anaconda* rm -f ./*.cfg ./clean.sh EOL %end %packages @^server-product-environment -cockpit* gdisk %end
ポイントとなる部分について、以下に説明していこう。
ディスクのパーティショニング
インストーラを使っていると、ディスクを思った通りにパーティショニングできずにイライラすることが多い。インストーラは万人に使えるようにしないければならないので仕方がないが、ぶっちゃけfdiskをそのまま開放してもらった方がずっと楽というのが自分の意見だ。Kickstartなら、それが思いのまま利用できる。
Kickstartでは %pre
というディレクティブが利用できる。これはインストール処理の前に実行するスクリプトを記述できる。ただし実行環境はインストーラのramdisk上なので、非常に貧弱で限られたことしかできないことに留意しなければならない。とはいえやりたいことはパーティショニングなのでまったく問題はない。
%pre sgdisk -Z -n 1::+1M -n 2::+4G -n 3:: -t 1:ef02 -t 2::8200 -c 1:"BIOS boot partition" -c 2:"Linux swap" -c 3:"Linux filesystem" /dev/vda %end
sgdiskコマンドはgdisk(fdiskのGPT対応版)のスクリプト対応版で、コマンドラインでバッチ処理するときに便利だ。オプションをばらすとこういう意味になる。
-Z | Zap。ディスク全体を初期化する |
-n 1::+1M | パーティション1を1MB切り出す |
-n 2::+4G | パーティション2を4GB切り出す |
-n 3:: | パーティション3を残り全部使って切り出す |
-t 1:ef02 | パーティション1のラベルをEF02 (BIOS)にする |
-t 2:8200 | パーティション2のラベルを8200 (swap)にする |
-c … | パーティションに名前を付ける |
%pre
で処理が終わったら、Kickstartが処理を行う。具体的には
# System bootloader configuration bootloader # Clear the Master Boot Record zerombr
# Disk partitioning information part biosboot --fstype="biosboot" --onpart=vda1 part swap --fstype="swap" --onpart=vda2 part / --fstype="xfs" --onpart=vda3 --label=root
のあたりだ。特に35~37行が、各パーティションに具体的にBIOS、swap、/マウントポイントを割り当てている。ファイルシステムについてお好みに書き換えたいなら、ここを変更してもらいたい。
IPアドレスに関する事項
最近のIPアドレス周りの設定については、デバイス名が伝統的なeth0からens3(なんで3?)みたいなのに変更され、ちょっと面倒なことになっている。さくらのクラウドではこの変更を抑止し、伝統的なeth0、eth1…を使い続けている。これを実現するために、grubの設定に次のような設定を追記している。
net.ifnames=0 biosdevname=0
この上で、さくらのクラウドのシステムはインターネット上位側(バックボーン側)がeth0と仮定し(システム上そちら側を上位につなぐ仕様になっている)、設定ファイルを書き換えようとする。具体的には /etc/sysconfig/network-scripts/ifcfg-eth0
などのファイルだ。このルールに従っていれば、コンパネやAPIのIPアドレス変更が利用できる。
さてKickstartでこれを実現するにはどうすればよいだろうか。第一の方法として、Kickstart起動時に上記のgrubオプションを手動で指定する方法が使える。これをやるとインストール処理そのものをeth0でやってくれ、最終的な設定ファイルもifcfg-eth0
でセーブしてくれる。だが手動で打ち込むべき手間が増える。
第二の方法はさくらのクラウドがやっているKickstart内で設定ファイルを書き換える方法だ。記述するべき内容は増えるが、実行するのはプログラムなので面倒はない。こっちに合わせておけばクラウドの仕様に合致するので無難ともいえる。
ネットワークの設定は、インストール処理が終わった後の %post
ディレクティブ内で指定する。ちなみに%post
ディレクティブ内は、インストール処理後のディスクイメージにchrootした環境下で実行されるので、ほぼすべての処理が思いのままに実行できる。
# network cat <<EOL >/etc/sysconfig/network NETWORKING=yes HOSTNAME=localhost.localdomain EOL cat <<EOL >/etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 BOOTPROTO="dhcp" ONBOOT="yes" EOL cat <<EOL >/etc/resolv.conf nameserver 133.242.0.3 nameserver 133.242.0.4 EOL # grub sed -i '/^GRUB_CMDLINE_LINUX/s/rhgb quiet/consoleblank=0 net.ifnames=0 biosdevname=0/' /etc/default/grub grub2-mkconfig -o /etc/grub2.cfg
ここでは3つのファイル(/etc/sysconfig/network、ifcfg-eth0、resolv.conf)を作成している。さくらのクラウドでは、VMインストール時にこれらをオーバーライトするので多少適当でもかまわない。特にIPアドレスはDHCP対応なので、このまま起動してもアクセスは可能だ。
最後のGRUBの設定はちょっとトリッキーだ。「rhgb」と「quiet」は起動時のグラフ表示を行うオプションだが、自分好みでないので削除している。代わりにコンソールのスクリーンセーブ機能のOFFと、eth0記法にするためのおまじないを入れる。そのうえでgrub2.cfgをアップデートして完了だ。
パッケージの追加
例示している設定ファイルではcockpitを削除している。cockpitの詳細は理解していないのだが、Webコンソールというのは気に食わないのでぜひ削除したい。そこで最初から削除しておきたい。
%packages @^server-product-environment -cockpit* gdisk %end
ところがこれを削除すると、一緒にgdiskも入れてもらえなくなるので、それを改めて追加している(ほかにもいろいろなくなるが、見たところ困らなそうだったのでgdiskだけ戻している)
このほかに、fail2banもぜひ入れておきたいが、指定してもうまくいかない。Kickstartのマニュアルによれば、指定できるパッケージ名は repodata/comps.xml を見よとある。これは要するに、インストールISO上のファイルと言うことだろうが、例示したり引用するのは面倒なのでやらない。いずれにしてもこれからパッケージ名を探すのはちょっと骨が折れそうだ。どちらかと言えば、%pre
の中からyum…じゃなかったdnfした方がいいような気がする。というわけでその方法でfail2banをインストールしてみる。
# fail2ban dnf -y install fail2ban cat <<EOL >/etc/fail2ban/jail.local [sshd] enabled = true EOL systemctl enable fail2ban
Fedoraのパッケージのfail2banは、デフォルトでは何もしてくれないので、自分でjail.localを書かなければならない。というわけで上記のようにファイルを用意してenableするコードを入れている。これで作成したサーバは最初から保護された状態になっている。
rootpw
rootのパスワードだが、もちろんこのままではいけない。適切にハッシュされた符号列を入れるべきだ。rootpwの行はこのone-linerの出力で丸ごと置き換えてほしい。
perl -e 'print "rootpw --iscrypted ", crypt("mypasswd", "\$6\$".substr(crypt(rand(1), "\$6\$"), 10, 16)), "\n";'
その他もろもろ
いろいろ細かいオプションがあるが、あまり変更するべきところはないと思う。強いて言えばkeyboardとlangぐらいだろうか?
Kickstartによるインストール手順
では具体的にKickstartでインストールしてみよう。さくらのクラウドでは、Fedora 30のISOイメージはパブリックISOイメージとして用意されているので、選択するだけでブートできる。
ISOイメージの指定のほかに、サーバの情報 >> タグ欄に「@boot-cdrom」という特殊タグを追加しておく。こうするとディスクより優先してISOイメージからブートするようになる。これは後の掃除のときに必要になる(掃除しなくてもよければ、この工程は不要だ)。
そうしておいてサーバを起動して、コンソールからアクセスすると、おなじみのインストーラが起動する。カウントダウンが始まっていると思うが、ここでTABキーを押す。するとインストーラに対してオプションを指定できるようになる。
Kickstart設定ファイルを与える方法はいくつかあるが、HTTP経由でネットワーク越しにアクセスさせる方法が一番楽だ。適当なWebサーバ上に、作成したKickstartファイルを置き、そのURLをインストール画面から入力する。「inst.ks=https://…」のように記入する。
できたらリターンキーを押す。後は終わるのを待つだけだ。
例示したスクリプトにはdnf updateを含むので、終わるのに10分間ぐらいかかる。最後までいくと、こんな画面になって止まる。
メッセージの通りにリターンキーを押してリブートする。上述の手順通りに「@boot-cdrom」タグをつけていれば、再びISOイメージからブートしてインストーラが起動するはずだ(さもないとインストールが完了したFedoraが起動する)。ここで、Troubleshootingを選択する。
次に Rescue a Fedora system を選ぶ。
これで、ramdisk上のシステムからディスクをマウントした状態でマシンをブートできる。途中で質問されるので、「1」と答えておく。
最後にリターンキーを押せば、shellに落ちて何でもできるようになる。インストールが終わったディスクは /mnt/sysimage にあるので、これをチェックする。
インストールの結果のログ、特に%post
処理の結果は post-ks.cfg
にセーブされているので、これをチェックしておく。もしanaconda全体の動作を確認したいなら、../var/log/anaconda/*
を見ればよい。問題がないと判断できたら、clean.shというファイルがあるのでこれを実行しておく。
sh clean.sh
これは何をしているのかというと、Kickstart設定ファイルのここに書いてある。
# cleanup batch cat <<EOL > /root/clean.sh rm -rf ../tmp/* rm -rf ../var/log/anaconda* rm -f ./*.cfg ./clean.sh EOL
ようするにログファイルを消し、/tmpをキレイにして、自分を消して終わる。お好み次第だが、実行しておくことをお勧めする。
最後にpoweroffして、ディスクを丸ごとアーカイブすれば終わりだ。
さくらのクラウドのディスク修正機能
さくらのクラウドにはディスク修正機能というのがあって、作成するサーバのIPアドレスやパスワードを書き換えられるようになっている。だがこれはさくらのクラウドが公式にサポートする「アーカイブ」で供給するイメージでないと利用できない。自作イメージである「マイアーカイブ」でも、仕様を一致させれば利用できなくはないが、前提条件が結構厳しい。マニュアルによると;
CentOS
https://manual.sakura.ad.jp/cloud/storage/modifydisk/about.html#centos
最後の位置のパーティションのパーティションタイプが8300
であること
最後の位置のパーティションのファイルシステムがext4
であること
最後の位置のパーティションに ディスク修正での修正対象のファイル が存在すること
最後の位置のパーティションに/etc/redhat-release
ファイルが存在し中身を初期状態から変更していないこと
などとなっている。
白状すると、この機能の2番目のバージョンは自分で書いた(1番目は社長が書いた)のでどういう理屈かはよく分かっているのだが、特定ファイルを壊さないように変更するために、システムが本当に自分の知っているディストリビューションかどうかをチェックしようとして色々前提を置かざるを得ないのだ。このため、Fedoraを対応させたいと思っても、/etc/redhat-release
の内容チェック(現在のバージョンでも変わっていなければ if (m/CentOS Linux release [67]\.\d+/) {...}
みたいになっているはずだ)を書き換えてもらわなければならないのだ。で、これが結構大変なのである。というのも中途半端に対応してユーザのシステムを破壊したら大変なことになってしまうからだ。
この危険を承知で、ディスク修正機能をだますことは可能だ。というのは前提条件は上記の通り公開されているので、その通りにシステムを作れば書き換えてくれるのである。つまりFedoraでは /etc/redhat-release
には
Fedora release 30 (Thirty)
と書いてあるわけだが、これを
CentOS Linux release 7.6.1810 (Core)
などと書き換えてしまえばいいのだ。しかしこんなことをして他の副作用はどうなるのか責任は負えない…。このほか、ファイルシステムにはxfsを指定しているがext4に戻さなければならなかったりする。現状ではDHCPでブートできるので、後からバッチで書き換えた方がいいように思われる。