仙石浩明の日記

2011年3月7日

Osukiniサーバを使ってみた 〜 仮想コンソールが提供されない VPS で独自OS をインストールする方法

今まで米国の 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, 例えば Linodeprgmr などでは、 仮想コンソールが利用できる。 さらに、 両者とも GRUB が使えるので、 複数 OS をインストールしておいて切り替えて使うこと (いわゆる 「デュアルブート」) ができる。 つまり一つの OS 上で何かトラブルが起きて OS が立ち上げ不能になっても、 別の OS (いわゆるレスキュー用 OS) を立ち上げて、 トラブった OS を修復することができる。

リアルサーバでは、 (仮想ではなく物理的な) コンソールが利用できる (当たり前)。 さらに、 トラブった時はレスキュー用の CD-ROM / USBメモリからブートして復旧作業を行なったりする。 VPS でもリアルサーバでも、 イザというときに備えて、 通常使う OS とは別に、 修復作業を行なうためのレスキュー用の OS を用意しておくことが極めて重要。

ところが、 レスキュー用 OS が一切利用できないばかりか、 仮想コンソールから操作することすらできないのが Osukiniサーバ。 トラブルに対して極めて脆弱であると言わざるを得ない。

Osukini Server Control Panel

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円なのだからスゴイ。

Filed under: システム構築・運用 — hiroaki_sengoku @ 08:36

1件のコメント »

  1. すごい!

    私が契約したウィンサーバーのVPSは、リモートが接続できなくなって、OS初期化するのに追加料金がかかりました(泣)。

    OS初期化できるだけましかも(笑)

    コメント by きこ — 2011年9月12日 @ 11:41

この投稿へのコメントの RSS フィード。

コメントする