やりたいこと
大量のTrapを受信するsnmptrapdの負荷を軽減するため、
負荷分散と送信元IPアドレス別の流量制御を行いたい。
BIG-IP等の高級品を使わず最近マイブームのNginxで無料でやりたい。
nginx.conf
stream {
limit_req_zone $binary_remote_addr zone=snmp_zone:5m rate=10r/s;
limit_req zone=snmp_zone burst=30 nodelay;
server {
listen 162 udp
proxy_pass snmptrapd-server;
}
upstream snmptrapd-server {
server snmptrapd-server-1:162;
server snmptrapd-server-2:162;
}
}
これで行ける…?
※ダメでした。上記configは利用できません。
検証
検証用環境を既存のDockerImageを使ってサクッと作成。
version: '3.3'
services:
snmptrapd-1:
container_name: snmptrapd-server-1
image: sig9/snmptrapd:latest
snmptrapd-2:
container_name: snmptrapd-server-2
image: sig9/snmptrapd:latest
nginx-snmptrap:
container_name: nginx-snmptrap
image: nginx:latest
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
trap-sender:
image: elcolio/net-snmp:latest
command:
- /bin/bash
- -c
- 'sleep 5; for i in `seq 1 10` ; do snmptrap -v 2c -c public nginx-snmptrap "" linkDown ; done'
depends_on:
- snmptrapd-1
- snmptrapd-2
実行結果
nginx-snmptrap | 2023/02/07 23:56:53 [emerg] 1#1: "limit_req_zone" directive is not allowed here in /etc/nginx/nginx.conf:14
nginx-snmptrap | nginx: [emerg] "limit_req_zone" directive is not allowed here in /etc/nginx/nginx.conf:14
limit_req_zoneディレクティブはここ(streamコンテキスト)に書くのダメだよ とのこと。
Module ngx_http_limit_req_module (nginx.org)
不勉強でした。limit_reqモジュールはhttpコンテキスト内のみで有効でした。
streamコンテキスト内で利用できるlimit_reqのモジュールを探したが、見つからず。
モジュールを自作するか、別で流量制御するアプリケーション挟むかしかなさそう。
limit_reqを外せば、ちゃんと動くので負荷分散は問題なくできた。
snmptrapd-server-1 | 2023-02-08 00:22:03 nginx-snmptrap.20230207snmptrapdtest_default [UDP: [10.220.8.2]:37611->[10.220.8.4]:162]:
snmptrapd-server-1 | DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (56492540) 6 days, 12:55:25.40 SNMPv2-MIB::snmpTrapOID.0 = OID: IF-MIB::linkDown
snmptrapd-server-2 | 2023-02-08 00:22:03 nginx-snmptrap.20230207snmptrapdtest_default [UDP: [10.220.8.2]:54096->[10.220.8.3]:162]:
snmptrapd-server-2 | DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (56492542) 6 days, 12:55:25.42 SNMPv2-MIB::snmpTrapOID.0 = OID: IF-MIB::linkDown
snmptrapd-server-1 | 2023-02-08 00:22:03 nginx-snmptrap.20230207snmptrapdtest_default [UDP: [10.220.8.2]:54507->[10.220.8.4]:162]:
snmptrapd-server-1 | DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (56492544) 6 days, 12:55:25.44 SNMPv2-MIB::snmpTrapOID.0 = OID: IF-MIB::linkDown
ちゃんとラウンドロビンで振り分けされている。
ただし、送信元IPがnginxサーバになってるので監視で使うには、使いづらい。
流量制御できないのも相まって、nginxでsnmptrap扱うのは、
向いていない(そもそもhttpサーバだし)ので、新しくアプリケーション作ってみましょうか、となった。