LoginSignup
5
2

More than 5 years have passed since last update.

Fluentdのin_httpプラグインでJSONを受け取るときのTip

Last updated at Posted at 2017-11-29

はじめに

fluentdのin_httpプラグインを使うと、一般的なHTTP POSTメソッドでJSONを投げ込むことでfluentdにデータを送ることができます。
その時に微妙に引っかかった点について書いていきます。

なお、ここではtd-agent-2.3.6-0.el6.x86_64を使用したときの話を書いているので後継バージョンで異なる可能性があります。

in_httpプラグインについて

ビルトインに含まれるプラグインで、HTTPで投げ込めます。

<source>
  @type http
  port 9880
  bind 0.0.0.0
  body_size_limit 32m
  keepalive_timeout 10s
  add_remote_addr true
</source>

上記のような設定時は以下のように投げ込むことでデータを入れられます。

curl -X POST -d 'json={"message":"TEST","user":"cuturn"}' http://example.com:9880/fluentd.tag.to -v

ポイントは、json={JSON} という形で投げ込むことです。また、in_httpプラグインはin_tailやin_tcpと違ってタグを送り元が決めることができることがポイントです。特にヘッダを指定する必要はありません。

ただし、上記設定はJSONデータ部分が誤っていても200OKが返ってしまうという問題があります。

普通にやるとJSONが間違っててもエラーを返さないので、少し設定を修正しましょう

通常通りの設定で動かすと、実はJSON文字列が多少間違っててもエラーレスポンスを返しません。json={}の形でさえあれば、200OKを返します。これはデバッグ上非常に宜しくありません。またlog_level debugとしたとしても、何のログもでてきません。

そこで、以下のようにformatを指定します。

<source>
  @type http
  port 9880
  bind 0.0.0.0
  body_size_limit 32m
  keepalive_timeout 10s
  add_remote_addr true
  format json
</source>

上記のように設定すると、以下のようなCURLで投げ込むことができます。json=は不要になりました。

curl -X POST -d '{"message":"TEST","user":"cuturn"}' http://example.com:9880/fluentd.tag.to -v

間違ったJSONを送った場合は、送信コマンド/応答含めて以下のような感じになります。

$ curl -X POST -d '{"message":"TEST","user":"cuturn",}' http://example.com:9880/fluentd.tag.to -v
...
> POST /log HTTP/1.1
> Host: example.com:9880
> User-Agent: curl/7.56.1
> Accept: */*
> Content-Length: 35
> Content-Type: application/x-www-form-urlencoded
>
...
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 400 Bad Request
< Content-Type: text/plain
< Connection: Keep-Alive
< Content-Length: 80
<
400 Bad Request
Received event is not json: {"message":"TEST","user":"cuturn",}
* STATE: PERFORM => DONE handle 0x600057950; line 1993 (connection #0)
* multi_done
* Connection #0 to host example.com left intact
* Expire cleared

というわけで、必ず安定してjsonを送れる自信があるならいいですが、フォーマット間違えたときにきちんと失敗した旨受け取りたい場合はformatを指定するよう設定しましょう。

HTTPS化したいとき

HTTPSで受け取りたい場合は、同サーバ上にNginxを立ててリバースプロキシするのがオススメになります。以下のような設定を/etc/nginx/conf.d/に置くことで、Nginx経由でfluentdへの通信が通るようになります。cipherとかログ設定とかSSLとかは適宜どうにかしてください。

### /etc/nginx/conf.d/fluentd.conf
server {
    listen                      443;
    server_name                 example.com;

    ssl                         on;
    ssl_certificate             /etc/nginx/ssl/server.crt;
    ssl_certificate_key         /etc/nginx/ssl/server.pem;
    ssl_protocols               TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers                 HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers   on;

    #charset koi8-r;
    access_log  /var/log/nginx/fluentd.access.log  main;

    location / {
        proxy_set_header Host             $host;
        proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_pass http://localhost:9880/;
    }
}

なお、X-Forwarded-Forヘッダを設定することでFluentdはREMOTE_ADDRフィールドにこのヘッダ内容を入れてくれます。これでばっちり送信元情報が使えます。BIG-IPや他のLoadBalancerを導入する場合も、同じ考え方をしてください。

またin_httpプラグインはtd-agent.logにアクセスログを出してくれないので、アクセスログが欲しいというだけであったとしてもNginxを立ててリバースプロキシする価値はあるかもしれません。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2