今まで米国の VPS を使っていたが、 いつのまにか日本の VPS もリーズナブルな値段になってきたらしい。 「さくらのVPS」 がメモリ 512MB で月額 980円、 「Osukini サーバ」 ST プラン がメモリ 1GB, ディスク 100GB で月額 980円。 「さくらのVPS」 でも充分安いが、 「Osukini サーバ」 の安さは目を疑うレベル。 これはもう試してみるしかない。
実は、 最初は 「さくらのVPS」 を申し込んだのだが、 rootパスワードが見つからない事件でイカってキャンセルしてしまった。 申し込んだ直後に VPS が起動できたので、 さくら++ と思いつつ root でログインしようとしたらパスワードが分からず Web じゅう探しまわる羽目に。 万策尽きてサポートに電話したら 15分以上待たされ、 しかも担当者には root と言っても話が通じず、 別の番号にかけなおせと言われる始末。 後ほど届いた 「仮登録完了のお知らせ」 メールに root パスワードが書いてあったのだが、 メールが届く前に VPS のコントロールパネルをいじれて、 起動までできてしまう現在の仕様はいかがなものか。
Osukini サーバの場合 OS は CentOS, Ubuntu, Debian から選べるが、 「my distribution」 以外は使う気が起きないので、 どうやって私の 「独自OS」 をインストールするか、 方法を考えてみた。 もちろん、 Osukini サーバのサポートの範囲外なので、 インストールする方法だけでなく、 トラブった時の復旧方法を考えておくことが重要。
Osukini サーバでは 仮想コンソール (hvc console, リモートコンソール) が提供されない。 OS の外部から操作する手段がほとんどなく、 ブートスクリプトの設定ミスなどで OS にリモートログインできなくなってしまったら最後、 OS の再インストールしか復旧手段はない (と思う)。 しかも、 (サポートの範囲外である) 独自OS の再インストールを支援してもらえるはずはないので、 せっかくインストールした独自OS は跡形もなく消えてしまう。
再起動すれば復旧できる一時的な障害はここでは考えない。 設定ファイルなどを不適切な内容に書き換えてしまった結果、 再起動してもリモートログインできない状態が続くケースのみを考える。 実際、 サーバを運用しているとそういうトラブルはよくある。 ネットワーク設定を間違えて通信不能になるだけで、 他は全く正常でもリモートログインはできなくなるし、 あるいは sshd の設定を間違えて sshd が起動しなくなっただけでもリモートログインできなくなる。
ネットワークが全く使えなくても、 sshd が立ち上がらなくなってしまっても、 OS 自体が正常に起動していれば init から起動される getty は生きていることが多いので、 仮想コンソールさえ使えれば、 大抵はログインできて修復できる。
他の VPS, 例えば Linode や prgmr などでは、 仮想コンソールが利用できる。 さらに、 両者とも GRUB が使えるので、 複数 OS をインストールしておいて切り替えて使うこと (いわゆる 「デュアルブート」) ができる。 つまり一つの OS 上で何かトラブルが起きて OS が立ち上げ不能になっても、 別の OS (いわゆるレスキュー用 OS) を立ち上げて、 トラブった OS を修復することができる。
リアルサーバでは、 (仮想ではなく物理的な) コンソールが利用できる (当たり前)。 さらに、 トラブった時はレスキュー用の CD-ROM / USBメモリからブートして復旧作業を行なったりする。 VPS でもリアルサーバでも、 イザというときに備えて、 通常使う OS とは別に、 修復作業を行なうためのレスキュー用の OS を用意しておくことが極めて重要。
ところが、 レスキュー用 OS が一切利用できないばかりか、 仮想コンソールから操作することすらできないのが Osukiniサーバ。 トラブルに対して極めて脆弱であると言わざるを得ない。
VPS にとって仮想コンソールは必須の機能だと思っていたので、 Osukiniサーバのコントロールパネルを見て驚いた。 「再起動」 「停止」 などの操作と、 OS の初期化しかできない (値段相応? でも、 仮想コンソール機能は Xen 標準なのに...)。
OS の初期化をすれば、 全てが消えてしまう。 いわば、 クリーンインストールしかできない CD-ROM からブートするようなもの。 トラブったからといって、 即クリーンインストールしたいという人がどれだけいると言うのか?
嘆いていても仕方がないので、 どうやってレスキュー用 OS 相当のことを実現するか考えてみる。 レスキュー用 OS を立ち上げることさえできれば、 独自 OS をインストールすることも可能になる。 こんなこともあろうかと、 2年前 (2008年10月) に作っておいた ptyd (Pseudo TTY Daemon) が役に立ちそう。
ptyd はリモートログインを可能にする簡易サーバ。 initramfs の中に入れておいて、 リモートからのメンテナンスを実現する目的で作った。 特長はそのサイズで、 わずか 12KB 〜 17KB しかない。 sshd (400KB 以上) あるいは dropbear (100KB 程度) では initramfs に入れるには大きすぎるので作ってみた次第。 今まで (仮想)コンソールが使えない状況に陥ったことがなかったので、 ptyd の出番はほとんどなかったのだが、 Osukiniサーバのおかげで日の目を見ることとなった。
initramfs というのは Linux OS 起動時に、 root ファイルシステムをマウントするために一時的に起動される簡易OS のこと。 マウントしたボリュームの /sbin/init へ処理を引き継いで短い役割を終える。 (昔の Unix を知ってる) 古い人には 「ミニルート」 (mini root) と言った方が通りがよいかも。 initramfs は 2MB 程度と極小であるにも関わらず OS としての機能は一通り備えているので、 「レスキュー用」 として使えなくもない (そもそも昔のレスキュー用ディスクはフロッピーディスク一枚に収まった)。 ptyd があれば、 initramfs がリモートからログイン可能なレスキュー用 OS になるというわけ。
senri:~ $ ls -l ptyd -rwxr-xr-x 1 sengoku user 17200 Mar 5 09:20 ptyd senri:~ $ ./ptyd @(#) $Id: ptyd.c,v 1.2 2011/03/03 10:29:43 hiroaki_sengoku Exp $ Usage: ptyd <opt>.. <prog> <arg>.. opt: -p <port> ; listen port -c <sec> ; wait <sec> for connection -i <sec> ; <sec> before terminate idle connection -a <file> ; read secret from <file> -d <level> ; debug level senri:~ $ cat /tmp/SEED abcdefg senri:~ $ ./ptyd -p 1234 -a /tmp/SEED /bin/sh
などと ptyd を起動すると、 1234番ポート (-p オプションで指定, デフォルトは 9000番) で listen する。 放っておくと 10秒 (-c オプションで変更可能) でタイムアウトする。 -a オプションは今回追加した機能で、 リモートログインを受付ける際に認証を要求する。 「-a /tmp/SEED」 と指定することによりパスワードを /tmp/SEED から読み込む。
試しにリモートからログインしてみる:
asao:~ $ telnet senri 1234 Trying 192.168.1.15... Connected to senri. Escape character is '^]'. 1299285953@1234:
認証方法はチャレンジ&レスポンス方式 (APOP などと同じ)。 プロンプト 「1299285953@1234:」 にパスワード (上記 /tmp/SEED の内容) を追加した文字列の MD5 値を入力すればよい。 例えば /tmp/SEED の内容が 「abcdefg〈改行〉」 であるなら、
asao:~ $ echo '1299285953@1234:abcdefg' | openssl md5 ee5478287007435a75dd875e0e56270a
なので、 「ee5478287007435a75dd875e0e56270a」 を入力する。 認証が成功すると、 ptyd は引数のコマンド (上記の例では /bin/sh) を実行し、 その標準入出力を疑似端末経由 (ptyd の名前の由来) でリモートからアクセスできるようにする。 つまり上記の例だと ptyd を実行したマシン (senri) 上で実行した /bin/sh を、 telnet を実行したマシン (asao) から操作できる。
initramfs の中の /init スクリプトで ptyd を呼ぶようにしておけば、 ブート時にレスキュー用 OS に切り替えることができる。 つまり何かトラブルが起きて (再起動しても) VPS にリモートログインできなくなってしまったとしても、 コントロールパネルで 「再起動」 あるいは 「強制停止」 ボタンを押し、 再起動中に ptyd がタイムアウトするまえにリモートからログインすればよい。 ログインしなければ ptyd がタイムアウト (デフォルトは 10秒) して、 OS が起動する。
具体的には以下のような感じ。 ptyd が listen するタイミングをとらえるために ping を打っておく。 再起動にともなってパケットが途絶えた後 (icmp_seq=6 以降)、 再びパケットが返ってくるようになった (icmp_seq=17 以降) ことを確認してから、 1234番ポートに対して telnet を試みる。
senri:~ $ ping meguro PING meguro.gcd.org (163.43.176.212): 48 data bytes 56 bytes from 163.43.176.212: icmp_seq=0 ttl=52 time=6.447 ms 56 bytes from 163.43.176.212: icmp_seq=1 ttl=52 time=6.303 ms 56 bytes from 163.43.176.212: icmp_seq=2 ttl=52 time=8.697 ms 56 bytes from 163.43.176.212: icmp_seq=3 ttl=52 time=8.132 ms 56 bytes from 163.43.176.212: icmp_seq=4 ttl=52 time=6.226 ms 56 bytes from 163.43.176.212: icmp_seq=5 ttl=52 time=7.810 ms 56 bytes from 163.43.176.212: icmp_seq=17 ttl=52 time=9.881 ms 56 bytes from 163.43.176.212: icmp_seq=18 ttl=52 time=5.948 ms C-c --- meguro.gcd.org ping statistics --- 19 packets transmitted, 8 packets received, 57% packet loss round-trip min/avg/max/stddev = 5.948/7.431/9.881/1.329 ms senri:~ $ telnet meguro 1234 Trying 163.43.176.212... Connected to meguro. Escape character is '^]'. 1299285953@1234:ee5478287007435a75dd875e0e56270a # df Filesystem 1K-blocks Used Available Use% Mounted on /dev/xvda3 112292896 6574080 100062332 6% /mnt # cat /proc/mounts rootfs / rootfs rw 0 0 none /proc proc rw,relatime 0 0 none /sys sysfs rw,relatime 0 0 none /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0 /dev/xvda3 /mnt ext3 ro,relatime,errors=continue,barrier=0,data=writeback 0 0 # ls --color=never /mnt bin home lost+found proc srv var boot initrd.img media root sys vmlinuz dev lib mnt sbin tmp etc lib64 opt selinux usr
ptyd のプロンプト 「1299285953@1234:」 に対して、 MD5 を算出して正しいレスポンス 「ee5478287007435a75dd875e0e56270a」 を入力することにより無事ログインできた。
「#」 は initramfs の /bin/sh のプロンプト。 通常起動時に root ディレクトリとなるボリューム /dev/xvda3 が /mnt ディレクトリにマウントされている。 このボリュームには、 Osukiniサーバ契約時にインストールしてもらった Debian squeeze がインストールされている。
この Debian を /mnt/mnt/saases ディレクトリ以下に待避:
# mount -oremount,rw null /mnt # mkdir /mnt/mnt/saases # cd /mnt # mv -i [a-i]* lib* media [o-z]* mnt/saases/ # ls --color=never lost+found mnt #
この Debian を使う予定はないので、 待避せずに消しちゃってもいいのだが、 まあディスク容量が余ってるのでとりあえず保存しておくということで。
そして、 あらかじめ /mnt/mnt/root にコピーしておいた my distribution 一式を、 /mnt (つまり /dev/xvda3 ボリュームの root ディレクトリ) へ展開:
# cd mnt/root # ls --color=never -la drwxr-xr-x 14 0 0 4096 Mar 2 11:27 . drwxr-xr-x 4 0 0 4096 Mar 4 11:09 .. lrwxrwxrwx 1 0 0 7 May 3 2008 bin -> usr/bin drwxr-xr-x 4 0 0 4096 Jan 12 10:03 boot drwxr-xr-x 2 0 0 4096 Mar 2 10:21 dev drwxr-xr-x 35 0 0 4096 Mar 1 10:34 etc drwxr-xr-x 3 0 0 4096 Feb 22 05:59 home drwxr-xr-x 3 0 0 4096 Dec 12 15:19 lib lrwxrwxrwx 1 0 0 3 Oct 11 2009 lib64 -> lib drwxr-xr-x 3 0 0 4096 Mar 2 11:27 mnt drwxr-xr-x 2 0 0 4096 Mar 2 10:20 proc drwxr-xr-x 3 0 0 4096 Mar 4 01:09 root lrwxrwxrwx 1 0 0 8 Oct 9 2009 sbin -> usr/sbin drwxr-xr-x 2 0 0 4096 Mar 2 10:21 sys drwxrwxrwt 3 0 0 4096 Mar 4 00:57 tmp drwxr-xr-x 15 0 0 4096 Feb 28 11:52 usr drwxr-xr-x 12 0 0 4096 Jan 31 02:01 var # mv -i * /mnt/ mv: overwrite '/mnt/mnt'? n # mount -oremount,ro null /mnt # exit Connection closed by foreign host. senri:~ $
以上で、 Debian squeeze と、 my distribution との入れ替えが完了。 exit すれば ptyd が終了して、 /initramfs のブートシーケンスが再開し、 my distribution が起動する。
senri:~ $ ssh meguro Last login: Sat Mar 5 22:41:49 2011 from gcd.org Linux 2.6.35.11-x86_64. meguro:~ $ df Filesystem 1K-blocks Used Available Use% Mounted on rootfs 112292896 21192732 85443680 20% / /dev/xvda3 112292896 21192732 85443680 20% / none 511188 20 511168 1% /dev none 511188 0 511188 0% /dev/shm /dev/xvda3 112292896 21192732 85443680 20% /usr/bin/.suid /dev/xvda3 112292896 21192732 85443680 20% /var/root/usr/bin/.suid meguro:~ $ free total used free shared buffers cached Mem: 1022380 1005408 16972 0 195024 235496 -/+ buffers/cache: 574888 447492 Swap: 2104508 572 2103936 meguro:~ $
広〜い (^^)。 これが月額 980円なのだからスゴイ。
すごい!
私が契約したウィンサーバーのVPSは、リモートが接続できなくなって、OS初期化するのに追加料金がかかりました(泣)。
OS初期化できるだけましかも(笑)
Comment by きこ — 2011年9月12日 @ 11:41