23
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Prometheus] Node ExporterでCPUとメモリとディスクを監視する

Last updated at Posted at 2021-06-09

目次

概要

PrometheusでCPUとメモリを監視するためのPromQLの例。

関連記事

Prometheus、Node Exporterの環境構築手順はこちらを参照。
Prometheus環境を構築手順

PromQLを書くための基礎知識はこちらを参照。
PrometheusでPromQLを扱う前に知っておいたほうがよい知識

CPU使用率

| PromQL | 意味 |
| --- | --- | --- |
| node_cpu_seconds_total | 各コア,各モードのCPU使用時間の累計を記録したメトリック(秒) |

example.com:9100(node-exporterが入っている)の各mode(idleを除く)の直近1分間のCPU使用時間の平均を計算するPromQL。

rate(node_cpu_seconds_total{mode!="idle"}[1m])

Screen Shot 2021-06-08 at 18.59.14.png

以下の表は各modeとその意味をまとめたもの。上記の例では、結果からidleを取り除いている。
引用元:https://www.codetd.com/ja/article/12249521

mode desc
user ユーザープロセスがCPUを使用する時間
system カーネルプロセスがCPUを使用する時間
nice ユーザープロセススペースで優先度が変更されたプロセスによって使用されるCPU時間
idle アイドル(誰も使用しない)CPU時間
iowait ioを待機しているCPU時間
irq ハード割り込みのCPU時間(hardware interrupts)
softirq ソフト割り込みのCPU時間(software interrupts)
steal ハイパーバイザーによって使用されるCPU時間

topコマンドを実行すると以下のような行があるが、ここに表示されているus, sy, niなどが、これらのmodeに当たる。

%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

マルチコアCPUの場合

マルチコアノードの場合、以下で各modeの平均値を出す。
without(cpu)は、各CPUの平均を出すため、計算時にCPU番号を無視するための式。

avg without(cpu) (rate(node_cpu_seconds_total{instance="example.com:9100",  mode!="idle"}[1m]))

avgの他に、avg_over_timeもある。
avgrateの組み合わせで算出するのに対し、avg_over_timeは単純にその時間の範囲の平均値を算出する。
以下のように使う。

avg_over_time(node_cpu_seconds_total{mode!="idle"}[1m])

参考:サンプルで学ぶ!PromQLで自在にグラフを描こう (Prometheus + Grafana)

CPU使用率が80%を超えているものを出力する例

avg without(cpu) (rate(node_cpu_seconds_total{instance="example.com:9100",  mode!="idle"}[1m])) >= 0.8

Screen Shot 2021-06-08 at 19.02.56.png

ロードアベレージ

PromQL 意味
node_load1 1分間のロードアベレージ
node_load5 5分間のロードアベレージ
node_load15 15分間のロードアベレージ

Screen Shot 2021-06-08 at 21.12.54.png

normalizeする場合はCPUのコア数で割る。
FYI: Which is Better: CPU Load or Normalized CPU Load?

ロードアベレージが1を超えたものを出力(normalizeする)

# ロードアベレージ / CPUコア数
node_load1 / count(count(node_cpu_seconds_total{instance="example.com:9100"}) without (mode)) without (cpu) > 1

Screen Shot 2021-06-08 at 21.32.19.png

メモリ使用率

PromQL 意味
node_memory_MemTotal_bytes メモリ総容量
node_memory_MemAvailable_bytes メモリ空き容量
# メモリ総容量 - メモリ空き容量 = 現在の使用量
node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes

メモリ使用率が80%以上のものを出力

(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes >= 0.8

Screen Shot 2021-06-08 at 21.36.01.png

ディスク容量

PromQL 意味
node_filesystem_size_bytes ディスク総容量(bytes)
node_filesystem_avail_bytes 残りディスク容量(bytes)

ディスク使用率

1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes)

inode使用率

PromQL 意味
node_filesystem_files_free freeのinode数
node_filesystem_files 総inode数

inode使用率

1 - (node_filesystem_files_free / node_filesystem_files)

I/OリクエストによるCPU使用率

PromQL 意味
node_disk_io_time_seconds_total IOに費やされた時間の合計秒数

Prometheusのrate(node_disk_io_time_seconds_total[1m])は、iostatコマンドの%utilの値と同義。

%util = デバイスへのI/OリクエストによるCPU使用率
参考:iostat 見方

I/O負荷を与えてみる

I/O負荷を与え、iostatコマンドとPormQL rate(node_disk_io_time_seconds_total[1m])の結果を比べてみる。

負荷を与える

stress-ngコマンドを使い30GBの書き込みを行い負荷を与える。
参考:stress-ngコマンドでCPU、メモリ、ディスクに負荷をかける

$ stress-ng -d 3 --hdd-bytes 30G

iostatの結果

option desc
-d デバイス使用率のみを出力する
-t 計測した時刻を出力する
-x ディスク統計情報を出力する
10 10秒ごとの結果を出力する
$ iostat -dtx 10
Linux 3.10.0-1127.19.1.el7.x86_64 (example.com) 	06/09/2021 	_x86_64_	(8 CPU)

# stress-ngコマンド実行前
06/09/2021 03:35:04 PM
Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     0.14    0.19    1.52    16.90    44.59    72.03     0.00    4.61    0.56    5.11   0.11   0.02
scd0              0.00     0.00    0.00    0.00     0.00     0.00     9.96     0.00    0.72    0.72    0.00   0.72   0.00

# stress-ngコマンド実行後
06/09/2021 03:35:14 PM
Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     0.10    2.10 2051.00    91.60 1031840.25  1005.24    86.22   82.18    0.14   82.26   0.33  67.81
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

# stress-ngコマンド実行後、utilが100%近くなっている
06/09/2021 03:35:24 PM
Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     2.40    0.20 2980.60     3.20 1498235.60  1005.26   127.44   84.47    4.50   84.48   0.34  99.97
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

PromQLの結果

I/OリクエストによるCPU使用率

rate(node_disk_io_time_seconds_total[1m])

stress-ngコマンド実行前
Screen Shot 2021-06-09 at 15.34.03.png

stress-ngコマンド実行後
1.0、つまり100%になっている。
Screen Shot 2021-06-09 at 15.36.59.png

iostatコマンドの%utiでも、PromQLの結果、どちらも100%近くになっていることを確認できた。

I/Oレイテンシ

PromQL 意味
node_disk_read_time_seconds_total IOのreadに費やされた時間の合計秒数
node_disk_reads_completed_total 正常に完了したreadの合計数
node_disk_write_time_seconds_total IOのwriteに費やされた時間の合計秒数
node_disk_writes_completed_total 正常に完了したwriteの合計数

これらは/proc/diskstatsから値を取得している。

node_disk_read_time_seconds_total
Screen Shot 2021-06-09 at 23.43.39.png

node_disk_reads_completed_total
Screen Shot 2021-06-09 at 23.43.50.png

node_disk_write_time_seconds_total
Screen Shot 2021-06-09 at 23.44.00.png

node_disk_writes_completed_total
Screen Shot 2021-06-09 at 23.44.09.png

$ cat /proc/diskstats
 252       0 vda 4682174 4304 929662806 2502865 27994455 2461794 1996846903 172438082 0 3754119 98035986
 252       1 vda1 152 0 1216 61 0 0 0 0 0 61 61
 252       2 vda2 4681923 4304 929656982 2502765 27816578 2461786 1996846823 172315078 0 2975909 96782251
  11       0 sr0 53 0 528 38 0 0 0 0 0 38 38

PromQLの結果と/proc/diskstatsで値が同じことが確認できる。
小数点の位置が異なるものもあるが、millisecondsかsecondsかで計測しているかの違い(だと思われる)。

PromQL sr0(Prom) sr0(diskstats) vda(Prom) vda(diskstats)
node_disk_read_time_seconds_total
(/proc/diskstats:7列目)
0.038 38 2502.8650000000002 2502865
node_disk_reads_completed_total
(/proc/diskstats:4列目)
53 53 4682174 4682174
node_disk_write_time_seconds_total
(/proc/diskstats:11列目)
0 0 172438.082 172438082
node_disk_writes_completed_total
(/proc/diskstats:8列目)
0 0 27994455 27994455

Read

IOのreadに費やされた時間の合計秒数 / 正常に完了したreadの合計数 = Read1回あたりにかかった秒数

rate(node_disk_read_time_seconds_total[1m]) / rate(node_disk_reads_completed_total[1m])

Write

IOのwriteに費やされた時間の合計秒数 / 正常に完了したwriteの合計数 = Write1回あたりにかかった秒数

rate(node_disk_write_time_seconds_total[1m]) / rate(node_disk_writes_completed_total[1m])

平均I/Oリクエストサイズ

PromQL 意味
node_disk_io_time_weighted_seconds_total The weighted number of seconds spent doing I/Os

"The weighted number of seconds"は直訳すると「加重秒数」だが、意味がよく分からない。加重平均なら分かるが。何かに重み付けをした上での秒数なのか?何に?サイズ?I/O数?

加重平均とは - 【プログラマーのための統計学】平均値の算出方法は1つじゃない

これは/proc/diskstatsの最後の列の値を取得している。diskstatsの最後の列の値についての説明は以下。

the weighted number of milliseconds spent doing I/Os

With the exception of operations in progress, all of the fields are cumulative counters that increase over time. The last field, the weighted number of milliseconds spent doing I/O operations, is special because it includes operations currently in-flight; it is basically the sum of the time spent for every operation, plus those not yet completed:
引用元:https://www.xaprb.com/blog/2010/01/09/how-linux-iostat-computes-its-results/

PromQLと/proc/diskstatsの値を比較してみる。

Screen Shot 2021-06-10 at 0.32.02.png

$ cat /proc/diskstats
 252       0 vda 4682204 4304 929664814 2502877 27998500 2462121 1996915380 172444038 0 3754432 98041060
 252       1 vda1 152 0 1216 61 0 0 0 0 0 61 61
 252       2 vda2 4681953 4304 929658990 2502777 27820589 2462113 1996915300 172321011 0 2976171 96787196
  11       0 sr0 53 0 528 38 0 0 0 0 0 38 38

PromQLの結果と/proc/diskstatsで値が同じことが確認できる。
小数点の位置が違うのは、以下の違いがあるため。

  • /proc/diskstats => the weighted number of milliseconds spent doing I/Os
  • node_disk_io_time_weighted_seconds_total => the weighted number of seconds spent doing I/Os
PromQL sr0(Prom) sr0(diskstats) vda(Prom) vda(diskstats)
node_disk_io_time_weighted_seconds_total
(/proc/diskstats:最後の列目)
0.038 38 98041.06 98041060

加重秒数の意味が分かっていないが、I/Oリクエストの平均サイズの算出は以下、らしい。

rate(node_disk_io_time_weighted_seconds_total[1m])

負荷をかけてから実行するとこんな感じ。

$ stress-ng -d 3 --hdd-bytes 30G

Screen Shot 2021-06-10 at 1.08.24.png

alert.rules記述例

alert.rules
groups:
  - name: sample001
    rules:
      - alert: cpu_usage_exceeds_80%
        # CPU使用率が80%を超えているもの
        expr: avg without(cpu) (rate(node_cpu_seconds_total{mode!="idle"}[1m])) >= 0.8
        for: 5m
        labels:
          severity: critical
        annotations:
          firing_text: "[{{ $labels.env }}] {{ $labels.instance }} CPU usage exceeds 80%"
          resolved_text: "[{{ $labels.env }}] {{ $labels.instance }} CPU usage falls"
      - alert: cpu_load_avg_exceeds_1
        # ロードアベレージが1を超えたもの
        expr: node_load1 / count(count(node_cpu_seconds_total) without (mode)) without (cpu) > 1
        for: 5m
        labels:
          severity: critical
        annotations:
          firing_text: "[{{ $labels.env }}] {{ $labels.instance }} CPU load average exceeds 1"
          resolved_text: "[{{ $labels.env }}] {{ $labels.instance }} CPU load average falls"
      - alert: memory_usage_exceeds_80%
        # メモリ使用率が80%以上のもの
        expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes >= 0.8
        for: 5m
        labels:
          severity: critical
        annotations:
          firing_text: "[{{ $labels.env }}] {{ $labels.instance }} Memory usage exceeds 80%"
          resolved_text: "[{{ $labels.env }}] {{ $labels.instance }} Memory usage falls"
      - alert: disk_usage_exceeds_80%
        # ディスク使用率が80%以上のもの
        expr: 1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes) >= 0.8
        for: 5m
        labels:
          severity: critical
        annotations:
          firing_text: "[{{ $labels.env }}] {{ $labels.instance }} Disk usage exceeds 80%"
          resolved_text: "[{{ $labels.env }}] {{ $labels.instance }} Disk usage falls"
      - alert: disk_usage_exceeds_80%
        # inode使用率が80%以上のもの
        expr: 1 - (node_filesystem_files_free / node_filesystem_files) >= 0.8
        for: 5m
        labels:
          severity: critical
        annotations:
          firing_text: "[{{ $labels.env }}] {{ $labels.instance }} Inode usage exceeds 80%"
          resolved_text: "[{{ $labels.env }}] {{ $labels.instance }} Inode usage falls"
      - alert: io_usage_exceeds_80%
        # I/OリクエストによるCPU使用率が80%以上のもの
        expr: rate(node_disk_io_time_seconds_total[1m]) >= 0.8
        for: 5m
        labels:
          severity: critical
        annotations:
          firing_text: "[{{ $labels.env }}] {{ $labels.instance }} I/O usage exceeds 80%"
          resolved_text: "[{{ $labels.env }}] {{ $labels.instance }} I/O usage falls"

その他

ちなみに、Node ExporterではCPUエラーやメモリエラーは取れない。

参考

23
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?