TECHSTEP

ITインフラ関連の記事を公開してます。

SNMP ExporterからのメトリクスをPrometheusで表示する

はじめに

Kubernetesで監視を行う際の代表的なツールのひとつとしてPrometheusがあります。PrometheusではExporterを介してメトリクスを受け取り、グラフ等で表示することができます。Exporterは様々な種類が公開されていますが、今回はその中からSNMP Exporterを使ってメトリクスを出力し、Prometheusの画面上で確認できるまでをやってみました。

SNMP Exporterとは

SNMP Exporterは、SNMP(Simple Network Management Protocol)によって集められた情報を、Prometheusで見れるようにしてくれるツールです。公式ページでは2つのツールを紹介しており、ひとつはSNMP Exporter自身、もうひとつはExporterで使用するsnmp.ymlを、ユーザの指定する情報に基づいて出力してくれるSNMP Exporter Config Generatorです。Generatorを使用する理由として、デフォルトのsnmp.ymlは行数も多く内容も複雑なため、手書きでの修正を推奨されていないからです。

今回はお試しということで非常に単純な設定しか入れないため、generatorは使用せず、手で修正したsnmp.ymlを使用しました。generatorの利用方法についてはまた後日紹介します。

環境

今回検証を行うのは、以下のような環境にあります。こちらの記事で環境構築について紹介しているので、詳細はそちらをご覧ください。

  • OS: Centos 7
  • Kubernetes version: 1.13.1
  • User: 以下の作業は全てrootユーザで実行しています。

今回は<k8s-node-1>ノードにNet-SNMPを導入し、SNMP-Exporterを介してメトリクスを受け取り、それをPrometheusで表示することを目指します。

Net-SNMPの設定

デフォルトの状態ではSNMPを利用できなかったため、Net-SNMPをインストールしてSNMPが利用できるようにします。

Net-SNMPの導入自体はとてもシンプルです。まずはyumコマンドを用いてインストールします。

yum install -y net-snmp net-snmp-utils

次にコンフィグファイルに当たる/etc/snmp/snmpd.confを編集します。こちらは行数が多いですが、関連するのは以下の箇所になります。

# 行数を確認する
[root@k8s-node-1 ~]# wc -l /etc/snmp/snmpd.conf
462 /etc/snmp/snmpd.conf

# コメントアウトされていない箇所を抜き出す
[root@k8s-node-1 ~]# egrep -v "^#|^$" /etc/snmp/snmpd.conf
com2sec notConfigUser  default       public
group   notConfigGroup v1           notConfigUser
group   notConfigGroup v2c           notConfigUser
view    systemview    included   .1.3.6.1.2.1.1
view    systemview    included   .1.3.6.1.2.1.25.1.1
access  notConfigGroup ""      any       noauth    exact  systemview none none
syslocation Unknown (edit /etc/snmp/snmpd.conf)
syscontact Root <root@localhost> (configure /etc/snmp/snmp.local.conf)
dontLogTCPWrappersConnects yes
[root@k8s-node-1 ~]# 

# 説明文と行番号も含めて出力する (説明文を追記しています)
[root@k8s-node-1 ~]# less -N /etc/snmp/snmpd.conf

~ 省略 ~

37 ####
38 # First, map the community name "public" into a "security name"
39 
40 #       sec.name  source          community
41 com2sec notConfigUser  default       public

# com2sec: セキュリティを定義
## sec.name: セキュリティ名
## source: 送信元IPアドレス
## community: コミュニティ名

43 ####
44 # Second, map the security name into a group name:
45 
46 #       groupName      securityModel securityName
47 group   notConfigGroup v1           notConfigUser
48 group   notConfigGroup v2c           notConfigUser

# group: com2secで定義したセキュリティ名と紐づくグループ名を定義
## groupName: グループ名
## securityModel: セキュリティモデル。{v1|v2c|usm}のいずれかを選択
## securityName: セキュリティ名。com2secで定義したものを入力

50 ####
51 # Third, create a view for us to let the group have rights to:
52 
53 # Make at least  snmpwalk -v 1 localhost -c public system fast again.
54 #       name           incl/excl     subtree         mask(optional)
55 view    systemview    included   .1.3.6.1.2.1.1
56 view    systemview    included   .1.3.6.1.2.1.25.1.1

# view: SNMPで参照するMIBツリーの参照許可範囲を指定
## name: ビュー名
## incl/excl: {include|exclude}から選択
## subtree: MIBツリーの参照範囲

58 ####
59 # Finally, grant the group read-only access to the systemview view.
60 
61 #       group          context sec.model sec.level prefix read   write  notif
62 access  notConfigGroup ""      any       noauth    exact  systemview none none

# access: SNMPへのアクセス許可対象を指定
## group: 上のgroupで定義したグループ名
## context: {any|v1|v2c|usm|tsm|ksm}から選択
## sec.model: {any|v1|v2c|usm}から選択
## sec.level: {noauth|auth|priv}から選択
## prefix: {exact|prefix}から選択
## read: 読み取り権限を与えるビュー名を入力
## write: 書き込み権限を与えるビュー名を入力 (なければnone)
## notif: 通知するビュー名を入力 (なければnone)
### context、sec.model、sec.level、prefixはSNMPv3で使用するパラメータ

~ 中略 ~

155 ###############################################################################
156 # System contact information
157 #
158 
159 # It is also possible to set the sysContact and sysLocation system
160 # variables through the snmpd.conf file:
161 
162 syslocation Unknown (edit /etc/snmp/snmpd.conf)
163 syscontact Root <root@localhost> (configure /etc/snmp/snmp.local.conf)

# syslocation: システムの存在する場所を入力
## 自由記述 
# syscontact: システムの連絡先を入力
## 上の例では「Root」というユーザの連絡先が「root@localhost」であることを示す

~ 中略 ~

176 ###############################################################################
177 # Logging
178 #
179 
180 # We do not want annoying "Connection from UDP: " messages in syslog.
181 # If the following option is commented out, snmpd will print each incoming
182 # connection, which can be useful for debugging.
183 
184 dontLogTCPWrappersConnects yes

# dontLogTCPWrappersConnects: この行をコメントアウトすると、snmpdがアクセスするたびに、その情報がログに出力されます。デバッグ等に有用です。

[root@k8s-node-1 ~]# 

なお、{v1|v2c|usm}は、それぞれ{SNMPv1|SNMPv2|SNMPv3}に対応しています。

今回はデフォルトの設定から以下のように変更しました。

# 変更後のsnmpd.confからコメントアウトの箇所以外を出力
[root@k8s-node-1 ~]# egrep -v "^#|^$" /etc/snmp/snmpd.conf
com2sec local localhost public
com2sec mynet 10.0.0.0/24 public
group MyGroup v1 local
group MyGroup v1 mynet
view all included .1 80
access MyGroup "" any noauth exact all all none
syslocation Centos 7, Linux Server
syscontact root <root@localhost>
dontLogTCPWrappersConnects yes
[root@k8s-node-1 ~]# 

# 差分を確認
[root@k8s-node-1 ~]# diff /etc/snmp/snmpd.conf.bk /etc/snmp/snmpd.conf 
41c41,43
< com2sec notConfigUser  default       public
---
> #com2sec notConfigUser  default       public
> com2sec local localhost public
> com2sec mynet 10.0.0.0/24 public
47,48c49,52
< group   notConfigGroup v1           notConfigUser
< group   notConfigGroup v2c           notConfigUser
---
> #group   notConfigGroup v1           notConfigUser
> #group   notConfigGroup v2c           notConfigUser
> group MyGroup v1 local
> group MyGroup v1 mynet
55,56c59,61
< view    systemview    included   .1.3.6.1.2.1.1
< view    systemview    included   .1.3.6.1.2.1.25.1.1
---
> #view    systemview    included   .1.3.6.1.2.1.1
> #view    systemview    included   .1.3.6.1.2.1.25.1.1
> view all included .1 80
62c67,68
< access  notConfigGroup ""      any       noauth    exact  systemview none none
---
> #access  notConfigGroup ""      any       noauth    exact  systemview none none
> access MyGroup "" any noauth exact all all none
162,163c168,172
< syslocation Unknown (edit /etc/snmp/snmpd.conf)
< syscontact Root <root@localhost> (configure /etc/snmp/snmp.local.conf)
---
> #syslocation Unknown (edit /etc/snmp/snmpd.conf)
> #syscontact Root <root@localhost> (configure /etc/snmp/snmp.local.conf)
> 
> syslocation Centos 7, Linux Server
> syscontact root <root@localhost>
[root@k8s-node-1 ~]# 
  • com2secではKubernetesクラスターのプライベートIPアドレスレンジ (10.0.0.0/24)を指定しています。
  • viewではすべてのMIBツリー情報を見せるように設定しています。
  • 今回はSNMPv1のみ使用しました。

コンフィグファイルを編集した後、サービスの起動を行います。

[root@k8s-node-1 ~]# systemctl start snmpd
[root@k8s-node-1 ~]# systemctl status snmpd
● snmpd.service - Simple Network Management Protocol (SNMP) Daemon.
   Loaded: loaded (/usr/lib/systemd/system/snmpd.service; disabled; vendor preset: disabled)
   Active: active (running) since Sat 2019-01-12 04:20:57 UTC; 6s ago
 Main PID: 12810 (snmpd)
    Tasks: 1
   Memory: 4.2M
   CGroup: /system.slice/snmpd.service
           └─12810 /usr/sbin/snmpd -LS0-6d -f

Jan 12 04:20:57 k8s-node-1 systemd[1]: Starting Simple Network Management Protocol (SNMP) Daemon....
Jan 12 04:20:57 k8s-node-1 snmpd[12810]: Duplicate IPv4 address detected, some interfaces may not be visible in IP-MIB
Jan 12 04:20:57 k8s-node-1 snmpd[12810]: NET-SNMP version 5.7.2
Jan 12 04:20:57 k8s-node-1 systemd[1]: Started Simple Network Management Protocol (SNMP) Daemon..
[root@k8s-node-1 ~]#

ここでDuplicate IPv4 address detected, some interfaces may not be visible in IP-MIBというメッセージが表示されていますが、原因がわかりませんでした。こちらを参照すると、特に気にする必要もなさそうです。

ひとまずこれで、監視対象サーバがSNMPを動かせるようになったので、今度は監視サーバ側 (k8s-master)からSNMPを見れるかを確認します。ここではsnmpwalkコマンドを用いて、MIB値を取得できるかを確認します。

[root@k8s-master ~]# yum install -y net-snmp net-snmp-utils

[root@k8s-master ~]# snmpwalk -v 1 -c public 10.0.0.235 | wc -l
4451

[root@k8s-master ~]# snmpwalk -v 1 -c public 10.0.0.235 | head
SNMPv2-MIB::sysDescr.0 = STRING: Linux k8s-node-1 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (1350) 0:00:13.50
SNMPv2-MIB::sysContact.0 = STRING: root <root@localhost>
SNMPv2-MIB::sysName.0 = STRING: k8s-node-1
SNMPv2-MIB::sysLocation.0 = STRING: Centos 7, Linux Server
SNMPv2-MIB::sysORLastChange.0 = Timeticks: (3) 0:00:00.03
SNMPv2-MIB::sysORID.1 = OID: SNMP-MPD-MIB::snmpMPDCompliance
SNMPv2-MIB::sysORID.2 = OID: SNMP-USER-BASED-SM-MIB::usmMIBCompliance
SNMPv2-MIB::sysORID.3 = OID: SNMP-FRAMEWORK-MIB::snmpFrameworkMIBCompliance
[root@k8s-master ~]#

確かにk8s-node-1から取得できているようです。

SNMP-Exporterの設定

続いてSNMP Exporterの設定を行います。SNMP Exporterの公式ページではBinaryファイルの起動方法が記載されているので、今回はそれに従います。まずは公式githubのreleaseページから圧縮ファイルをダウンロードします。

wget https://github.com/prometheus/snmp_exporter/releases/download/v0.14.0/snmp_exporter-0.14.0.linux-amd64.tar.gz
tar xvzf snmp_exporter-0.14.0.linux-amd64.tar.gz
cd snmp_exporter-0.14.0.linux-amd64

デフォルト設定でよければ、あとは./snmp_exporterと入力すれば起動し、http://<k8s-masterのグローバルIPアドレス>:9116にアクセスすると以下のような画面が表示されます。

f:id:FY0323:20190112182939j:plain

さらにhttp://<k8s-masterのグローバルIPアドレス>:9116/metricsにアクセスすると、取得するメトリクスが表示されます。

f:id:FY0323:20190112191417j:plain

これでSNMP Exporter自体は起動できましたが、監視対象サーバのSNMPを受け取るための設定を行います。 SNMP Exporterのコンフィグファイルに当たるsnmp.ymlの中身を一部だけ見てみます (各ポイントの説明を追記しています)。

# モジュール名
cisco_wlc:

# walk: snmpwalkするOID
  walk:
  - 1.3.6.1.2.1.2
  - 1.3.6.1.2.1.31.1.1

~ 中略 ~

# metrics: メトリクスの名前とOIDとの紐付けを定義
  metrics:
  - name: ifNumber
    oid: 1.3.6.1.2.1.2.1
    type: gauge

~ 中略 ~

上記のように、モジュール名、walk、metricsなどの値を定義します。

[20190113追記]

snmp.ymlのフォーマットに関して公式ページのこちらこちらに説明されていました。こちらに簡単に抜粋しておきます。

  • auth: {community|user|security_level}などなど、様々なauth/versionに関するオプションがあります。
  • walk: walkするOIDサブツリーのリスト
  • get: 直接getするOIDのリスト
  • metrics: 抽出するメトリクスのリスト

今回snmp.ymlに追加した設定は以下になります。

[root@k8s-master snmp_exporter-0.14.0.linux-amd64]# diff snmp.yml snmp.yml.org 
2,17d1
< linux:
<   version: 2
<   auth:
<     community: public
<   walk:
<   - 1.3.6.1.2.1.1.5.0
<   - 1.3.6.1.2.1.2.1.0
<   metrics:
<   - name: sysName
<     oid: 1.3.6.1.2.1.1.5.0
<     type: gauge
< 
<   - name: ifNumber
<     oid: 1.3.6.1.2.1.2.1.0
<     type: gauge
< 
[root@k8s-master snmp_exporter-0.14.0.linux-amd64]# 

これでSNMP Exporterの設定は完了したので、SNMP Exporterを起動します。

[root@k8s-master snmp_exporter-0.14.0.linux-amd64]# ./snmp_exporter &
[1] 11915
[root@k8s-master snmp_exporter-0.14.0.linux-amd64]# INFO[0000] Starting snmp exporter (version=0.14.0, branch=HEAD, revision=da73490e051012714ee36cbf69d74dd41e21d4fb)  source="main.go:139"
INFO[0000] Build context (go=go1.11.2, user=root@86242397dc77, date=20181204-15:41:19)  source="main.go:140"
INFO[0000] Listening on :9116                            source="main.go:226"

[root@k8s-master snmp_exporter-0.14.0.linux-amd64]# 

Prometheusの設定

最後にPrometheusの設定を行います。Prometheusの起動方法等はこちらの記事で紹介しています。ここではprometheus.ymlファイルの変更箇所を紹介します。

[root@k8s-master prometheus-2.6.0.linux-amd64]# prometheus.yml
# my global config
global:
  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
    - targets: ['localhost:9090']

# ここからが追加箇所
  - job_name: snmp
    static_configs:
    - targets: ['localhost:9116']
[root@k8s-master prometheus-2.6.0.linux-amd64]# 

追加したものは単純にSNMP Exporterの接続先を指定しただけです。

上記を追加したのち、Prometheusを起動します。

[root@k8s-master prometheus-2.6.0.linux-amd64]# ./prometheus --config.file=prometheus.yml &
[2] 13936
[root@k8s-master prometheus-2.6.0.linux-amd64]# level=info ts=2019-01-12T04:42:42.359459537Z caller=main.go:243 msg="Starting Prometheus" version="(version=2.6.0, branch=HEAD, revision=dbd1d58c894775c0788470944b818cc724f550fb)"
level=info ts=2019-01-12T04:42:42.359544708Z caller=main.go:244 build_context="(go=go1.11.3, user=root@bf5760470f13, date=20181217-15:14:46)"
level=info ts=2019-01-12T04:42:42.359569444Z caller=main.go:245 host_details="(Linux 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 k8s-master (none))"
level=info ts=2019-01-12T04:42:42.359612736Z caller=main.go:246 fd_limits="(soft=1024, hard=4096)"
level=info ts=2019-01-12T04:42:42.359632891Z caller=main.go:247 vm_limits="(soft=unlimited, hard=unlimited)"
level=info ts=2019-01-12T04:42:42.361882876Z caller=main.go:561 msg="Starting TSDB ..."
level=info ts=2019-01-12T04:42:42.362027192Z caller=web.go:429 component=web msg="Start listening for connections" address=0.0.0.0:9090

これでPrometheusが見れる状態になりましたので、http://<k8s-masterのグローバルIPアドレス>:9090にアクセスします。アクセスした画面からStatusTargetsにアクセスすると、prometheus.ymlで設定したjob_name: snmpが確認できます。

f:id:FY0323:20190112192345j:plain

さらに最初の画面に戻り、Expressionから「snmp」と入力すると、SNMPの幾つかのメトリクスが表示され、取得できていることが確認できます。

f:id:FY0323:20190112192852j:plain

snmp.ymlで設定したMIB値のものが取れていないように見えますので、設定に誤りがあるかもしれません。。。引き続き調べてまいります。

参考リンク

TCP/IP - SNMP

SNMPとMIB/OIDについて(CentOS編)

ネットワーク機器のSNMP MIB/OIDまとめ

snmpd.conf - ファイルのフォーマットと規約の説明 - Linux コマンド集 一覧表

Net-SNMP の設定について

CentOS で SNMPd のログを切り分ける

Prometheus の SNMP Exporter で net-snmp からメトリクス収集するメモ

【AWS】素のEC2サーバーにCactiをインストールする