ちょっと長くなっちゃった…。
VPS(Virtual private server)は1台のサーバに複数の仮想サーバを起動させて、それをお客さんに提供する仕組みなので、1台の実サーバを用意するよりも安価でいいのですが、1台のサーバでたくさんの仮想サーバが動くのでリソースの制限がなかなかにきついです。
しかも安価なVPSであればあるほど、リソースの制限はきびしぃ。
リソース制限の例として、回線(帯域)、メモリ、CPU、同時起動プロセス数、同時オープンファイル数、TCPの同時接続数と色々あるわけですが、今回取り上げるのは「同時起動プロセス数」。
同時起動プロセス数はその名のとおり、同時に起動できるプロセスの数であり、VPSではこの値が通常のサーバよりもかなり低く設定されている。
このあたりの数値はレンタルサーバによっては、普通に公開されていて、低いところだと60とか、上位プランになれば100とか300とか増えていく。
ちなみにこのサイトが動いているサーバ(正確にはVPSじゃなく、もっと安い共用サーバなんだけど)の、同時起動プロセスは30程度だったりする(もうちょっとあったかな?)。
で、この同時起動プロセスがあまり高くないVPSに、万を越えるメールを一気に送りつけるとだ、どうなるかというと一瞬でプロセスが全て食い尽くされる。例えばプロセス上限が70としたら、70プロセスが常に立ち上がりっぱなしになる。
こうなるとこのVPSに対しては何もすることが出来ない。いや、正確に言うと「プロセスが増える(forkする)処理が伴う、処理」は全て実行できない。
※named(bind)とかの応答は別にプロセスがforkするわけじゃないので、DNSサーバとかは普通に機能する。
困るのは(例外もあるけど)Web、ftp、mail、ssh、telnetとか。というか主要サービスほぼ全てorz
apacheとかはworkerプロセスとかで動かせば大丈夫かもしれないけど、残念ながらたいがいのapacheはpreforkなんです。
それでプロセスを食いつぶされていたら、その原因となっている処理を止める必要があります。メールが大量に送られている場合はsendmailを一時的に止めるとか。
VPSは基本的に外のレンタルサーバから借りてる事がほとんどなので、sendmailを止めるにはまずVPSに対してssh接続をする必要があります。そのとき第一の関門があって、ssh接続もプロセスをforkする処理のため、それ以上プロセスが増やせずに処理に失敗してつながりません\(^o^)/
ただ、プロセスは常に上限に達しているわけではありません。メール受信の嵐の中でも、メールのキュー処理の嵐の中でも、処理は確実に進められています。自分の役割が終わったプロセスはそのまま終了し、同時起動プロセス数に1つ空きができます。そして間髪いれずに次のメールが送られてきたり、メールのキュー処理が始まり、空いたプロセスがすぐに埋まります。
そう、狙うはプロセスが落ちた瞬間。その空いたプロセスは誰のものでもない。早い者勝ち。次のメール要求が来るよりもはやく、ssh接続を行えばよい。
そうするとssh接続が出来る。
…が、悲しい事にssh接続処理中に多分2回くらいプロセスのforkする処理がはいってるっぽい(中の詳しい動きはよくしらない)。なので、2回程、他のプロセス終了の瞬間をばっちり狙う「運」が必要ってことです。
これは非常に確立が低い。
ちなみにtelnet接続もforkしますが、こっちは1回のforkでOKっぽいので、sshより接続できる可能性はぐっと高い。
ただ、こちらは最近の動向ではtelnet利用禁止になる動きがつよく、肝心なときにそもそも利用できない事が多い。でも、ほんとプロセス食いつぶしたときのtelnetは頼みの綱だと個人的に思う。使えないけどorz
と、サーバにログインするところから大変なのですが、運良くssh接続する事ができたとします。とりあえず現状のリソースはどうなってるかと、psやtopコマンドを実行しようとすると、こんな感じのエラーがでて動かない。
No more processes.
psとかも1プロセス立派に使います。なので、これも他のプロセス終了の瞬間を狙わないといけません。狙うというが、ひたすらpsコマンドを連打するしかないんだけども。
ちなみにほとんどのコマンドがなかなか実行できません。lsとかlessとかcatとかnetstatとか全部アウト。
シェル内臓のコマンドになるcdとかechoなら動くので、lsの代用は「echo *」でなんとななったりする裏業もあったりします。
psでなんとかプロセスを見る事が出来て、sendmailが大量に起動しているようでしたらとりあえずsendmailプロセスを止めましょう。で、sendmailを止めるコマンドを入力。
No more processes.
まぁ動かないんですよ。しかもsendmailのようなデーモンを止めるコマンドは基本的にスクリプトの塊りで、コマンドの中でも別のコマンドを実行していたりしてます。つまりこれはpsやtopみたいな単純なコマンドに比べて、更に「運」が必要です。というか多分無理、動かない。経験者は語る。
デーモンの再起動がだめならじゃぁOSの再起動だっ。って事で「reboot」実行!
No more processes.\(^o^)/
これはもう説明する必要もないですね。
デーモンの停止もOSの再起動も難しいので次はどうするか?次は問題を起こしているプロセス、つまり今の例ではsendmail。こいつをkillコマンドで殺します。
デーモンの停止コマンドで丁寧にsendmailの停止なんてやってられません。なんど実行しても動かないし。
kill プロセスID で基本的にプロセスは落ちますが、落ちないときはkill -KILL プロセスID でもっと強制的に落とします。
sendmailの場合、メールのロストとかの可能性もありそうで怖いのですが、背に腹は変えられません。多分、sendmailも長年のノウハウの積み重ねで極力メールのロストをしないような設計になっているはずなので、きっと大丈夫なはず。うん。
killで問題のプロセスを落とす事ができたら、同時に起動しているプロセスもかなり減って、快適に各コマンドを実行できるようになります。その間に色々とプロセスを増大させない対策をします。
メールの大量受信が原因だったら、こんな感じでいくつか対応方法がありそう。
・送信元のメールサーバに大量配信をやめてもらう(これは事前にお願いしててもいいかな)
・大量に発生したメールのキューでいらないのを消す
・大量配信元のメールサーバからの受信を拒否するようにiptablesに記述
・問題のユーザ宛のメールを一時的に/dev/nullに行くように仕向ける
・問題のユーザを消してみる
対策が終わったらsendmailを改めて起動。あとプロセス数が頭打ちした歳、変なゾンビプロセスとか残っている可能性があるので、可能なら一度VPSの再起動をしたほうがいいかも。
と、気づいたら長くなってしまったけど、これはVPSにおける最大の欠点だと思う。ssh接続をしたいのに出来ないジレンマ、やっと接続できたのにコマンドが実行できないジレンマ、その間に発生するお客からの問い合わせ。
でも、VPSは安いんだよなぁ。。。うん。
作成日:2009/09/10 02:49:27