まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

Amazon EC2 インスタンスの負荷測定をどうやって行うべきか、という問題です。結論を先にいうと「EC2 インスタンスの場合は top コマンドではなく、CloudWatch を使うべき」ということになります。

きっかけは自分が先日ツイートしたこの現象に気付いたことでした:


EC2 で運用しているサーバーの CPU 負荷を測定すると、CloudWatch で測定した場合は80%超え(上図左)になってアラート出まくりなのに、直接ログインして top コマンドで測定するとせいぜい10%前後(上図右)になる、というものです。

なぜ測定方法によって負荷値が異なるのか? CPU 負荷の定義が違うのか? だとしたらどちらを信用すべきなのか、どちらかはそもそも信用してはいけないのか、・・・・

よくわからんなあ・・・ と思っていたのですが、ある日こんな情報を見つけました:
EC2 monitoring: the case of stolen CPU


簡単に言うと、「例えば CPU が 0.1 個割り当てられた仮想マシンでは、(topコマンドでの)CPU 負荷 = 10% の状態でその仮想マシンのCPU的には100%になっている」ということです。なので EC2 上の(Xen上の)仮想インスタンスを1台のマシンとみなして負荷を計測するのであれば CloudWatch を使うべき、ということになります。逆に言えばこの環境下での top コマンドの結果には注意が必要です。


上記ページには "If you’re an IBM cus­tomer with a pSeries frame these ques­tions aren’t entirely new to you"(IBM の pSeries の顧客であれば特別目新しいことではない) とも書かれてます。へぇ、AIX ってそうなんだ。知らなかったけどね・・・ :P


 

ワードプレス(WordPress)をよく使っています。個人でも業務でも。ブログというよりは、いわゆるCMS(コンテンツ管理システム)の機能を使ったサイトのプラットフォームとして利用することが多いです。まだまだですが、それなりに詳しくなってきたかなと自負しています。

CMS なのでファイルのアップロード機能などは普通に備えています。ただ「ワードプレスでファイルのアップロードができない」という質問は FAQ と化しています。ワードプレスでアップロードしたファイルはデータベースではなくファイルシステム内に格納(というか移動)されて保管されるのですが、この格納先ディレクトリはワードプレスの zip ファイルを展開しただけではできず、自分で wp-content/ フォルダの下に uploads/ という名前のサブディレクトリを作り、apache 等のウェブユーザーが書き込み可能な権限を設定する必要があります。大抵はこれで解決します。

そこまで設定しても「アップロードできない」ことはたまにあるようです。これもまだ FAQ といっていいレベルで、「WordPress アップロード エラー」あたりでググると、この問題に悩む人達がいかに多いかわかります。多くの場合はアップロードしようとすると「HTTP エラー。」というメッセージが表示されるようです。
wp_httperror00

原因はケース・バイ・ケースですが、プラグインの相性が悪いケースだとすると一度全てのプラグインを無効にしたら直ったとか、諦めて再導入したら直ったとか、色々試したけどそれでもまだ直らないとか、色んなケースがあるようです。特に注目したいのは最後のケースで、この問題は世に(ネットに)出回っている情報では解決出来ないケースが少なからずある、ということです。そういうのにぶち当たっちゃったら大変だよね・・・

なんて考えてたら、自分の所にも厄介なのがやってきました。何が厄介かって「以前は問題なくアップロードできていたのに、今アップロードすると100%失敗する」というもの。以前は動いていたんだから根本的な問題とは思えないが、今実際にアップロードすると常に「HTTP エラー。」になってしまいます。 念のためプラグインを全て無効にした上で試すなど、ウェブで見つけた情報を頼りに色々試してみましたが、解決には至りませんでした。


と、ここまでが今回のブログエントリの導入部です。ちょっとだけ WordPress に詳しくなった自分を試す意味も含めて、この「ググってもよくわからない」ケースを自力で解決すべく、WordPress の PHP デバッグを敢行してみました。以下はその結果として分かったことのまとめです。今回分かった原因と同じ原因で悩んでいる人がどれだけいるかわかりませんが、参考になれば。


まずは HTTPD のログをみます。アップロードが失敗するタイミングで /wp-admin/async-upload.php が HTTP コード 500 を返していることが分かりました。まずはこのファイルにデバッグライトを仕掛けて、、と。これを地道に繰り返して、どこでエラーが発生しているのかを特定していきます。
wp_httperror02

そして、エラー箇所をたどっていくと /wp-admin/includes/media.php 内の wp_read_image_metadata() 関数でエラーが発生していることを発見しました。
wp_httperror03

これ、WordPress のコア関数の1つなので、これがエラーと言われても・・・ と思いつつも、とりあえず Codex によると、この関数は /wp-admin/includes/image.php で定義されているようなのでこのファイルを開いて更にデバッグライトを埋め込んで・・・ 

ん?
wp_httperror01
 
なんと /wp-admin/includes/image.php のサイズが0バイト!そりゃここでコケるわな!


というわけで、今回の WordPress のファイルアップロードができない問題を自分の環境下で調査した結論としては、WordPress を構成するファイルの一部がたまたま壊れてしまっていたからでした。ファイルが壊れる原因は色々考えられるのですが、修正するには元のアーカイブなどから壊れる前の該当ファイルを取り出してコピーする、とかになると思います。それにしてもこれが原因だとすると、気付くのは結構たいへんだと思う・・・

そしてこういうことが起こっていると、ファイルアップロード時には(これも話をややこしくしてると思うけど)「HTTP エラー。」というエラーメッセージが表示される、ということも分かりました。このエラーメッセージはかなり汎用的に使われていて、必ずしも HTTP レベルでの問題とは思わないほうがいいかも。

なお、WordPress を導入したディレクトリから、
 # find . -size 0 -print
を実行すると、同じように何らかの原因でサイズがゼロになってしまったファイルの一覧を取り出すことができます。


WordPress のファイルアップロード時「HTTP エラー。」で悩んでいて、設定とかを見なおしたけどまだよく分からない、という場合は念のため調査してみるのもいいかもです。
 

「起動中の Amazon EC2 のインスタンスが消える!?」というオカルトな現象に2度ほど遭遇しました。

1度目はオペレーションミスか勘違いかと思ったんですが、2度あるとさすがに勘違いでは済まなくなります。

まあサーバーとしては実稼働中ではなかった(実はこれがクセモノだった、実稼働中ならもっと早く真相に気づけたかも)ので、深刻な状態にはならなかったのですが、この現象の正体を突き止めるべく調べてみました。


この怪現象はこんな感じ。Amazon EC2 にログインして、サーバーインスタンスを起動して使っていました(画面は管理コンソールです)。
2014010807


が、ある時に同じ管理コンソールを見てみると動いていたはずのインスタンスが消えています! まじかっ!?
2014010808


何がなんだかよく分からないけど、消えてしまったものはもう存在しないんだよね? それなら再度構成しないといけないのでインスタンスを作リ直して・・・ なんてやってました。

このインスタンスは本稼働前の準備段階のインスタンスだったので実際にユーザーがアクセスしたりしていたわけではないのです。その意味では「ああ本番前でよかった」と問題にはならなかったのですが、、 すごいオチが隠れてました。 みなさん、分かります?



以下、真相です。

まずサーバーインスタンスは消えたわけではなく、ちゃんとずっと動いていました。なので本来は作り直す必要もありませんでした。

ではなぜ管理コンソールから消えていたのか?

これは単に異なるリージョンを見ていた、ということでした。

上記図を再度見直してみます。最初のインスタンス稼働中の管理コンソール画面ではリージョンは US East(N.Virginia) に設定されていました。つまりこのサーバーはバージニア州のデータセンター内で動いていた、ということです。
2014010801

次にサーバーが消えたように見えた管理コンソール画面のリージョンは US West(Oregon) になっています。つまりこちらはオレゴン州のデータセンターを参照していて、そこでは(作ってないから当たり前ですが)何も動いていない、ということでした。
2014010804


そっかー。なんだ、リージョンが切り替わったのに気付かなかっただけか。 めでたし、めでたし。


・・・ところでいつリージョンが切り替わったんだ?俺は何もしてないぞ。 
管理コンソール見るたびにリージョンなんか意識してないし、こんなことが頻繁に起こってたら、いつか本当にやらかす可能性があるぞ。

で、このリージョン切り替わりの謎をずっと探っていたのですが、最近になってやっと分かりました。結論としては
 ・AWS のリージョン情報がブラウザのクッキーに残っていて、
 ・AWS アカウントを複数持っていて、適宜切り替えて使っていた
のが原因でした。

まず AWS のリージョン情報(らしきもの)はブラウザのクッキーに残っていました。console.aws.amazon.com のクッキーとして3つの(それぞれの用途はわかりませんが) "us-west-2" リージョンが記録されていることを確認しています。
2014010805


次に自分は業務用と個人用と、2つの AWS アカウントを持っています。同じPCの同じブラウザで、ログインユーザーを切り替えて使っています。

たとえば、まず業務用アカウントを使ってログインしているとします。この時は US-East リージョンにあるインスタンスを使っています。
2014010801


この状態でいったんログアウトします。リージョン情報はクッキーに残っているので、次回ログイン時のデフォルトリージョンは US-East になるはずです(なので同じ業務用アカウントでログインした時はこの続きの管理コンソール画面が表示されるはずです)。

ここで個人用アカウントに切り替えてログインします。リージョン情報がクッキーに残っていて、どうやらユーザーごとの制御はしていないようなので個人用アカウントでも US-East リージョンで管理コンソールが表示されます。
2014010802

この状態から新しくサーバーインスタンスをリージョン指定なしで作り、それが US-West リージョンで作成された場合(或いは US-East 以外のリージョンを指定して作成した場合)、当然ですがインスタンスは US-East リージョンではなく、US-West リージョン内に作成されます。そしてこのタイミングで管理コンソールのリージョンも US-West に切り替わります。実際にインスタンスを作成しなくても、このようなオペレーションが行われたと仮定して(手動で) US-West リージョンに切り替えておくと、この後の現象を再現できます。
2014010803

この状態で個人用アカウントはログアウトし、再度業務用アカウントでログインし直します。するとクッキーに残ったリージョンは US-West なので、業務用アカウントでは前回のログアウト直前まで US-East で作業していたにも関わらず、US-West の画面になります。リージョンが異なるので当然ですがそこには直前の画面にあった稼働中のサーバーインスタンスはありません(見えません)。 これが「消えていた」ように見えたわけです。
2014010804

これが世にも恐ろしい「Amazon EC2 のインスタンスが消えた!」現象の原因だったように推測しています。

AWS アカウントを複数持っている人は少ないのか、利用者はリージョンを固定して使っているのか、ググってもこの現象が発生している、という情報を見つけることができませんでした。

上のはあくまで推測にすぎないのですが、現にクッキーの状態も推測にあっていたので、あながち間違ってないのかな、と思ってます。





 

このページのトップヘ