Zabbix クライアントでコマンド実行し、標準では用意されていない項目を監視する

[しまねソフト研究開発センター](https://www.s-itoc.jp)（略称 ITOC）にいます、東です。

[前回](https://qiita.com/HirohitoHigashi/items/951b3ea04488c51c3be4) は、Zabbix クライアントの基本的な設定を行い、さらにログ監視の設定を行いました。引き続き今回は、クライアントで任意コマンドを実行させることで、標準では用意されていない項目を監視してみようと思います。


# 目標

* 任意のポートのTCP接続数合計を監視する
* TCP接続数の取得は、クライアントでコマンドの実行により行う


# 手順

記憶では、以前のバージョンのZabbixではサーバ側の設定だけでこのようなことができていたように思いますが、当記事でターゲットにしているバージョン (6.0LTS) では、おそらくセキュリティーの関係で、それはできなくなっています。また、目標の「任意のポートのTCP接続数合計を監視する」は、エージェントバージョン2からは標準で持っている機能のようですが、当記事の目的は「クライアントでコマンドを実行することによる汎用性」ですので、これを目標に定めてやってみます。


# クライアントの設定 FreeBSDの場合

## コマンド列の設計

まずは TCP 接続数を取得するコマンド列を作ります。汎用性を考えると、できるだけ標準コマンドだけで間に合わせたいと思います。

FreeBSDの場合は、netstat を使います。

netstat の出力を確認すると、
```
$ netstat -an -p tcp
Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address          Foreign Address        (state)
tcp4       0      0 192.168.108.61.80      192.168.108.10.61585   FIN_WAIT_2
tcp4       0      0 *.80                   *.*                    LISTEN
tcp6       0      0 *.80                   *.*                    LISTEN
tcp4       0     36 192.168.108.61.22      192.168.108.10.62483   ESTABLISHED
tcp6       0      0 *.22                   *.*                    LISTEN
tcp4       0      0 *.22                   *.*                    LISTEN
tcp4       0      0 *.10050                *.*                    LISTEN
tcp6       0      0 *.10050                *.*                    LISTEN
```

このように LISTEN が混ざりますので、取り除いてから必要なポート番号の行をカウントします。

```
$ netstat -an -p tcp | grep -v LISTEN | grep "\.80" | wc -l
       1
```

これをベースにします。

## Agentd へ設定追加

Agentd に、`UserParameter` を指定し、目的のユーザーパラメータを追加します。
以下の通り設計します。

* パラメータ名として、`my.tcp.connection.count` とする
* ポート番号の設定はサーバからのパラメータで与えられるようにする

前項ではコマンド列で、ポート番号80をカウントしましたが、サーバごとに監視したいポート番号は違うと思われますので、サーバ設定により監視対象ポート番号を指定できるようにアレンジします。

以下の行を設定ファイルに追加し Agentd を再起動します。

```:/usr/local/etc/zabbix6/zabbix_agentd.conf
UserParameter=my.tcp.connection.count[*],netstat -an -p tcp | grep -v LISTEN | (if [ -n "$1" ] ; then grep "\.$1 "; else grep "^tcp"; fi) | wc -l
```


# クライアントの設定 Linux(Debian) の場合

## コマンド列の設計

Linuxの場合は、ss を使います。

ss の出力を確認すると、
```
$ ss -ant
State           Recv-Q      Send-Q                     Local Address:Port                        Peer Address:Port       Process
LISTEN          0           128                              0.0.0.0:22                               0.0.0.0:*
LISTEN          0           20                             127.0.0.1:25                               0.0.0.0:*
LISTEN          0           4096                             0.0.0.0:10050                            0.0.0.0:*
ESTAB           0           0                         192.168.108.65:22                        192.168.108.10:55954
ESTAB           0           52                        192.168.108.65:22                        192.168.108.10:39569
LISTEN          0           128                                 [::]:22                                  [::]:*
LISTEN          0           511                                    *:80                                     *:*
LISTEN          0           20                                 [::1]:25                                  [::]:*
LISTEN          0           4096                                [::]:10050                               [::]:*
FIN-WAIT-2      0           0                [::ffff:192.168.108.65]:80               [::ffff:192.168.108.10]:12097
```

FreeBSDと同様に LISTEN が混ざりますので、取り除いてから必要なポート番号の行をカウントします。

```
$ ss -ant | grep -v LISTEN | grep ":80" | wc -l
1
```

これをベースにします。

## Agentd へ設定追加

Agentd に、`UserParameter` を指定し、目的のユーザーパラメータを追加します。
FreeBSDの場合と同様に、以下の通り設計します。

* パラメータ名として、`my.tcp.connection.count` とする
* ポート番号の設定はサーバからのパラメータで与えられるようにする

以下の行を設定ファイルに追加し Agentd を再起動します。

```:/etc/zabbix/zabbix_agentd.conf
UserParameter=my.tcp.connection.count[*],ss -ant | grep -v LISTEN | (if [ -n "$1" ] ; then grep ":$1 "; else tail -n +2; fi) | wc -l
```


# Zabbix Server への登録

## HTTP(80) ポート監視の追加

ウェブフロントエンドを使い、先ほどのユーザパラメータ監視を登録します。

* 左ペインのメニューから 設定 > ホスト とクリックし、対象ホスト行の `アイテム` をクリックします
* 右ペイン上部の [アイテムの作成] をクリックします
* アイテムの新規登録画面が表示されるので、以下の項目を入力します

![202504_205508.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/86477a19-4d39-43de-8c6b-3b287371d938.png)

　名前：TCP Connections HTTP
　キー：my.tcp.connection.count[80]

下段の [追加] をクリックして、登録完了です。

## 他のポートの監視

入力欄「キー」の各カッコ内で任意のポート番号を指定できますので、監視したいポートの数だけ同様に追加します。
またポート番号を空欄にすればすべての TCP 接続数をカウントできます。

![202504_205851.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/1d8d50fa-fadf-4bf6-a4b9-cedc6b2da0d2.png)


## トリガーの追加

追加した監視項目が一定値を超えたらアラートを発生する、簡単なトリガーを設定してみます。

* 左ペインのメニューから 設定 > ホスト とクリックし、対象ホスト行の `トリガー` をクリックします
* 右ペイン上部の [トリガーの作成] をクリックします
* トリガーの新規登録画面が表示されるので、以下の項目を入力します

![202504_214542.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/02e44c83-16a7-46d2-a2b4-d8dcdc3fcd7f.png)

　名前：TCP Connection HTTP {HOST.CONN}
　深刻度：警告
　条件式：条件式欄はビルダーがあり、以下の方法で使います

[追加] ボタンをクリックし、トリガー条件式ダイアログを開いて、以下の項目を入力します。

![202504_214632.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/561ad224-caab-4726-ba73-6b9d560fd268.png)

　アイテム：TCP Connections HTTP
　関数：last() - 最新値
　結果：`>` 100

[挿入] をクリックしてダイアログを閉じ、[追加] をクリックして決定します。

これで完了です。

![202504_174429.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/a3a09e07-9199-44e8-a61d-4ebe16d7ad49.png)



# テスト

ブラウザでアクセスしただけでは、とてもスレッショルドを超えられないと思うので、ここでは、apache httpd に付属する `ab` コマンドを使ってみます。

```
ab -n 100 -c 100 http://192.168.108.61/
```

しばらく待つと、以下の通り警告が発生し、正常な動作が確認できました。

![202504_175155.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/c6485260-c449-4165-9a9e-140be150685e.png)


# おわりに

今回は、クライアントでコマンドを実行して、任意の監視項目を作ることをやってみました。今回の接続数の監視では、ESTABLISHED 状態だけでなく、FIN_WAIT 等もカウントされます。これが望ましくない場合は、コマンド列の設計でアレンジできます。このように、とても応用範囲が広い方法です。