SNMPでリソース情報を取得する

## 目的
- サーバーからリソース情報を定期的に収集して蓄積したい。
- リソース情報の取得方法としては様々な手段があるがSNMPで取得できる情報を確認する。
- 具体的にターゲットとするサーバーリソースは以下。
    - CPU
    - メモリ
    - ディスク

## 背景
- snmpによる定期的なリソース監視を行うとき、snmpwalkですべての情報を取得する場合、取得対象サーバに余計な負荷がかかりそう。取得した情報の保存先ディスクも圧迫されるので、できるだけ有用な情報のみに厳選しておきたい。

## 検証環境
本来はサーバーで検証したいところだが、今回はMacbookを使用する。
Net-SNMPはすでにインストールされて、サービスとして起動している状態とする。

- OS: Mac OSX
- SNMP: Net-SNMP

## 参考情報

[MacOSXでSNMPを使う設定をする] (https://qiita.com/suto3/items/1d38cd639c83a7e42343)

[Net-SNMPが提供するMIB情報] (http://www.net-snmp.org/docs/mibs/)

## 検証
### メモリ・ディスク情報
Net-SNMPの参考情報[HOST-RESOURCES-MIB](http://www.net-snmp.org/docs/mibs/host.html)より、メモリ・ディスクに関する情報を探す。

まずは**hrStorage**の情報を取得してみる。

```shell:
$snmpwalk -v 2c -c public localhost hrStorage
HOST-RESOURCES-MIB::hrMemorySize.0 = INTEGER: 8388608 KBytes
（省略）
HOST-RESOURCES-MIB::hrStorageType.1 = OID: HOST-RESOURCES-TYPES::hrStorageRam
HOST-RESOURCES-MIB::hrStorageType.10 = OID: HOST-RESOURCES-TYPES::hrStorageVirtualMemory
HOST-RESOURCES-MIB::hrStorageType.31 = OID: HOST-RESOURCES-TYPES::hrStorageFixedDisk
HOST-RESOURCES-MIB::hrStorageType.32 = OID: HOST-RESOURCES-TYPES::hrStorageFixedDisk
HOST-RESOURCES-MIB::hrStorageType.33 = OID: HOST-RESOURCES-TYPES::hrStorageFixedDisk
HOST-RESOURCES-MIB::hrStorageType.34 = OID: HOST-RESOURCES-TYPES::hrStorageFixedDisk
HOST-RESOURCES-MIB::hrStorageType.35 = OID: HOST-RESOURCES-TYPES::hrStorageFixedDisk
HOST-RESOURCES-MIB::hrStorageDescr.1 = STRING: Physical memory
HOST-RESOURCES-MIB::hrStorageDescr.10 = STRING: Swap space
HOST-RESOURCES-MIB::hrStorageDescr.31 = STRING: /
HOST-RESOURCES-MIB::hrStorageDescr.32 = STRING: /dev
HOST-RESOURCES-MIB::hrStorageDescr.33 = STRING: /private/var/vm
HOST-RESOURCES-MIB::hrStorageDescr.34 = STRING: /net
HOST-RESOURCES-MIB::hrStorageDescr.35 = STRING: /home
（省略）
HOST-RESOURCES-MIB::hrStorageAllocationUnits.1 = INTEGER: 4096 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.10 = INTEGER: 4096 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.31 = INTEGER: 4096 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.32 = INTEGER: 512 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.33 = INTEGER: 4096 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.34 = INTEGER: 1024 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.35 = INTEGER: 1024 Bytes
HOST-RESOURCES-MIB::hrStorageSize.1 = INTEGER: 2097152
HOST-RESOURCES-MIB::hrStorageSize.10 = INTEGER: 524287
HOST-RESOURCES-MIB::hrStorageSize.31 = INTEGER: 29545461
HOST-RESOURCES-MIB::hrStorageSize.32 = INTEGER: 370
HOST-RESOURCES-MIB::hrStorageSize.33 = INTEGER: 29545461
HOST-RESOURCES-MIB::hrStorageSize.34 = INTEGER: 0
HOST-RESOURCES-MIB::hrStorageSize.35 = INTEGER: 0
HOST-RESOURCES-MIB::hrStorageUsed.1 = INTEGER: 1130201
HOST-RESOURCES-MIB::hrStorageUsed.10 = INTEGER: 85397
HOST-RESOURCES-MIB::hrStorageUsed.31 = INTEGER: 11605117
HOST-RESOURCES-MIB::hrStorageUsed.32 = INTEGER: 370
HOST-RESOURCES-MIB::hrStorageUsed.33 = INTEGER: 786437
HOST-RESOURCES-MIB::hrStorageUsed.34 = INTEGER: 0
HOST-RESOURCES-MIB::hrStorageUsed.35 = INTEGER: 0
```

出力結果から、メモリやディスクに関して使用できそうな情報を抽出する。

|項目  |参考値  |メモ  |
|---|---|---|
|hrMemorySize |INTEGER: 8388608 KBytes |マシン搭載しているメモリ量 |
|hrStorageType |hrStorageRam |ストレージタイプ：物理メモリ |
| |hrStorageVirtualMemory |ストレージタイプ：仮想メモリ |
| |hrStorageFixedDisk |ストレージタイプ：物理ディスク |
|hrStorageDescr |Physical memory |物理メモリの場合 |
| |Swap space|仮想メモリの場合|
||/  |物理ディスクのマウントポイント|
||/dev  |物理ディスクのマウントポイント|
|hrStorageSize |INTEGER: 2097152 |ストレージのサイズ |
|hrStorageUsed |INTEGER: 1683085 |ストレージの使用量 |

コマンドの出力内容と比較してみる。

---

- 物理メモリ量のコマンド出力

```shell:
$top -l 1 -s 0 | grep PhysMem
PhysMem: 5306M used (1953M wired), 2885M unused.
```

- 物理メモリ量の評価

SNMPのhrMemorySizeとtopの結果を比較
SNMPの出力結果：8388608 KBytes　≒　8192 MBytes
topの出力結果；5306M used ＋　2885M unused.　≒　8191 Mbytes
評価：両者は概ね一致している

SNMPのhrStorageSize、hrStorageUsedとtopコマンドの結果を比較

|項目  |値..(a)|hrStorageAllocationUnits..(b)|(a)*(b)|top  |
|---|---:|---:|---:|---:|
|hrStorageSize | 2097152 |4096 Bytes|8192 MB | 8191 MB|
|hrStorageUsed | 1130201 |4096 Bytes|4414 MB | 5306 MB |

使用メモリに関してやや乖離があります。
topコマンド以外でもメモリ容量を確認してみました。

- MACのアクティビティモニタのメモリと比較

使用メモリは取得タイミングによって変動があるため
何回か取得してみます。

|項目  |SNMP|top|アクティビティモニタ |
|---|---:|---:|---:|
|1回目 | 5.53 GB |6.26 GB | 4.85 GB|
|2回目 | 5.54 GB |6.26 GB | 4.84 GB|

結果としては取得方法によって使用済みメモリの容量の見え方に差があるということがわかりましたが、
SNMPで取得した使用済みメモリの容量は概ね正しい結果を出力していそうです。

**結論：SNMPで正しい物理メモリ量を取得可能**

---

- ディスク容量のコマンド出力(MB単位で出力)

```shell:
$df -Pm
Filesystem    1M-blocks  Used Available Capacity  Mounted on
/dev/disk1s1     115411 45330     66373    41%    /
devfs                 0     0         0   100%    /dev
/dev/disk1s4     115411  3072     66373     5%    /private/var/vm
map -hosts            0     0         0   100%    /net
map auto_home         0     0         0   100%    /home
```

SNMPのhrStorageUsedとdfの結果を比較

|項目  |SNMP(hrStorageUsed)..(a)|SNMP(hrStorageAllocationUnits)..(b)|(a)*(b)|df  |
|---|---:|---:|---:|---:|
|/ | 11605117 |4096 Bytes|45332 MB | 45330 MB|
|/dev | 370 |512 Bytes |0MB | 0 MB |
|/private/var/vm | 786437 |4096 Bytes | 3072 MB| 3072 MB |
|/net |0 |1024 Bytes|0 MB  |0 MB |
|/home |0 |1024 Bytes|0 MB  |0 MB|

- ディスク容量の評価

hrStorageUsed * hrStorageAllocationUnits の計算結果がdfコマンドの出力
結果とほぼ一致した。

SNMPでは項目によっては、カウンタが32bit表現が限界という仕様がある。
AllocationUnitsが4096 Bytesを前提としたとき、32bit表現の最大容量は以下の通り。
4,294,967,295 * 4096 Bytes = 16,383 GB
32bit表現だとしても、おおよそ16TBまで正しく出力可能と思われる。

**結論：SNMPで正しいディスク容量を取得可能**

---

### CPU情報
Net-SNMPの参考情報HOST-RESOURCES-MIBより、CPUに関する情報を探す。

まずは**hrProcessorTable**の情報を取得してみる。
（出力結果のID部分は一部加工）

```shell:
$snmpwalk -v 2c -c public localhost hrProcessorTable
HOST-RESOURCES-MIB::hrProcessorFrwID.100000 = OID: SNMPv2-SMI::zeroDotZero
HOST-RESOURCES-MIB::hrProcessorFrwID.100001 = OID: SNMPv2-SMI::zeroDotZero
HOST-RESOURCES-MIB::hrProcessorFrwID.100002 = OID: SNMPv2-SMI::zeroDotZero
HOST-RESOURCES-MIB::hrProcessorFrwID.100003 = OID: SNMPv2-SMI::zeroDotZero
HOST-RESOURCES-MIB::hrProcessorLoad.100000 = INTEGER: 19
HOST-RESOURCES-MIB::hrProcessorLoad.100001 = INTEGER: 4
HOST-RESOURCES-MIB::hrProcessorLoad.100002 = INTEGER: 14
HOST-RESOURCES-MIB::hrProcessorLoad.100003 = INTEGER: 4
```

今回、検証に使用したmacはCPUのコア数は2コアなのですが
スレッド数が4のため、CPU数としては4が認識されています。

出力結果のhrProcessorLoadについてMIB情報の説明を確認してみます。

>The average, over the last minute, of the percentage of time that this processor was not idle.
Implementations may approximate this one minute smoothing period if necessary.

直近1分間のCPU使用率(単位は%)を出力しているようです。

CPUに負荷をかけるstress-ngを使用してさらに検証してみます。

```shell:
$stress-ng -c 1 &

$ps -o comm,pid,%cpu
COMM        PID  %CPU
-bash      9894   0.0
-bash     24040   0.0
stress-ng 24117   0.0
stress-ng 24118 100.0

$top
Processes: 332 total, 3 running, 329 sleeping, 1222 threads
Load Avg: 3.02, 3.30, 3.01  CPU usage: 42.19% user, 2.92% sys, 54.87% idle

$snmpwalk -v 2c -c public localhost hrProcessorLoad
HOST-RESOURCES-MIB::hrProcessorLoad.100000 = INTEGER: 70
HOST-RESOURCES-MIB::hrProcessorLoad.100001 = INTEGER: 28
HOST-RESOURCES-MIB::hrProcessorLoad.100002 = INTEGER: 71
HOST-RESOURCES-MIB::hrProcessorLoad.100003 = INTEGER: 28
```

アクティビティモニタの状態
システム：　　6.56%
ユーザ：　　　44.98%
アイドル状態：50.14%

SNMPの平均CPU使用率　＝　(70+28+71+28)/4　=　49.25%
アクティビティモニタのCPU使用率　＝　6.56(システム)＋44.98(ユーザ)　＝　51.54%
topコマンドでのCPU使用率　＝　2.92(システム)＋42.19(ユーザ)　＝　45.11%

SNMPでの取得結果はその他の取得結果とほぼ一致しました。

- CPU情報の評価

SNMPではCPUスレッド数及び、
CPUスレッド毎の直近1分間の平均CPU使用率(システム＋ユーザ)を確認可能。

**結論：SNMPでCPU使用率を取得可能**