T

Windows AzureでCentOS

今日、「クラウド電話API!Twilio API 勉強会 Vol.10 @東京」のイベントでちょこっとお手伝いと宣伝+自慢に行ってきたのですが、Microsoftさんのご好意によりWindows Azureのお試しアカウントを頂きました。IISの運用経験がほとんどないので、いったいどうしようかと思っていたのですが、お話を伺うと別に普通にCentOSも動くということなのでさっそく動かしてみました。Azureのイベントということで、なんか萌えキャラとかばんばん見せられたらうんざりと思っていたら、そんなの一瞬たりとも出てこなかったので大変好感を持ちました。まあAzure自体がまだ英語のままの部分もあったりして日本ローカルの部分は少ないっぽいんですが、そのお陰でセットアップまで一度も幼稚なアニメキャラとか見ないで済みました。すばらしいです。

Azure上の仮想サーバの作成自体はめちゃめちゃに簡単です。事前準備としてSSHでのログインに鍵認証を利用したかったので事前にopensslでcerまたはpam形式の鍵ペアを作成しておくといいでしょう。

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out cert.pem
$ chmod 600 private.key
$ openssl  x509 -outform der -in cert.pem -out cert.cer

ダッシュボードで仮想マシンを作成します。下の方に新規追加ボタンがあるので「コンピューティング」→「仮想マシン」→「ギャラリーから」を選択すると「OpenLogic」としてCentOSが表示されます。

azure1

OpenLogicというのはCentOSのサポートなどを提供する会社だそうです。こいつを選択して、上で作成したキーの公開鍵の方を登録すれば準備完了です。しばらく待てばサーバが起動するので(デフォルトでSSHのポートが開いています)、早速ログインしてみましょう。サーバはデフォルトで○○.cloudapp.netという名前で公開されるようです。好きな名前をつけてください。最初のユーザーアカウントもここで決めることが出来ます。

$ ssh -i private.key your_name@○○.cloudapp.net

これでいつものCentOSにログインできます。特にサービスは起動していません。また外部からの接続もSSHのポートしか開放されていないので、このままでは何も出来ません。iptablesが起動しているのですが、Azureの環境自体でインバウンドのアクセスはコントロールできるので、細かい制御をしない場合はiptablesを落としてしまってもまあ大丈夫です。

が。困ったことにビルド関連のツールが一切入っていません。そこでyumでインストールしようと

$ sudo yum groupinstall 'Development Tools'

を実行してみたのですが、kernel-headerのバージョンがどうこうといわれてエラーになってしまいます。というのも、デフォルトでyumはkernelを除外するようになっており、その設定を変更しないといけないからです。/etc/yum.confには

exclude=kernel*

としっかり記述されているので、これを

#exclude=kernel*

に書き換えるとインストールできるようになります。なぜ除外されていたのかわかりませんが、開発関連のツールのインストールが終われば元に戻しておいてもいいでしょう。

ここまで来たら、あとはいつもの作業です。nginxやrbenv、bundlerやrailsをインストールするともうほとんど完成です。めでたしめでたし。

おっと、1つ忘れてはいけないことが。Azure上の仮想マシンの一覧から作成した仮想マシンを選択し、その管理画面からエンドポイントを選択します。デフォルトではSSHしか開放されていないので、ここにHTTPを追加してみます。

endpoint

しばらく待つと設定が完了し、リモートから80番ポートへのアクセスを受け付けるようになります。

これで準備が完了しました。あとはAzureのストレージを利用するgemなんかを試してみると面白いかもしれません。

Apacheの救急救助手順

最近Apacheの設定なんか知らないという人が増えたのでメモ。急にアクセス数が増えてサーバのロードアベレージが跳ね上がり、レスポンスが返らなくなったサーバについて質問されたとき、どこをどう確認するか、いつもあまり考えずにやってることを記録する。専門ってわけじゃないので、応急処置として何をしているのか見る感じ。対処法はそれぞれのシステムで違うだろうけど。

Apacheのログを見られるなら、それを最初に確認する。意外なことにディスク容量が足りなくて動かなくなっていたり、ファイルシステムの上限設定に引っかかっていて動かないケースも結構あるのだ。それから、セマフォキューが書き込めなくなっていることもあるが、これが一番見つかり難い。Apacheのエラーログに

[emerg] (28)No space left on device: Couldn't create accept lock

こんなのが出ているのにディスクの残り容量やクォータに問題がなければ、セマフォの問題なのでクリアしないといけない。

// rootで
# for i in `ipcs -s | awk '/httpd/ {print $2}'`; do (ipcrm -s $i); done

手慣れたサーバ管理者なら、こんな感じのワンライナーをどこかに保存してあるはずだ。ここを参考にした記憶がある。

MuninやNagiosなどで監視しているなら、最初に必ず確認しよう。証拠も無しにあれこれ手を出したり推測で動き出すのは愚か者に特有の対応だ。もちろんサーバがレスポンスを返せないような状態になったら何の情報も取れなくなっているだろうが、たとえそうであっても、そうなるに至るまでの過程は見える。Apacheのウェブサーバで提供しているサービスなら、たいていCPUが原因で死ぬことはないので、I/O waitとかSWAPの発生、メモリの使用状況とかを真っ先に見る。別に難しい理屈はない。I/O waitが伸びていてSWAPが発生していれば、メモリの使用状況もひどいことになっているはずなので、それらが一致していれば、ああApacheに割り当てられたリソースをシステム側で供給維持しきれなくなって暴動が起きたんだなと理解できる。PHPなんかが動いているpreforkのApacheなら、プロセス数がMaxClientsまで達したかどうかを見るといいかもしれない。達していれば単純に性能の限界だったんだろう。その前にコケていたなら、設定が間違っている。まあ、あんまりきちんと設定されていないサーバでは、大概は達する前にコケている。そんなときは、とりあえずApacheがどれくらいメモリを食うのか調べてみるのも一興。

$ ps ax | grep httpd | grep -v grep | awk '{print $1}' | while read pid
do
cat /proc/$pid/status | grep VmHWM
done

ひゃっほう、Apacheのプロセスたちが物理メモリをピーク時にどれだけ使ったか表示される。これらの数値を見て、まあ大きい方のやつがApacheのMaxClientsの分だけ起動したらどうなるかかけ算すれば、リソースをApacheに食い尽くされないMaxClientsの設定値が見えてくるはずだ。80MBのプロセスがいるなら、まあみんなが最大値になってしまうことはないけれど、そいつをシステムの物理メモリで割った値にちょっと手加減するくらいならなんとかなると見当がつくだろう。

上のやつだとkB単位で個々に結果が表示されるので、どうせなら一気にその合計まで出そう。

$ ps ax | grep httpd | grep -v grep | awk '{print $1}' | while read pid
do
cat /proc/$pid/status | grep VmHWM
done | awk '{sum += $2} END {print sum}'

手元のサーバで実行したら642964だった。kBだから640MB程度。まだまだ大丈夫そうだ。

他にも、サーバに運良くログインできれば、例えばvmstatやsarを実行してみる。

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0 307012 212128 118136 2375840    1    1    23   103    8    9 10  2 88  0  0
 1  0 307012 210656 118148 2375848    0    0     4   136  694  606  3  1 97  1  0
 0  0 307012 211416 118152 2375852    0    0     0   124  589  478  4  0 95  0  0
 0  0 307012 206736 118152 2375880    0    0     4    12  785  630  5  1 93  0  0
 0  0 307012 214992 118152 2375888    0    0     8     0  429  297  1  1 98  0  0
 0  0 307012 208428 118152 2375908    0    0     0   168  506  694 22  2 76  0  0
 0  0 307012 211900 118152 2375920    0    0     0   168  809  614  7  3 90  0  0
.......

$ sar 
(略)
10時00分01秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
10時10分01秒       all     10.96      0.20      2.01      0.25      0.02     86.57
10時20分01秒       all     11.01      0.27      1.92      0.36      0.02     86.42
10時30分01秒       all     11.55      0.23      2.11      0.32      0.02     85.77
10時40分01秒       all     11.27      0.20      1.86      0.21      0.02     86.44
10時50分01秒       all     11.05      0.38      1.73      0.22      0.02     86.61
11時00分01秒       all      7.74      0.20      1.55      0.14      0.02     90.35
11時10分01秒       all     10.51      0.21      2.31      0.34      0.02     86.61
平均値:        all      9.86      0.24      1.58      0.39      0.02     87.90

上は一時的に死にかけたけど健康を取り戻しつつあるサーバの例。vmstatのswapの欄で頻繁にsiとかsoが出ていたり、swpdの値が増え続けているなら非常にまずい状態だ。ApacheのMaxClientsを下げてでもリソース消費を抑えないとサーバにログインさえできなくなるかもしれない。OOM Killerに大事な身内を殺される前になんとかしないといけない。またsarでiowaitの増減を確認すると問題の起きる時間帯がうまく特定できる。

娘が自らオムツを外して床におしっことうんこをするというチャレンジに成功したので、掃除や着替えに忙しく中断していたら、何を書こうとしていたのか思い出せない。ええと、最近のクラウンド環境とかだと、物理サーバの頃よりますますI/O性能に引っ張られてしまう傾向にあるから、まずはこれらの確認が大事になる。

それから、忘れてはいけないのがserver-statusで、SSHでトンネル掘ってでも見に行くべきだ。レスポンスが遅くなっているページがあればすぐに見つかるし、例えばApacheからImageMagickのプロセスを呼んでそのまま刺さりっぱなしになっているリクエストなどが見つかり、そいつがプロセスを占有しているのが問題の原因だったりすることもある。それから、現在のスロット(preforkだったら各プロセス)のステータスがリアルタイムで表示されるのも面白い。

CC__.WWCC..WCK.KKKKW..WWKKW.....................................
................................................................

例えば、Kはデータの送出が終わってもKeepAliveで一応待っている状態のやつ、Wがデータを送出中、Cは接続終了処理中で、「.」は接続を待ち受けているやつだ。もしレスポンスが悪くて困っているなら、場合によってはいっそKeepAliveを切ってしまってもいいだろう。感覚としては、PC向けのサービスで帯域の利用状況が問題になってはいないケースなら切ってしまうことの方が多い。

とりあえず、初動としてはまずはこんな感じの対応をする。いずれも安定稼働しているサーバのメンテでやっていることなので、それ以外は別の対処があるだろうし、アプリケーション側で出来ることもたくさんあるが、夜中の連絡で緊急出動する場合はそこまでやっていられないだろう。

rbenvでcron

しょっちゅう忘れるのでメモ。rbenvの環境でRubyをcronから実行すると、細かい実行環境の違いで失敗する。なので、こんな工夫が必要になる。

42 4 * * * /bin/bash -c 'export LANG=ja_JP.UTF-8;export PATH="$HOME/.rbenv/bin:$PATH";\
 eval "$(rbenv init -)";ここから実際にやりたいことを書く'

* 実際には一行で。

まず-cでbashを続く文字列から読み込んで実行するモードにする。LANGの設定をここかcrontabの先頭で指定しておかないとRubyのスクリプトの先頭に「# -*- coding: UTF-8 -*-」と書いていても非ASCII文字がどうたらというエラーになる。PATHも同じで、インラインで書くなら上みたいな感じにする。あとはおまじないだと思いましょう。

自宅サーバが亡くなりました

2009年の9月から稼働していたhpのProliant ML115 G5が(おそらく電源の故障がきっかけで)動かなくなってしまいました。マザーボードの交換がめんどい機種なので部品の交換では難しく、思い切って近所のPC Depoに出かけたらセール品だけでなんとかなりそうだったので、時間もないので購入してしまいました。さようならAMD、こんにちはIntel。量販店にXeonなんかないですからCore i5にしましたが、対応マザーボードも安くてECC無しのメモリで動くからまあいいです。それに、よく考えたらSandy Bridgeは家のどのマシンよりハイスペックです。通販で買う方が多少は安いパーツもありましたが、DDR3のメモリとマザーボード、ケースでしめて35,000円くらいでした。HDDとDVDドライヴ、ケーブル類は元のマシンからの流用です。

ついでにESXi 5.0に更新しました。バージョン3の時代みたいに無茶なことをしなくてもHDDにインストールできるようになったんですね。

ただ、いくつかデータプールにあったVMが消えてる気がするんだよな…

zsh、rvm、vim

zshを使ってみて、vimでファイルの編集中に「:!ruby %」で実行したらrvmがちゃんと動いていなかったので調べたら、vimは.zshrcを読まなくて、かわりに.zshenvを読み込んでいた。ln -s ~/.zshrc ~/.zshenvする必要がある(.zshenvを置いてない人は)。

参考はこちら:rails.vim, rvm, ZSH, and a curious (infuriating) bug

hdd死亡

みんなのブログをホスティングしていたマシンのhddが死にました

バックアップがあるので華麗に復旧、と思ったら、バックアップ用のディスクが死んでいるではありませんか!

\(^o^)/

さくらのVPSでLokka(コピペでインストール)

デフォルトのCentOS release 5.5だとRuby 1.8.5になってしまうので、えいやとソースからインストール。Lokkaで使うsqlite-develとWEBrick用にopenssl-devel、gemで使うのでreadlineとzlibのヘッダファイルも。

* ここからroot権限で。

# yum install readline-devel zlib-devel sqlite-devel openssl-devel
# mkdir -p /usr/local/src/ruby
# cd /usr/local/src/ruby
# wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p302.tar.bz2
# tar jxfv ruby-1.8.7-p302.tar.bz2
# cd ruby-1.8.7-p302
# ./configure --prefix=/usr
# make && make test
# make install

rubygemsを用意。

# mkdir -p /usr/local/src/rubygems
# cd /usr/local/src/rubygems
# wget http://rubyforge.org/frs/download.php/70696/rubygems-1.3.7.tgz
# tar zxfv rubygems-1.3.7.tgz 
# cd rubygems-1.3.7
# ruby ./setup.rb 
# gem list
# gem install bundler

いよいよLokka。

*ここからは一般ユーザで。

$ mkdir lokka
$ cd lokka
$ wget --no-check-certificate https://github.com/downloads/komagata/lokka/lokka-v0.1.0.zip
$ unzip lokka-v0.1.0.zip 
$ cd komagata-lokka-50a9c78/
$ bundle install --path bundle --without production test
$ bundle exec rake db:set
$ bundle exec rackup

これで起動する。

gpgとわたし

われわれのようなズボラな人間にとってのgpgの主な使い道は、リモート接続した先でrootユーザになるためにパスワードを調べるのが面倒くさくて、パスワードを書いたファイルをgpgで暗号化してログイン先のサーバのホームディレクトリに置くことだと思うのですが、いかがでしょうか。

*今はもうお客様のサーバではやっていません。本当です。

MeeGoでyum update失敗

何か知らないがChromeの更新に失敗していた。パッケージャのミスでrpmの取得先が間違っていたらしい。yum clean allしてからやり直した。

RhodesとiPhone SDK4

Rhodesが出力するbuild.xmlの

iphone:
configuration: Debug
sdk: iphonesimulator3.0

ここを

iphone:
configuration: Debug
sdk: iphonesimulator4.0

にするだけで動作した。