icmpping[]キーとSourceIPの困った仕様【MIRACLE ZBX 1.8, 2.0, 2.2】
icmpping[]キーの動作
icmppingキーは、外部のfping, fping6コマンドを使用することにより、指定したIPアドレス、もしくはホストに対しての死活監視を行うことができます。
fpingコマンドは、IPv4用、fping6はIPv6用となっています。
icmpping[]キーの実装調査
お客様からの調査依頼の過程でicmpping[]キーの実装調査を行いました。そのお客様はIPv6での監視を行いたいとのことで、様々なキー等に対して調査を行った ようですが、icmpping[]キーがIPv6での監視を行うことができないとのことでした。
icmpping[]キーによる監視は、Pingerプロセスにより行われます。
Pingerプロセスの大元は、src/zabbix_server/pinger/pinger.c に記述されており、main_pinger_loop()から
process_pinger_hosts()
→ src/zabbix_server/pinger/pinger.c : do_ping()
→ process_ping()
とコールしています。このprocess_ping()に主だったコードが記述されています。
実装のよくないコードがある
調査を進めていったところ、process_ping()によくない実装がありました。
下記は、MIRACLE ZBX-2.2.9-3のコードとなります。2.0.x, 1.8.xの最新版も同様な実装となっています。
183 #ifdef HAVE_IPV6
184 if (NULL != CONFIG_SOURCE_IP)
185 {
186 if (SUCCEED != get_address_family(CONFIG_SOURCE_IP, &family, error, max_error_len))
187 return ret;
188
189 if (family == PF_INET)
190 {
191 if (0 == (fping_existence & FPING_EXISTS))
192 {
193 zbx_snprintf(error, max_error_len, "File '%s' cannot be found in the system.",
194 CONFIG_FPING_LOCATION);
195 return ret;
196 }
197
198 zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING_LOCATION, params, filename);
199 }
200 else
201 {
202 if (0 == (fping_existence & FPING6_EXISTS))
203 {
204 zbx_snprintf(error, max_error_len, "File '%s' cannot be found in the system.",
205 CONFIG_FPING6_LOCATION);
206 return ret;
207 }
208
209 zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING6_LOCATION, params6, filename);
210 }
211 }
212 else
213 {
214 offset = 0;
215
216 if (0 != (fping_existence & FPING_EXISTS))
217 offset += zbx_snprintf(tmp + offset, sizeof(tmp) - offset,
218 "%s %s 2>&1 <%s;", CONFIG_FPING_LOCATION, params, filename);
219
220 if (0 != (fping_existence & FPING6_EXISTS))
221 zbx_snprintf(tmp + offset, sizeof(tmp) - offset,
222 "%s %s 2>&1 <%s;", CONFIG_FPING6_LOCATION, params6, filename);
223 }
224 #else
l.184にて、CONFIG_SOURCE_IP(zabbix_server.confに設定したSourceIP)がNULLでないかどうかを判定します。
NULLでない場合、l.186にてCONFIG_SOURCE_IPに設定したIPのタイプ判別をget_address_family()を用いて行っています。これは、PF_INETかPF_INET6を返すと考えてください。
そして、PF_INETのとき(IPv4アドレスのとき) fping を用いた監視を行い、そうでないとき fping6 を用いるようになっています。
また、l.184の判定でNULLのときは、l.212からのブロックに入り、fping, fping6の両方を試すようになっています。
fping, fping6コマンドの挙動
fping, fping6コマンドについてですが、これらはIPv4, IPv6のアドレスしかそれぞれ受け付けません。IPv6, IPv4のアドレスを与えた場合、失敗します。
全体を悪い方向に組み合わせると…
以上のことを下記のような設定の組み合わせで使用してみます。
- SourceIPにIPv4アドレスを指定する。
- 監視対象にIPv6アドレスを指定する。
SourceIPにIPv4アドレスが指定されることにより、fpingコマンドを用いることになります。しかしながら、監視対象のアドレスがIPv6であるため、監視が成功しません。
これを回避するためには、SourceIPをIPv6アドレスにするか、設定しないかにするしかありません。が!他の監視設定で、SourceIPをIPv4アドレスにしなくてはならない状況も考えられ、そのときは回避のしようがありません。
そもそもとして、Timeoutの設定もそうですが、Zabbixでは監視対象に応じて細かく設定できないことがあまりよくないと考えられます。
今回のケースならば、PingerSourceIPのような設定項目があってもよいと思います。
ちなみに、fpingコマンドにバグがありますので、当社が提供している最新版を使用してください。