えいのうにっき

a-knowの日記です

Mackerel でみる Linux システムメトリック項目の見方・考え方

Mackerel について考えない日はないというくらいに Mackerel・Love な僕なわけですが(考えない日はあります)、Mackerel の Web 画面で日頃なにげなく見ている「システムメトリック」、みなさんはどのような意識を持って観察していますでしょうか。

f:id:a-know:20170131075603p:plain

https://home.a-know.me をホストしているサーバのシステムメトリックのようす。

ここでひとつおさらいをしておくと、「システムメトリック」とは、監視対象のサーバにインストールされた mackerel-agent が、それ単体で収集・投稿するメトリックのことです。一般的な Linux系OS に mackerel-agent をインストールした場合、以下のような項目がシステムメトリックとして Mackerel に投稿されます。

  • loadavg5
  • cpu
  • memory
  • disk
  • interface
  • filesystem

今日は、Mackerel が「システムメトリック」として定めているこれらの値の見方や考え方について、書いてみたいと思います。

loadavg5

言わずと知れた、「ロードアベレージ」です。 ロードアベレージの値は、直接的には uptimew コマンドで確認することができるものです。

$ uptime
 00:11:25 up 20:16,  1 user,  load average: 0.00, 0.01, 0.05
$ w
 00:11:27 up 20:16,  1 user,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
centos   pts/0    39.247.149.210.r 00:11    5.00s  0.00s  0.00s w

load average: 0.00, 0.01, 0.05 のところがロードアベレージで、3つ並んでいる値は左から順番に「1分間の平均値」「5分間の平均値」「15分間の平均値」となります。この3つの値のうち、「5分間の平均値」が Mackerel に投稿されています。

ロードアベレージとは、ざっくり書くと「実行待ちの(実行キュー内にある)プロセスの数とディスクのI/O待ちのプロセスの数の合計値」となります。CPUやディスクさえ空いていれば、すぐにでも実行できるプロセスの数、ということですね。 このロードアベレージの値は、システム全体の負荷の状況を表すものとして従来より用いられてきました。

システム全体の負荷の状況を表しているのであれば、この値を見ることは重要そうです。実際大事だと言えるとも思うのですが、そのシステムやサービスの特性によっては、瞬間的に処理が集中しロードアベレージの値が増加することもあると思います。そういう場合、大事なことは「瞬間的に処理が集中しても、だんだんと平常時の負荷にまで落ち着くことができるかどうか」ということです。なので、「ロードアベレージがある値以上になったらヤバイ」という単純な見方をすることにはそれほど意味がありません。

見るべきはその傾向で、もしロードアベレージの値が描くグラフが徐々にでも右肩上がりになっていれば、それは「実際に捌いている処理量( x )」と「捌くべき処理の総量( y )」が x < y の関係になってしまっているということの現れです。この状態になっていると、放っておくとどんどんと処理待ちプロセスが溜まり、処理されるのが遅れてくる一方なので、根本的な対策を講じる必要があるといえます。具体的には、CPUかディスクの性能にボトルネックがあると思われるので、それらの値を確認することになります。

ただこのロードアベレージの値、マルチコアCPUが当たり前の今の時代においてその負荷の度合いを見るための指標としては必ずしも相応しいものとはいえないのでは、という議論もあるようです(実際に、将来的には Linux でも廃止される可能性があるそう?です)。

cpu

演算処理装置である CPU の使用率を表しています。なので、そもそもこの値を注視すべきサーバの種類とそうでもないサーバがあると思います。「サーバの種類」と書きましたが、Mackerel で言うところのロール( Role )ですね。CPU メトリックの場合は、通信の介在という役割が主であるプロキシサーバなどよりも、アプリケーションが稼働しているアプリケーションサーバなどについてこそ注意して見るべき、というかんじです。

Mackerel ではその種類ごとに細分化された使用率を確認することができますが、だいたいのケースでは以下の4種類をおさえておけばよさそうです。

  • cpu.user
  • cpu.iowait
    • I/O待ちによりアイドル状態であった時間の割合
  • cpu.system
  • cpu.idle
    • I/O待ちがなく、かつCPUがアイドル状態であった時間の割合

cpu.user が高騰していないかどうか、つまり CPU の高負荷状態については監視する必要があるでしょう。ただその閾値は「稼働しているアプリケーションによる」としか言えないので、その数値を一概に決めることはできません。なので、「平常時はどれくらいのCPU使用率を推移するものなのか」という点については日頃から意識しておく必要があります。

そして、特にアプリケーションサーバの場合は、CPU負荷がスカスカ(過剰な低負荷)でもそれはそれで問題です。平常時・ピーク時それぞれにおいて想定される負荷の総量に対して適切なサーバーリソースを準備し、その予測を下回るような負荷が計測された場合にはそれに気がつけるようにしておく、ということも大事です。

あとは、loadavg5 の上昇傾向を把握したときに、そのボトルネックを探る目的で cpu のグラフを確認するという使い方もあると思います。 ロードアベレージが高騰していて、なおかつ、

  • cpu.iowait.percentage が高騰している場合
    • ディスクのI/O性能がネック
  • cpu.user.percentage が高騰している場合
    • カーネル以外(そのサーバで稼働させているアプリケーションなど)のプロセスが原因であり、その処理内容を改善するか、CPUのスペックを挙げることで改善される可能性がある
  • cpu.iowait.percentagecpu.user.percentage も高騰していない場合
    • そのCPUで一度に処理が行える数に対して要求の数が大きすぎることがロードアベレージ高騰の原因なので、コア数を増やす・同じ役割のサーバ台数を増やし負荷分散することで改善される可能性がある

...といったことを、CPU のグラフから読み取ることができるかと思います。

memory

メモリの使用状況です。その使用率・空き容量を観察するわけですが、基本的に最近のOSでは、空きメモリの大部分をページキャッシュとして使うようになっている・そしてそれは必要に応じて開放される部分も含まれているので、その点については注意が必要です。

Mackerel で見るときのことを想定して例にとると、現在の Mackerel では used + cached + buffers + free = total という前提に基いており、またページキャッシュ(cache)には必要に応じて開放される部分も含まれているので、「メモリの使用率」というものを考えるときには (used + cached + buffers) / total ではなく used / total で考える必要があります( buffers はいわゆるバッファ(良い日本語が出てこない。。)なので、これも純粋な使用領域とはみなしません)。

現在の Mackerel では、という書き方をしましたが、基本的(概念的)なメモリ構成の捉え方としても、 used + cached + buffers + free = total という考え方で問題ありません。ただ最近の Linux でのメモリ構成はもう少し複雑化している、という点については考慮しておく必要があります。

kernel バージョン 3.14 以降では、 /proc/meminfo で見れる値のなかに MemAvailable というものがあります(参考:https://www.kernel.org/doc/Documentation/filesystems/proc.txt)。これは読んで字のごとく、「利用可能な空きメモリの量」を出してくれているというスグレモノです。 そして上述の cached の値には、実はその内訳をさらに細分化すると「必要に応じて開放できないページキャッシュ」も含まれているのですが、その一方で MemAvailable はそのあたりの考慮もされている値なので、MemAvailable が取れるような環境ではこの値を使って計算する方がより正確な使用率・利用可能なメモリ量の値を取ることができます。このことは、様々なバージョンの Linux カーネルを持つホストが登録される Mackerel のメモリリソースの管理・可視化においての、今後の課題でもあります。

ところで、サービスの種類や稼働アプリケーションの種別にもよるかと思いますが、特に Web アプリケーションにおいてはもはやスワップさせてしまったら負け・おしまい」という考え方が主流です(スワップ領域は、多くの場合はディスクデバイス上に作成されるため、スワップの発生は極端なパフォーマンスの低下につながる(一昔前はディスクデバイス=HDD、だったので特に))。

なので、そもそもスワップ領域を確保していない場合もあるかと思いますが、指定している場合は memory.swap_used の値を注視してもよいのかもしれません。

disk

ディスクの読み書きに関する、IOPS(1秒あたりのI/Oアクセス)の値です。

ディスクのIOPS性能は、製品仕様として明示的に示されていることが殆どです。つまり明確な性能の限界があるなかで、「現状の負荷の占める割合」と「今後発生し得る瞬間的な値の高騰に耐えられるか」という観点が大事です。

上述のとおり、ディスク性能の不足はサーバ全体のボトルネックにもなり得ますので、「将来的なサービスの成長に耐えられるかどうか」といったキャパシティプランニング的な見方も必要でしょう。いずれにしても、この disk においても、平常時の値や1日 / 1週間 / 1ヶ月といった期間におけるトレンドを把握しておくことが重要です。

ここでもサーバのロールについて言及しておくと、ディスクへの書き込みが主なサーバとなるとデータベース・サーバやストレージサーバといったところが挙げられます。disk は、そういったサーバでこそ特に注視するべきメトリック項目であるといえるでしょう。

interface

ネットワーク帯域の使用状況です。単位は KB/秒tx は送信、 rx は受信です。

オンプレ環境などでは、そのネットワーク帯域量に明確な上限があるはずなので、その帯域を専有してしまっていないか?(上限帯域量の限界値近くを長時間推移していないか?)という観点でその値やグラフに向き合うのがよさそうです。

クラウド環境では上記の観点に加えて、通信そのものに料金が掛かる場合が殆どだと思います。なので、その観点での監視を設定しておくのも良いかもしれませんね。前月分のグラフと料金実績の相関を把握しておく、といったことも良いプラクティスだと思います。

このメトリックを特に注視すべきサーバのロールとしては、プロキシサーバ・Webサーバ・コンテンツ配信サーバ...といったところでしょうか。これらのロールを担うサーバは、どうしてもネットワーク転送量が増大しがちです。またロードバランサーなど、パブリックネットワークに面するサーバの interface を監視しておくことで DOS 攻撃を検知する方法のひとつとしても使えますし、コンテンツ配信サーバの前に AWS CloudFront のようなキャッシュの仕組みを置いている場合は、コンテンツ配信サーバの interface の値の増大によりキャッシュの効きが悪くなっているかも、みたいなことにも気がつけそうですね。べんり。

interface については同僚にも聞いてみたところ、データベースサーバについても見るようにしているそうで、とても興味深かったです。SELECT * FROM hoge ... みたいなダメな SQL を発行していないかどうかを見る指標にも出来るとのこと。おもしろい。

filesystem

これは簡単ですね。ディスクサイズとその使用量を表すメトリックです。

パーティションの分割の仕方にもよりますが、空き容量が枯渇するとログなどの書き出しが行えなくなったりして、結果的にそこで動作していたアプリケーションが停止してしまったりするなど、良いことはなにひとつありません。

なので、定期的にその値を確認し、対策が必要だと思われる場合はその対策作業に掛かる所要時間を逆算した上で前もって作業を行なう必要がある...、、わけですが、この点 Mackerel では、通常の閾値設定によるアラート発報に加え、式監視機能にて timeLeftForecast 関数を用いることで、「線形回帰したメトリックが閾値に到達するx秒前になったらアラート発報」(将来予測)といったことを行なうことができます。

これを活用することにより、ディスクの拡張や不要ファイルの削除などを、ディスク使用量が危険水域に到達する一週間前などに、十分な余裕を持って行なうことができるので、ディスクの枯渇で今までに痛い目にあったことのある人にはぜひ設定をオススメしたいところです。

以上!

以上、Mackerel のシステムメトリック 6項目についての見方・考え方を、ごくごく簡単にまとめてみました。

今回の記事では、各項目ごとに多くても数十行の説明で留めてしまっていますが、原理原則を理解した上でより厳密に書こうとするならば、それぞれいくらでも書けてしまうほどに奥が深い世界であると思っています。

今回ここで書いたものはあくまでもとっかかりとして理解していただいて、必要に応じてさらなる深掘りをしてもらえればと思います。

また、今回の説明を書きながら自分でも改めて実感したことは、あるサービスを安定的に・継続して提供していくということを考えたとき、その値を継続的に記録し、平常時の状態と傾向を把握することこそが大事なことなのだな、ということです。そして、これはもう宣伝として捉えてもらっても構わないのですが、そういったことを適切な作業量で行ってもらうためのサービスが Mackerel なんだと思っています。

そして、なんでもかんでも闇雲に監視しまくればいいというものではないんだな、ということもあります。これについては、同僚がサーバをスポーツ選手に例えていたのが納得感がありました。

スポーツ選手と一口に言っても、「プロ野球のピッチャー」「サッカー選手」「バドミントン選手」、いろいろな競技の選手がいますよね。野球のピッチャーやバドミントン選手において、腕のしなやかさや強靭さというものはある程度共通して必要な水準というものはあるのかもしれませんが、同じスポーツ選手だからといって同じ項目をサッカー選手についても見ていく必要は(たぶん)無いはずです。

サーバもそれと同じで、本文の説明でも既に言及している通り、サーバの役割(ロール)に合わせて、特に注視すべき項目というものがあります。むしろそれ以外の項目についても注視してしまうことは、時にはノイズとして日々の運用作業を妨げる要因にもなりかねません。もちろん、一概に言えるものではありませんが。

今回のような観点を入り口として、「各サーバの状態を見るときに、本当に必要な観点はなにか」を意識してもらえると嬉しいなと思います。



follow us in feedly