Linuxの負荷調査

はじめに

前回は負荷について書きました。 chimay.hatenablog.com

今回は、Linux OSにおける各リソースの利用状況の調査方法をまとめてみます。 インフラエンジニアの道具となるためのコマンドがほとんどなので、それぞれのコマンドの特徴を理解して使い分けができるようにしましょう。

※環境は、Amazon Linux を利用

負荷調査の流れ

大まかな流れ

  1. 現状把握
  2. 原因調査
  3. 復旧対処

現状把握

まずは、サーバで発生している状況を理解しない事には始まりません。 CPU、メモリ、トラフィック、ディスクの使用率を調査しましょう。

筆者は下記の順番で見る事が多いです。LoadAverageは全体把握のためですが、それ以外の理由は可能性が高いと考えている順番です。

1.LoadAverage
2.CPU使用率
3.メモリ使用率
4.ディスク使用率
5.トラフィック使用率

LoadAverage

まずは、LoadAverageです。 サーバの負荷状態を数値化したようなものだと思ってください。高ければ高いほど、サーバ負荷は高いです。 但し、CPU数に依存するので LoadAverage / CPU数 でサーバ毎に計算してください。

uptime

現在時刻、稼働時間、ログインユーザ数、load average がわかります。

$ uptime
 07:53:23 up  1:20,  1 user,  load average: 0.00, 0.01, 0.02
$
w

uptime でわかる情報にプラスで、実際にログインしているユーザとログイン元、ログイン時間などがわかります。調査時は、uptime よりも w で済ませる事の方が多いと思います。
スクリプトでデータを取得する際は uptime の方がデータ加工しやすいです。

$ w
 07:01:57 up 28 min,  1 user,  load average: 0.00, 0.01, 0.01
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
ec2-user pts/0    xxx.xxx.xxx.xxx 07:00    4.00s  0.00s  0.00s w
$

CPU使用率

CPU使用率が高い原因が、CPU不足なのか 処理待ちによる wait値の上昇なのかを見るようにしましょう。

top

出力される情報が多く、リアルタイムで情報が更新されるので 負荷調査時にはよく使われます。オプションが非常に多いので、詳細は割愛します。

$ top
top - 08:01:05 up  1:27,  1 user,  load average: 0.00, 0.01, 0.02
Tasks:  69 total,   1 running,  68 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.1%sy,  0.0%ni, 99.7%id,  0.1%wa,  0.0%hi,  0.0%si,  0.1%st
Mem:    503380k total,   253740k used,   249640k free,    67308k buffers
Swap:        0k total,        0k used,        0k free,    90516k cached
sar

このコマンドもオプションを使い分ける事でいろいろな情報を確認出来ます。詳細はそのうち別記事で書きます。リアルタイムで見たい場合は、 1 のオプションを付与しましょう。

※1 は実際には間隔(秒)の指定なので、5 を付与すれば 5秒間隔で出力出来ます。

$ sar
Linux 4.1.13-19.31.amzn1.x86_64 (igrashi)       05/03/2016      _x86_64_        (1 CPU)

06:33:15 AM       LINUX RESTART

06:40:01 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
06:50:01 AM     all      0.00      0.00      0.00      0.01      0.00     99.99
07:00:01 AM     all      0.01      0.00      0.01      0.01      0.00     99.97
07:10:01 AM     all      0.01      0.00      0.01      0.02      0.00     99.96
07:20:01 AM     all      0.00      0.00      0.01      0.01      0.00     99.99
$ sar 1
Linux 4.1.13-19.31.amzn1.x86_64 (labo)  05/03/2016      _x86_64_        (1 CPU)

09:00:30 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
09:00:31 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
09:00:32 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
09:00:33 AM     all      0.99      0.00      0.00      0.00      0.00     99.01
09:00:34 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
09:00:35 AM     all      0.00      0.00      0.99      0.00      0.00     99.01
09:00:36 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
09:00:37 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
09:00:38 AM     all      0.00      0.00      0.99      0.00      0.00     99.01
^C
$

メモリ使用率

スパップアウトが発生しているかどうかを確認するようにしましょう。

free

Amazon Linuxでは、-a オプションを付与する事をおすすめします。available という列が追加されて表示されます。これは、buffers/cacheの開放できるメモリを含めた空き容量になります。

$ free -a
             total       used       free     shared    buffers     cached  available
Mem:        503380     255532     247848         60      67484      91988     455580
-/+ buffers/cache:      96060     407320
Swap:            0          0          0
$
vmstat

とはいえ、リアルタイムでスパップアウトが発生しているかどうかはこちらのコマンドでの確認になります。si と so がそれぞれスパップインとスパップアウトになります。

※1行目は過去の統計データなので、無視してください。

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 247748  67528  91988    0    0    27     3   11   18  0  0 100  0  0
 0  0      0 247732  67528  91988    0    0     0     0   13   17  0  0 100  0  0
 0  0      0 247732  67528  91988    0    0     0     0    9   12  0  0 100  0  0
 0  0      0 247732  67528  91988    0    0     0     0   13   21  0  0 100  0  0
 0  0      0 247732  67528  91988    0    0     0     0   12   18  0  0 100  0  0
cat /proc/meminfo

実はいろいろ用意されているコマンドは /proc 配下に格納されている情報を読み込んで整形しているだけだったりします。なので、直接該当ファイルを開いてもOKです。

※当然ですが、意味がわかるかどうかは別にして、こちらの方が情報量は多いです。

$ cat /proc/meminfo
MemTotal:         503380 kB
MemFree:          247716 kB
MemAvailable:     455520 kB
Buffers:           67552 kB
Cached:            91988 kB
SwapCached:            0 kB
Active:           133556 kB
Inactive:          43148 kB
Active(anon):      17164 kB
Inactive(anon):       52 kB
Active(file):     116392 kB
Inactive(file):    43096 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:         17184 kB
Mapped:            15804 kB
Shmem:                60 kB
Slab:              67904 kB
SReclaimable:      58876 kB
SUnreclaim:         9028 kB
KernelStack:        1376 kB
PageTables:         2540 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      251688 kB
Committed_AS:      65324 kB
VmallocTotal:   34359738367 kB
VmallocUsed:        1560 kB
VmallocChunk:   34359732383 kB
AnonHugePages:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       22528 kB
DirectMap2M:      501760 kB
$

ディスク使用率

意外と100%になるディスク使用率。100%になると、新しいファイルの生成が出来なくなるのでシステムの挙動がおかしくなります。なので、確実に確認はしておきましょう。

df

使用量を確認する事が出来ます。ついでに、i-node も確認すると尚良。

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1      7.8G  3.7G  4.0G  49% /
devtmpfs        237M   56K  237M   1% /dev
tmpfs           246M     0  246M   0% /dev/shm
$ df -i
Filesystem     Inodes  IUsed  IFree IUse% Mounted on
/dev/xvda1     524288 165728 358560   32% /
devtmpfs        60669    430  60239    1% /dev
tmpfs           62922      1  62921    1% /dev/shm
$
iostat

リアルタイムでI/O状況の確認には、iostatを利用しましょう。先程紹介した、vmstat の bi と bo を見ることでもI/Oを確認する事が出来ます。

$ iostat
Linux 4.1.13-19.31.amzn1.x86_64 (labo)  05/03/2016      _x86_64_        (1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.08    0.00    0.05    0.09    0.08   99.70

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
xvda              3.06        53.48        13.99     388969     101776

$

トラフィック使用率

sar -n DEV

sar のオプションの1つで過去のトラフィック値を確認出来ます。こちらもオプションに 1 を付与する事でリアルタイムで確認する事が出来ます。

$ sar -n DEV
Linux 4.1.13-19.31.amzn1.x86_64 (igrashi)       05/03/2016      _x86_64_        (1 CPU)

06:33:15 AM       LINUX RESTART

06:40:01 AM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
06:50:01 AM      eth0      0.11      0.11      0.01      0.01      0.00      0.00      0.00
06:50:01 AM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:00:01 AM      eth0      0.12      0.12      0.01      0.01      0.00      0.00      0.00
07:00:01 AM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:10:01 AM      eth0      0.24      0.24      0.02      0.03      0.00      0.00      0.00
07:10:01 AM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:20:01 AM      eth0      0.10      0.10      0.01      0.01      0.00      0.00      0.00
07:20:01 AM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
ifstat

リアルタイムの確認には、ifstat などもあります。

$ ifstat
#kernel
Interface        RX Pkts/Rate    TX Pkts/Rate    RX Data/Rate    TX Data/Rate
                 RX Errs/Drop    TX Errs/Drop    RX Over/Rate    TX Coll/Rate
lo                     2 0             2 0           140 0           140 0
                       0 0             0 0             0 0             0 0
eth0                8495 0          6041 0         5656K 0         1769K 0
                       0 0             0 0             0 0             0 0
$
ifstatus

視覚的に判りやすいのコマンドでは、ifstatus などがあります。 テキストだと解りづらいので、キャプチャです。

f:id:nanashimei:20160503082548j:plain

原因調査

ある程度リソースの利用状況がわかったら、次はそれを引き起こしている原因(プロセス)の特定です。

ps

psコマンドでは各プロセス毎のリソースの利用状況がわかるので、前もって調べておいた情報を元に特定しましょう。

$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.4  19644  2496 ?        Ss   06:33   0:00 /sbin/init
root         2  0.0  0.0      0     0 ?        S    06:33   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    06:33   0:00 [ksoftirqd/0]
root         5  0.0  0.0      0     0 ?        S<   06:33   0:00 [kworker/0:0H]
root         6  0.0  0.0      0     0 ?        S    06:33   0:00 [kworker/u30:0]
root         7  0.0  0.0      0     0 ?        S    06:33   0:00 [rcu_sched]
root         8  0.0  0.0      0     0 ?        S    06:33   0:00 [rcu_bh]
root         9  0.0  0.0      0     0 ?        S    06:33   0:00 [migration/0]
root        10  0.0  0.0      0     0 ?        S<   06:33   0:00 [khelper]
root        11  0.0  0.0      0     0 ?        S    06:33   0:00 [kdevtmpfs]
root        12  0.0  0.0      0     0 ?        S<   06:33   0:00 [netns]
root        13  0.0  0.0      0     0 ?        S<   06:33   0:00 [perf]
root        14  0.0  0.0      0     0 ?        S    06:33   0:00 [kworker/u30:1]
root        16  0.0  0.0      0     0 ?        S    06:33   0:00 [xenwatch]
root        21  0.0  0.0      0     0 ?        S    06:33   0:00 [xenbus]
root        22  0.0  0.0      0     0 ?        S    06:33   0:00 [kworker/0:1]
root       124  0.0  0.0      0     0 ?        S    06:33   0:00 [khungtaskd]
root       125  0.0  0.0      0     0 ?        S<   06:33   0:00 [writeback]
root       127  0.0  0.0      0     0 ?        SN   06:33   0:00 [ksmd]
root       128  0.0  0.0      0     0 ?        S<   06:33   0:00 [crypto]
root       129  0.0  0.0      0     0 ?        S<   06:33   0:00 [kintegrityd]
root       130  0.0  0.0      0     0 ?        S<   06:33   0:00 [bioset]
root       132  0.0  0.0      0     0 ?        S<   06:33   0:00 [kblockd]
root       479  0.0  0.0      0     0 ?        S<   06:33   0:00 [md]
root       610  0.0  0.0      0     0 ?        S    06:33   0:00 [kswapd0]
root       681  0.0  0.0      0     0 ?        S    06:33   0:00 [fsnotify_mark]
root       696  0.0  0.0      0     0 ?        S<   06:33   0:00 [kthrotld]
root       740  0.0  0.0      0     0 ?        S<   06:33   0:00 [deferwq]
root      1366  0.0  0.0      0     0 ?        S<   06:33   0:00 [ata_sff]
root      1380  0.0  0.0      0     0 ?        S    06:33   0:00 [scsi_eh_0]
root      1381  0.0  0.0      0     0 ?        S<   06:33   0:00 [scsi_tmf_0]
root      1391  0.0  0.0      0     0 ?        S    06:33   0:00 [scsi_eh_1]
root      1392  0.0  0.0      0     0 ?        S<   06:33   0:00 [scsi_tmf_1]
root      1457  0.0  0.0      0     0 ?        S    06:33   0:00 [jbd2/xvda1-8]
root      1458  0.0  0.0      0     0 ?        S<   06:33   0:00 [ext4-rsv-conver]
root      1489  0.0  0.0      0     0 ?        S<   06:33   0:00 [kworker/0:1H]
root      1501  0.0  0.5  11464  2736 ?        Ss   06:33   0:00 /sbin/udevd -d
root      1591  0.0  0.0      0     0 ?        S<   06:33   0:00 [kpsmoused]
root      1632  0.0  0.4  11460  2172 ?        S    06:33   0:00 /sbin/udevd -d
root      1646  0.0  0.0      0     0 ?        S    06:33   0:00 [kworker/0:3]
root      2080  0.0  0.0      0     0 ?        S    06:33   0:00 [kauditd]
root      2088  0.0  0.4  15936  2384 ?        Ss   06:33   0:00 crond
root      2121  0.0  0.0      0     0 ?        S<   06:33   0:00 [ipv6_addrconf]
root      2252  0.0  0.4   9360  2240 ?        Ss   06:33   0:00 /sbin/dhclient -q -lf /var/lib/dhclient/dhclient-eth0.leases -pf /var/run/dhclient-eth0.pid eth0
root      2293  0.0  0.3  46536  1964 ?        S<sl 06:33   0:00 auditd
root      2311  0.0  0.5 243236  2584 ?        Sl   06:33   0:00 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5
root      2327  0.0  0.0   4380    88 ?        Ss   06:33   0:00 rngd --no-tpm=1 --quiet
rpc       2341  0.0  0.4  35292  2252 ?        Ss   06:33   0:00 rpcbind
rpcuser   2358  0.0  0.6  39860  3308 ?        Ss   06:33   0:00 rpc.statd
dbus      2389  0.0  0.0  21792   228 ?        Ss   06:33   0:00 dbus-daemon --system
root      2421  0.0  1.3 152080  6820 ?        S    06:33   0:00 /usr/sbin/snmpd -LS0-6d -Lf /dev/null -p /var/run/snmpd.pid
root      2484  0.0  0.5  77816  2572 ?        Ss   06:33   0:00 /usr/sbin/sshd
ntp       2509  0.0  0.8  29292  4368 ?        Ss   06:33   0:00 ntpd -u ntp:ntp -p /var/run/ntpd.pid -g
root      2584  0.0  1.2  92948  6424 ?        Ss   06:33   0:00 /usr/libexec/postfix/master
postfix   2591  0.0  1.3  93200  6552 ?        S    06:33   0:00 qmgr -l -t fifo -u
nobody    2593  0.0  0.7 159124  3720 ?        Ss   06:33   0:00 proftpd: (accepting connections)
root      2618  0.0  0.3   6460  1616 ttyS0    Ss+  06:33   0:00 /sbin/agetty ttyS0 9600 vt100-nav
root      2620  0.0  0.2   4312  1492 tty1     Ss+  06:33   0:00 /sbin/mingetty /dev/tty1
root      2623  0.0  0.2   4312  1444 tty2     Ss+  06:33   0:00 /sbin/mingetty /dev/tty2
root      2625  0.0  0.2   4312  1388 tty3     Ss+  06:33   0:00 /sbin/mingetty /dev/tty3
root      2627  0.0  0.2   4312  1392 tty4     Ss+  06:33   0:00 /sbin/mingetty /dev/tty4
root      2629  0.0  0.2   4312  1488 tty5     Ss+  06:33   0:00 /sbin/mingetty /dev/tty5
root      2631  0.0  0.3  10876  1628 ?        S    06:33   0:00 /sbin/udevd -d
root      2632  0.0  0.2   4312  1408 tty6     Ss+  06:33   0:00 /sbin/mingetty /dev/tty6
root      2689  0.0  1.3 117784  6712 ?        Ss   07:00   0:00 sshd: ec2-user [priv]
ec2-user  2691  0.0  1.1 117784  5652 ?        S    07:00   0:00 sshd: ec2-user@pts/0
ec2-user  2692  0.0  0.6 115348  3288 pts/0    Ss   07:00   0:00 -bash
postfix   2907  0.0  1.3  93032  6584 ?        S    08:13   0:00 pickup -l -t fifo -u
ec2-user  3050  0.0  0.6 115348  3396 pts/0    S    08:22   0:00 bash
ec2-user  3220  0.0  0.4 117204  2460 pts/0    R+   08:44   0:00 ps aux
$
netstat

トラフィックの場合は、netstat コマンドで接続が多いプロセスを特定しましょう。下記のようなオプションで、PIDも出力する事が出来ます。

$ sudo netstat -anep
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       User       Inode      PID/Program name
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      0          10059      2484/sshd
tcp        0      0 0.0.0.0:25                  0.0.0.0:*                   LISTEN      0          10309      2584/master
tcp        0      0 0.0.0.0:33410               0.0.0.0:*                   LISTEN      29         9566       2358/rpc.statd
tcp        0      0 127.0.0.1:199               0.0.0.0:*                   LISTEN      0          9825       2421/snmpd
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      0          9488       2341/rpcbind
tcp        0    464 172.31.15.196:22            xxx.xxx.xxx.xxx:19752       ESTABLISHED 0          12759      2689/sshd
tcp        0      0 :::21                       :::*                        LISTEN      99         10425      2593/proftpd
tcp        0      0 :::22                       :::*                        LISTEN      0          10061      2484/sshd
tcp        0      0 :::39943                    :::*                        LISTEN      29         9572       2358/rpc.statd
tcp        0      0 :::111                      :::*                        LISTEN      0          9491       2341/rpcbind
udp        0      0 0.0.0.0:820                 0.0.0.0:*                               0          9487       2341/rpcbind
udp        0      0 0.0.0.0:68                  0.0.0.0:*                               0          8856       2252/dhclient
udp        0      0 127.0.0.1:838               0.0.0.0:*                               0          9560       2358/rpc.statd
udp        0      0 0.0.0.0:111                 0.0.0.0:*                               0          9486       2341/rpcbind
udp        0      0 172.31.15.196:123           0.0.0.0:*                               0          10144      2509/ntpd
udp        0      0 127.0.0.1:123               0.0.0.0:*                               0          10143      2509/ntpd
udp        0      0 0.0.0.0:123                 0.0.0.0:*                               0          10136      2509/ntpd
udp        0      0 0.0.0.0:161                 0.0.0.0:*                               0          9824       2421/snmpd
udp        0      0 0.0.0.0:47782               0.0.0.0:*                               29         9563       2358/rpc.statd
udp        0      0 :::820                      :::*                                    0          9490       2341/rpcbind
udp        0      0 :::52050                    :::*                                    29         9569       2358/rpc.statd
udp        0      0 :::111                      :::*                                    0          9489       2341/rpcbind
udp        0      0 fe80::4b2:53ff:fe38:5837:123 :::*                                    0          10146      2509/ntpd
udp        0      0 ::1:123                     :::*                                    0          10145      2509/ntpd
udp        0      0 :::123                      :::*                                    0          10137      2509/ntpd

復旧対処

調査の結果わかった内容で対策を考えましょう。

まとめ

こんなに書いといてあれですが、実際には、いきなり ps コマンドで特定する事の方が多いかもしれません。

また、サーバにログインして確認するコマンドを紹介しましたが、実際の運用では可能な限りモニタリングツールを導入してサーバへのログインなしに確認できる環境を作りましょう。サーバが複数台の環境だとコマンドで見るよりもグラフを見た方が何倍も判りやすく、早い解決が期待出来ます。

おすすめ書籍

より詳しい内容は下記書籍が初心者にもわかりやすいと思います。今回の内容だと特に最初の1冊をお勧めします。