Fluentdから#SORACOM Funnel経由でAmazon Kinesis Firehoseにログを送信する
ども、大瀧です。
SORACOMから発表された新サービスFunnelは、IoTデバイスの通信をバックエンドのクラウドサービスに転送します。今回は、IoTデバイスからの通信として、Fluentd(td-agent)からKinesis Firehoseへの転送を試してみます。
Fluentdとは
Fluentdは、ログなどのデータ収集ソフトウェアとして広く用いられているOSSです。手軽に導入するために、開発主体のTreasure Data社が提供するtd-agentディストリビューションを利用するのが一般的です。 *1
Kinesis Firehoseとは
Kinesis Firehoseは、AWSのマネージドなストリーミング基盤サービスの一つで、簡単にS3やRedshiftへのデータ格納を行うことができます。
SORACOM Funnelなしでも、FluentdにはKinesis Firehoseプラグイン *2があるのですが、IoTデバイス全台にAWSのAPIキーを配置するのは、運用コストと盗難のリスクから難しいケースもあると思います。
SORACOM FunnelのKinesis Firehose Adapterを利用することで、AWS APIキーをアダプタに設定し、IoTデバイスからFunnelへはAPIキーなしのTCP/UDP/HTTPのいずれかのリクエストでFirehoseへのPutRecordが可能になります。こうすることで、IoTデバイスにAPIキーを配置する必要がなくなるわけです。
では、設定していきます。
Fluentd(td-agent)の設定
動作確認環境
- OS : Ubuntu Server Trusty 64bit
- td-agent : バージョン2.3.0
今回は、fluent-plugin-out-httpプラグインを利用しHTTPでFunnelへのログ送信を構成します。まずはtd-agentとfluent-plugin-out-httpプラグインをインストールします。
$ curl -L https://toolbelt.treasuredata.com/sh/install-ubuntu-trusty-td-agent2.sh | sh :(略) $ sudo td-agent-gem install fluent-plugin-out-http :(略) $
今回はApacheのアクセスログを転送するので、以下のようにtd-agent.conf
を設定しました。
<source> @type tail path /var/log/apache2/access.log pos_file /var/log/td-agent/httpd-access.log.pos tag apache.access format apache2 </source> <match **> type http endpoint_url http://funnel.soracom.io/ http_method post # default: post serializer json # default: form rate_limit_msec 100 # default: 0 = no rate limiting raise_on_error false # default: true </match>
- 115行目 : ここからfluent-plugin-out-httpの設定
- 117行目
endpoint_url
: Funnelのエンドポイント(funnel.soracom.io
)を指定 - 118行目
http_method
: Funnelが許容するHTTPメソッドの記述がドキュメントに見当たらないため、Getting Startedの例に従いPOSTにしておく - 119行目
serializer
: FunnelへのHTTPリクエストは現時点でJSONフォーマットのみとのことなので、json
をセットしておく
これでOKです。/var/log/apache2/
および/var/log/apache2/access.log
のパーミッションに注意しつつ、td-agentを実行しましょう。
Firehoseの構成
清野のエントリーと同じ構成でオレゴンリージョンに作成しました。Firehoseのデリバリーストリーム名、AWSリージョン名とIAMユーザーのAPIキー、シークレットキーを控えておきましょう。
Funnelの構成
SORACOMユーザーコンソールには、Funnelの設定画面に加えてFunnelリリース当初は無かった認証情報ストアの画面が追加されたので、今回はこれらを利用してみます。
ユーザーコンソールのメニューから[セキュリティ] - [認証情報ストア]をクリックし、[+ 認証情報を登録]ボタンをクリックします。
適当な[認証情報ID]を入力しつつ、[種別]を「AWS認証情報」、[AWS Access Key ID]、[AWS Secret Access Key]にAPIキー、シークレットキーそれぞれをペーストし、[登録]をクリックします。
続いて、FunnelはSIMグループ単位で設定するため、[グループ]メニューからグループを選択、[SORACOM Funnel設定]のアコーディオンメニューを開きます。
[ON]に切り替え、[リソースタイプ]から「Amazon Kinesis Firehose」、[リソースURL]は「https://firehose.<リージョン名>.amazonaws.com/<デリバリーストリーム名>
」の規則で入力、[認証情報]は先ほど登録した認証情報IDを選択し、[保存]をクリックします。
これで準備OKです。デバイス上でcurl localhost
などを実行しアクセスログを出すと、Funnel→Firehose→S3とログが転送されていきます。Firehoseは転送するデータがある程度溜まるまでバッファリングするので、アクセスログを貯めるかしばらく待ってからS3バケットを確認しましょう。以下のようにファイルが格納されていれば正常に動作しています。
ファイルの中身は以下のようになっていました。
{"operatorId": "OP0123456789", "timestamp": 1454034500854, "destination": {"resourceUrl": "https://firehose.us-west-2.amazonaws.com/takipone-test", "service": "firehose", "provider": "aws"}, "credentialsId": "otaki-funnel-firehose", "payloads": {"code": 200, "agent": "curl/7.35.0", "host": "127.0.0.1", "referer": null, "user": null, "path": "/", "method": "GET", "size": 11764}, "sourceProtocol": "http", "imsi": "XXXXXXXXXXXXXXXX"} {"operatorId": "OP0123456789", "timestamp": 1454034501314, "destination": {"resourceUrl": "https://firehose.us-west-2.amazonaws.com/takipone-test", "service": "firehose", "provider": "aws"}, "credentialsId": "otaki-funnel-firehose", "payloads": {"code": 200, "agent": "curl/7.35.0", "host": "127.0.0.1", "referer": null, "user": null, "path": "/", "method": "GET", "size": 11764}, "sourceProtocol": "http", "imsi": "XXXXXXXXXXXXXXXX"} {"operatorId": "OP0123456789", "timestamp": 1454034501726, "destination": {"resourceUrl": "https://firehose.us-west-2.amazonaws.com/takipone-test", "service": "firehose", "provider": "aws"}, "credentialsId": "otaki-funnel-firehose", "payloads": {"code": 200, "agent": "curl/7.35.0", "host": "127.0.0.1", "referer": null, "user": null, "path": "/", "method": "GET", "size": 11764}, "sourceProtocol": "http", "imsi": "XXXXXXXXXXXXXXXX"} {"operatorId": "OP0123456789", "timestamp": 1454034502242, "destination": {"resourceUrl": "https://firehose.us-west-2.amazonaws.com/takipone-test", "service": "firehose", "provider": "aws"}, "credentialsId": "otaki-funnel-firehose", "payloads": {"code": 200, "agent": "curl/7.35.0", "host": "127.0.0.1", "referer": null, "user": null, "path": "/", "method": "GET", "size": 11764}, "sourceProtocol": "http", "imsi": "XXXXXXXXXXXXXXXX"} {"operatorId": "OP0123456789", "timestamp": 1454034502694, "destination": {"resourceUrl": "https://firehose.us-west-2.amazonaws.com/takipone-test", "service": "firehose", "provider": "aws"}, "credentialsId": "otaki-funnel-firehose", "payloads": {"code": 200, "agent": "curl/7.35.0", "host": "127.0.0.1", "referer": null, "user": null, "path": "/", "method": "GET", "size": 11764}, "sourceProtocol": "http", "imsi": "XXXXXXXXXXXXXXXX"} {"operatorId": "OP0123456789", "timestamp": 1454034503106, "destination": {"resourceUrl": "https://firehose.us-west-2.amazonaws.com/takipone-test", "service": "firehose", "provider": "aws"}, "credentialsId": "otaki-funnel-firehose", "payloads": {"code": 200, "agent": "curl/7.35.0", "host": "127.0.0.1", "referer": null, "user": null, "path": "/", "method": "GET", "size": 11764}, "sourceProtocol": "http", "imsi": "XXXXXXXXXXXXXXXX"} {"operatorId": "OP0123456789", "timestamp": 1454034503846, "destination": {"resourceUrl": "https://firehose.us-west-2.amazonaws.com/takipone-test", "service": "firehose", "provider": "aws"}, "credentialsId": "otaki-funnel-firehose", "payloads": {"code": 200, "agent": "curl/7.35.0", "host": "127.0.0.1", "referer": null, "user": null, "path": "/", "method": "GET", "size": 11764}, "sourceProtocol": "http", "imsi": "XXXXXXXXXXXXXXXX"} {"operatorId": "OP0123456789", "timestamp": 1454034507992, "destination": {"resourceUrl": "https://firehose.us-west-2.amazonaws.com/takipone-test", "service": "firehose", "provider": "aws"}, "credentialsId": "otaki-funnel-firehose", "payloads": {"code": 200, "agent": "curl/7.35.0", "host": "127.0.0.1", "referer": null, "user": null, "path": "/", "method": "GET", "size": 11764}, "sourceProtocol": "http", "imsi": "XXXXXXXXXXXXXXXX"} {"operatorId": "OP0123456789", "timestamp": 1454034508734, "destination": {"resourceUrl": "https://firehose.us-west-2.amazonaws.com/takipone-test", "service": "firehose", "provider": "aws"}, "credentialsId": "otaki-funnel-firehose", "payloads": {"code": 200, "agent": "curl/7.35.0", "host": "127.0.0.1", "referer": null, "user": null, "path": "/", "method": "GET", "size": 11764}, "sourceProtocol": "http", "imsi": "XXXXXXXXXXXXXXXX"}
いい感じですね!payloads
以下がApacheログのデータ、それ以外はFunnelが付与したSIMに関する情報です。
まとめ
Fluentdのログ出力をSORACOM Funnel経由でKinesis Firehoseに転送する様子をご紹介しました。FunnelとFirehoseの組み合わせで、デバイス側のログ出力がすごく楽になる様子を感じていただけたのではないでしょうか。SORACOMのデータ転送料金が気になるのであれば、Funnel経由ではありませんがWi-Fiの固定回線とSORACOM Endorseの認証連携を組み合わせるのも面白いかもしれません。
脚注
- IoTデバイスによってはリソース面からRubyベースのFluentdの利用が難しいこともあるので、軽量版のFluentBitにHTTP Output Pluginがサポートされると今回の構成が試せるので誰か作ってくれないかなぁと思っています。 ↩
- 近々AWSオフィシャルのKinesisプラグインに統合される見通し ↩