VPN接続の帯域をCloudWatchでモニタしてみた
VPNコネクションの帯域は各種SNMP監視ツールでモニタするのがよいと思いますが、せっかくなのでCloudWatchの画面でも確認できるようにしてみました。
下準備
使用しているルータのトンネルインターフェースのindexを調べます。うちはSEILを使用していて、トンネルインターフェース名はそれぞれipsec0/1なので、
$ snmpwalk -v 2c -c public gw2 ifDescr | grep ipsec | head -2 IF-MIB::ifDescr.549 = STRING: ipsec0 IF-MIB::ifDescr.550 = STRING: ipsec1
549と550がそれぞれtunnel1と2のindexである事が分かりました。
あとは、ifInOctets(CustomerGatewayから見て受信なので、AWSから見てNetworkOut)やifOutOctets(同じくNetworkIn)のOIDが分かればOK。.1.3.6.1.2.1.2.2.1.10と.1.3.6.1.2.1.2.2.1.16がそれぞれ該当します*1。
次にそれらの値をCloudWatchのCustomMetricのどのNameSpace/Metric/Dimensionで書き出したいかをまとめます。
[ { "NameSpace":"VPC","MetricName":"NetworkOut","Dimension":{"TunnelName":"vpn-18943e19-1"}, "host":"192.168.1.254", "community":"public", "mib":".1.3.6.1.2.1.2.2.1.10.549" } , { "NameSpace":"VPC","MetricName":"NetworkIn","Dimension":{"TunnelName":"vpn-18943e19-1"}, "host":"192.168.1.254", "community":"public", "mib":".1.3.6.1.2.1.2.2.1.16.549" } , { "NameSpace":"VPC","MetricName":"NetworkOut","Dimension":{"TunnelName":"vpn-18943e19-2"}, "host":"192.168.1.254", "community":"public", "mib":".1.3.6.1.2.1.2.2.1.10.550" } , { "NameSpace":"VPC","MetricName":"NetworkIn","Dimension":{"TunnelName":"vpn-18943e19-2"}, "host":"192.168.1.254", "community":"public", "mib":".1.3.6.1.2.1.2.2.1.16.550" } ]
スクリプトを動かす
pythonのスクリプトを動かします。botoとpysnmpをpip等でインストールしておいてください。
かなり適当に書きなぐった(リージョンやコンフィグファイル名が決め打ちです)物ですので、気に入らないところは適宜修正してください。
環境変数やIAM Roleなどで認証情報が設定されている事が前提となります。
cron等で1分間毎に動かす事で、平均使用帯域(Mbps)をCloudWatchのCustomMetricとして記録します。/var/tmp/{OID} に前回の値を書き込むので注意です。
#!/usr/bin/env python # -*- coding: utf-8 -*- import boto.ec2.cloudwatch c = boto.ec2.cloudwatch.connect_to_region('ap-northeast-1') import json config=json.load(open("config.json")) from pysnmp.entity.rfc3413.oneliner import cmdgen cmdGen = cmdgen.CommandGenerator() for metric in config: try: f=open('/var/tmp/'+metric['mib'].encode('latin-1')) previous=int(f.read()) f.close() except: print "new mib" previous=0 errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( cmdgen.CommunityData(metric['community']), cmdgen.UdpTransportTarget((metric['host'], 161)), cmdgen.MibVariable(metric['mib'].encode('latin-1')), lookupNames=True,lookupValues=True ) if errorIndication: print(errorIndication) elif errorStatus: print(errorStatus) elif len(varBinds) != 1 : print("only 1 var is allowed") else: for name, val in varBinds: if previous == 0 : print('%s : %s (new)' % (metric['mib'], val.prettyPrint() )) else : diff=int(val)-previous if diff < 0: diff=diff + 4294967296 mbps=8.00*diff/(1024*1024)/60 print('%s : %s - %d = %d / 60 sec = %f Mbps' % (metric['mib'], val.prettyPrint(), previous, diff, mbps)) c.put_metric_data(metric['NameSpace'],metric['MetricName'],mbps,None,'Megabits/Second',metric['Dimension']) f=open('/var/tmp/'+metric['mib'].encode('latin-1'),'w') f.write(str(val)) f.close()
結果の確認
しばらく動かしてみて、グラフを確認します。
こんな感じに描画されます。
CloudWatchのデータは2週間しか保存されませんので、データ蓄積用というよりは状況の確認やアラーム用途といった所でしょうか。
*1:これらは32bitカウンタなのですが、64bitカウンタが使えるルータがあればそれを利用した方がよいと思われます