読者です 読者をやめる 読者になる 読者になる

俺の報告

RoomClipを運営するエンジニアの日報(多分)です。

microインスタンスのCPU使用率はCloudWatchを信じろ - 日報 #113

解せぬ解せぬと思っていたことがようやく分りました。
嬉しい半面、異常に時間をロスしたことに地団ステップを踏まざるを得ません。

結論から先に書きます。
しかも箇条書きで。

  1. t1.microのtopコマンドやvmstatでのCPU使用率は信じるな
  2. t1.microのCloudWatchのCPU使用率を信じろ
  3. かと言ってt1.microのvmstatコマンドとかから実際のCPU使用率を計算することはかなり難しい。(実質無理?)
  4. 安定してCPU監視のもと動作させたいなら、smallインスタンスから使え

ということです。
サービスレベルでmicroを使う時は注意が必要というのは、 一見当たり前のようですが、
今回はその中でも重箱の隅をつつくような理由で説明させていただきます。
もちろん、下記の情報を知った上で上手にmicroを使えるのがハイパーいいことだとは思います。

さて、では簡単に説明を。

ことの起こりはAWSのt1.microインスタンスの不思議な挙動でした。 topコマンドやvmstatでみる値と、
cloudwatchで見る値が極端に違うのです。

さらっとググると沢山出てきます。
http://serverfault.com/questions/420122/why-does-top-report-a-different-cpu-usage-than-cloudwatch
ここでも嘆いている人がいます。

サクッと原因を説明すると、
http://axibase.com/news/ec2-monitoring-the-case-of-stolen-cpu/
ここにある通りで、要は、

「microインスタンスは依存している物理サーバのほんの一部しか使っておらず、topコマンド等で出てくるCPU利用率は、本体の物理サーバの方の値である。しかし、CloudWatchではそのほんの一部におけるCPU使用率を表示している。そのため、たとえtopコマンドで10%だったとしてもCloudWatch上100%となり、実質サーバは落ちる。」

ということだ。
これで納得することは一応出来る。
だが問題は、じゃぁどうやってCloudWatchが取得できているようなCPUの値を計算するかということになる。
それが出来ないと、結局インスタンス上で走るプログラムたちのヘルスチェックはあやふやになってしまうからだ。

ここからは簡単に思える。
とどのつまり、microインスタンスが「物理サーバ全体のどれほどの領域を専有しているのか?」を明らかにすればいいからだ。
ここでECUというありがい概念が出てくる。
ECUhttp://aws.amazon.com/jp/ec2/instance-types/ にもある通り、 「1つの 1.0-1.2 GHz 2007 Opteron または 2007 Xeon プロセッサの CPU能力に等しい能力」
のことである。
要はXeonの初期型で1.1GHzくらいのクロック数のCPU1コア分の処理能力ということだ。
そしてt1.mircoはそれが1ECUだと言っているのだ。
http://www.ec2instances.info/?region=ap-northeast-1
ここを参照すればしっかと書いてあることがわかる。
それからおもむろにt1.mircoインスタンスにログインし、
cpuの情報を書きコマンドで取得すると

cat /proc/cpuinfo

....

model name : Intel(R) Xeon(R) CPU E5-2650 0 @ 2.00GHz

....

ということがわかる。
で、このCPUのスペックはというと、
http://ark.intel.com/ja/products/64590/
ここを参照すれば分かる。
いわく、8コア、16スレッド(HT)、2GHzのCPUであるようだ。
意外とでかいサーバだとわかった。
単純にALUやアーキテクチャが一緒だったとして、
クロック数だけの問題で考えれば、
1コア2GHzをECU換算すれば2/1.1 = 1.8 程度だとわかる。
まぁブースト機能とかもあるので多めに見積もって1コアあたり2ECU程度の物理マシンだと考えることが出来そうだ。

さて、そうなるとt1.mircoは1ECU分を使い、1コアだといっているので、
100%CPUを使い切ったとしても、2ECU分の処理能力がある1コア全体からすると、
高々50%程度なわけだ。
なので、topコマンドで50%を叩きだしてしまったら、CloudWatch上は100%と表示されるはずなので、
ばっくり言ってvmstatで得られたCPU使用率の倍の値をしきい値として考えれば良いことになる。

とは、ならない。

なぜか?とか言う前に、実際にならない。
microインスタンスを鬼のように回せば分かるが、
大体50%なんてCPUがいく遥か昔にCloudWatch上で100%を叩き出すケースが多い。
僕の感覚ではtopコマンド上で20%言ったらもうアウトだ。
なぜそんなことになるのか?
その解決ドキュメントがこれだ。
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/concepts_micro_instances.html
もう知っている人からすれば、「今更何を…」と思うかもしれないが、
意外と盲点だと俺は思ったので紹介しておく。

重要なのはこの記述。
インスタンスは、2 つの基本レベルの CPU 使用率のみで機能するように設計されています。1 つは通常の低バックグラウンドレベルで、もう 1 つはバックグラウンドレベルよりはるかに高い短期スパイクレベルです。インスタンスは、最大 2 つの EC2 コンピューティングユニット(ECU)で動作することが許可されています
ということで、microはバーストに対してこそ強くECUを発揮するが、そうでなければ1ECUを遥かに下回る処理能力しか発揮しない。
即ち、完全にバースト処理向きのサーバであって、
常時処理するようなワーカープロセスが常駐していいようなインスタンスではないのだ。
smallインスタンスからこの不思議な設定は消え失せ、
しっかりと常時1ECUのリソース確保ができるようになる。
実際僕の手元のインスタンスで計測した結果、大体2倍程度のCPU使用率がCloudWatchに表示された。

ということで、冒頭に戻る。
t1.mircoインスタンスをガチで使う時はtopコマンドCPU使用率は当てにしない方がいい。
CPUを常時気にしながらプロセス管理をするようなプログラムを走らせたいなら、
最低限smallから始めるといい。
そうでなければハングアップする前に、CloudWatchベースでオートスケーリングなどを行い、カバーし無くてはならない。

ところで、
c3.xlargeのような4コア14ECUとか言っちゃうようなインスタンスの場合はどうだろうか?
これも物理マシンの一部を借りてるはずだからtopコマンドに意味は無いのか?
と思いちょいと覗いた感じだと、問題なくtop、vmstatの値とCloudWatchの値は一致していそうだ。
コアを複数使うようなサーバの場合は1コアの部分的リソースを使うなんてケチな事は言わずに、
物理マシンの16コアのウチ、4コアを全て使う、みたいな設定のようだ。
しかもインテルのスーパーバイザのおかげか、コアの数や論理CPUの数がいくつであろうと、
物理CPUの数を1としてくれているみたいなので(実際は違うのだろうけど)、
topコマンドを打っても1つのCPUの処理状況のみで管理できるような仕組みになっている(っぽい)

以上、走り書きですが、
またしてもしっかりとドキュメントを読まなかったことの後悔でございます。
では。