そーだいなるらくがき帳

そーだいが自由気侭に更新します。

Linuxの監視 ~ mackerel-plugin-linuxを読み解く

ついに始まりました。Mackerel プラグインアドベントカレンダー(全部CRE) の1日目です。

qiita.com

soudai.hatenablog.com

それでは早速1日目は mackerel-plugin-linux です。

mackerel-plugin-linuxLinux専用のプラグインであり、Linux使いの方は必須とも言えるプラグインのご紹介です。

github.com

インストールと設定手順

名前の通り、Linux専用のプラグインですので他のOSについては今回は考慮に入れません。 mackerel-plugin-linuxプラグイン集として提供しているパッケージの mackerel-agent-plugins に含まれています。 そのため公式の手順で簡単にインストール出来ます。

mackerel.io

インストール先は /usr/bin/mackerel-plugin-linux です。 Mackerelのプラグインはコマンドですので実行する事ができます。

※/usr/bin はPATHが通っているので省略出来ます

# mackerel-plugin-linux
linux.disk.rwtime.tsreading_xvda        0.000000        1511755502
linux.disk.rwtime.tswriting_xvda        60.000000       1511755502
linux.interrupts.interrupts     8655.000000     1511755502
linux.context_switches.context_switches 31125.000000    1511755502
linux.forks.forks       1440.000000     1511755502
linux.users.users       1.000000        1511755502
linux.swap.pswpin       0.000000        1511755502
linux.swap.pswpout      0.000000        1511755502
linux.ss.ESTAB  9.000000        1511755502
linux.ss.TIME-WAIT      5.000000        1511755502
linux.ss.UNCONN 41.000000       1511755502
linux.ss.LISTEN 15.000000       1511755502
linux.disk.elapsed.iotime_xvda  60.000000       1511755502
linux.disk.elapsed.iotime_weighted_xvda 60.000000       1511755502

設定ファイルであるmackerel-agent.confは標準では /etc/mackerel-agent/mackerel-agent.conf にインストールされます。 こちらに下記のとおり追記しましょう。

[plugin.metrics.linux]
command = "mackerel-plugin-linux"

以上を行った上でmackerel-agentを再起動してください。

見れるメトリック

README.mdにも書いてありますがもう少し具体的に見ていきましょう。

各グラフ定義ごとに説明します。 また表に出てくるdiffとはプラグイン上で差分値計算をするかどうかです。 となっている項目はプラグインで前回の実行時の値と差分値計算して出力しています。

Disk Read/Write Time

メトリック名(ラベル) プラグインの出力名 diff 説明
(ファイルシステム名) Read linux.disk.rwtime.tsreading_xvda 1分平均のディスクの読み込み時間
(ファイルシステム名) Write linux.disk.rwtime.tswriting_xvda 1分平均のディスクの書き込み時間

前述のコマンドでは下記の部分です。

linux.disk.rwtime.tsreading_xvda        0.000000        1511755502
linux.disk.rwtime.tswriting_xvda        60.000000       1511755502

実際には /proc/diskstats の値を利用しています。 プラグインが出力する値は1分あたりの差分値ですが/proc/diskstatsには要求されてから書き込み/読み込みが完了するまで時間が入っています。

diskstatsの出力についてはこちらをどうぞ。

Linuxカーネルのドキュメント - procfs-diskstats

プラグインではdiskstatsのfields 7とfields 10をそれぞれ使っています。 詳しくはこちらをどうぞ

iostatの説明(英語)

この値でDisc I/Oの状態を確認することが出来ます。

Disk Elapsed IO Time

メトリック名(ラベル) プラグインの出力名 diff 説明
(ファイルシステム名) IO Time linux.disk.elapsed.iotime_xvda 1分平均のディスク I/Oの予定時間の経過時間
(ファイルシステム名) IO Time Weighted linux.disk.elapsed.iotime_weighted_xvda 1分平均のディスク I/Oの実行された時間の経過時間

前述のコマンドでは下記の部分です。

linux.disk.elapsed.iotime_xvda  60.000000       1511755502
linux.disk.elapsed.iotime_weighted_xvda 60.000000       1511755502

こちらも同様に /proc/diskstats の値を利用しています。 リンクは省略しますがfields 13とfields 14をそれぞれ使っています。 この値はiotime_weightedがiotimeよりも大きい場合はディスクI/Oに対してディスクの性能が不足しています。 常に大きく差が出るような場合などはディスクI/Oをチューニングしたり、IOPSのより高いディスクの交換することを検討したりします。

Linux Context Switches

メトリック名(ラベル) プラグインの出力名 diff 説明
Context Switches linux.context_switches.context_switches 1分平均のコンテキストスイッチ回数

前述のコマンドでは下記の部分です。

linux.context_switches.context_switches 31125.000000    1511755502

実際には /proc/stat のctxtの値を利用しています。 /proc/statについてこちらをご参考ください。

Man page of PROC

コンテキストスイッチの詳細については割愛しますが、CPUから見るとタスクを切り替えずに行えた方がスムーズに処理ができてると言えるため少ないほうが良いといえます。 しかしコンテキストスイッチを0にすることは難しく、また色んな要因で変化するため日常的に監視すると言うよりは他の要因をきっかけに値を確認し、その時の変化で原因を探る要素の一つして活用することが多いでしょう。 例えばコンテキストスイッチ数が多く、ディスクI/Oの値が多いときはプロセスに割り当てられた実行時間を使いきり、ほかのプロセスに実行を渡すための割り込みが入っていると想定することが出来ます。 つまりI/O待ちのためにプロセスに割り当てられた実行時間を有効に使いきれないと仮定することができます。 このように他の値と併せて比較することで色んな要素が見えてくる値です。

Linux Forks

メトリック名(ラベル) プラグインの出力名 diff 説明
Forks linux.forks.forks 1分平均のfork回数

前述のコマンドでは下記の部分です。

linux.forks.forks       1440.000000     1511755502

実際には /proc/stat のprocessesの値を利用しています。 こちらもforkの詳細については割愛しますが、例えばPostgreSQLのようなプロセスタイプのミドルウェアは必然的に多くなります。 その他の場合でもシステムコールでfork()を呼ばれれば当然増えていきます。 こちらもコンテキストスイッチ同様に常時監視するのでは無く、他の値と併せて比較し、原因を探る時に役立つ値です。

Linux Interrupts

メトリック名(ラベル) プラグインの出力名 diff 説明
Interrupts linux.interrupts.interrupts 1分平均の割り込み処理回数

前述のコマンドでは下記の部分です。

linux.interrupts.interrupts     8655.000000     1511755502

実際には /proc/stat のintrの値を利用しています。 プロセスの割り込みの詳細については割愛しますが、私はコンテキストスイッチと併せてintrを見ます。 intrが増えているとコンテキストスイッチも併せて増えていくことが大半だからです。 Linuxの仕組みと併せてstatの値を知ると相関関係が見えてきます。

Linux Network Connection States

メトリック名(ラベル) プラグインの出力名 diff 説明
Established linux.ss.ESTAB TCPの状態がEstablishedの数
Syn Sent linux.ss.SYN-SENT TCPの状態がSyn Sentの数
Syn Received linux.ss.SYN-RECV TCPの状態がSyn Receivedの数
Fin Wait 1 linux.ss.FIN-WAIT-1 TCPの状態がFin Wait 1の数
Fin Wait 2 linux.ss.FIN-WAIT-2 TCPの状態がFin Wait 2の数
Time Wait linux.ss.TIME-WAIT TCPの状態がTime Waitの数
Close linux.ss.UNCONN TCPの状態がCloseの数
Close Wait linux.ss.CLOSE-WAIT TCPの状態がClose Waitの数
Last Ack linux.ss.LAST-ACK TCPの状態がLast Ackの数
Listen linux.ss.LISTEN TCPの状態がListenの数
Closing linux.ss.CLOSING TCPの状態がClosingの数
Unknown linux.ss.UNKNOWN TCPの状態がUnknownの数

前述のコマンドでは下記の部分です。

linux.ss.ESTAB  9.000000        1511755502
linux.ss.TIME-WAIT      5.000000        1511755502
linux.ss.UNCONN 41.000000       1511755502
linux.ss.LISTEN 15.000000       1511755502

実際には ss -na コマンドの出力結果を利用しています。 ssコマンドはsocket statisticsのことでLinuxのネットワーク/ソケット情報を詳細に教えてくれます。 ちなみに引数ですが次のとおりです。

-n, --numeric       don't resolve service names
-a, --all           display all sockets

ですのでDNSサーバなどに問い合わせての名前解決せずに全てのソケットの情報を表示しています。

[root@demo]# ss -na
Netid  State      Recv-Q Send-Q   Local Address:Port                  Peer Address:Port
nl     UNCONN     0      0                    0:2493                              *
nl     UNCONN     0      0                    0:0                                 *

上記を見て分かる通り、現在の接続の現在のステータスの数を数えています。 TCPのステータスについてはこちらが参考になります。

qiita.com

ここではTCPの詳細については割愛しますが、上記TCP状態遷移図を見ていただくと分かる通り、CLOSINGやESTABLISHEDやLISTENは基本的に多くなります。 この値を見ることでネットワークが状態が可視化されるわけですが例えばTIME_WAITが多い場合はCLOSEDまでまでの待ち時間が多いということが読み取れます。 この現象は短時間に短い通信が集中すると、TIME_WAIT状態のコネクションが増えるために起こります。 このようにTCPの状態をシステムメトリックスのinterfaceの値と比較することでより詳しくネットワークの状態を知ることができます。

Linux Swap Usage

メトリック名(ラベル) プラグインの出力名 diff 説明
Swap In linux.swap.pswpin 1分平均のスワップインしているKB数
Swap Out linux.swap.pswpout 1分間のスワップアウトしているKB数

前述のコマンドでは下記の部分です。

linux.swap.pswpin       0.000000        1511755502
linux.swap.pswpout      0.000000        1511755502

実際には /proc/vmstat のpswpinとpswpoutの値を利用しています。 ちなみにSwapの詳細については割愛しますが、イン・アウトは次のとおりです。

Swapが発生するとメモリで処理できずにハードディスク等にアクセスするので処理が急激に遅延します。 例えばRDBMSなどではSwapが最初は発生していなかったのにデータ量が大きくなるとメモリに乗り切らず、ある日突然Swapが発生するようになります。 この時、この値を見るとSwapの状況がわかるというわけです。 例えばとても大きなファイルを扱っているときなどスワップアウトが発生しやすく、スワップアウトばかり増えていくと状況はどんどん悪化する事が予想されます。 このような場合はアプリケーションをチューニングしたり、メモリを増やす対応が必要になります。

Linux Users

メトリック名(ラベル) プラグインの出力名 diff 説明
Users linux.users.users ログインしているuser数

前述のコマンドでは下記の部分です。

linux.users.users       1.000000        1511755502

実際には who コマンドの出力を利用しています。 whoコマンドは今ログインしているアカウントを表示します。 つまり不正なログインが発生していたり、夜間に誰かが作業していることをグラフから読み解くことができます。 よくあるユースケースとしては夜間急にアラートがあがった、usersを見ると1になっている。 あぁこれは誰かが作業してるなと判断できてSlack等で @here する、このようなユースケースがあります。

Tips

mackerel-plugin-linuxは多くのグラフを作ります。 そのためむしろ減らしたいときもあるでしょう。 そんな人のために --type を使うと好きなグラフのみを表示することができます。 こちらも併せてご活用ください。

# mackerel-plugin-linux --help
NAME:
   mackerel-plugin-linux - Get metrics from Linux.

USAGE:
   mackerel-plugin-linux [global options] command [command options] [arguments...]

VERSION:
   0.1.0

AUTHOR:
   Yuichiro Saito <saito@heartbeats.jp>

COMMANDS:
     help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --tempfile value, -t value  Set temporary file path. [$ENVVAR_TEMPFILE]
   --type value, -p value      Select metrics type(s) to fetch: all, swap, netstat, diskstats, proc_stat, users [$ENVVAR_TYPE]
   --help, -h                  show help

またメトリックのフィルタリングについてはmackerel-agentの機能の include_pattern exclude_pattern でも行うことができます。 こちらは別のプラグインでも活用できますので是非ご検討ください。

Filter plugin metrics value by include_pattern and exclude_pattern option by astj · Pull Request #416 · mackerelio/mackerel-agent · GitHub

さて1日目はLinux向けのプラグインについての説明でした。 初日から頑張りすぎたので明日からクオリティが下がるかもしれません… 明日はWebサーバの2大巨頭の一つ、Apache2です(つまり明後日は…) 引き続き、Mackerel プラグインアドベントカレンダーをお楽しみに!

2日目 mackerel-plugin-apache2