Amazon Linux上でnginx⇒fluentd⇒Amazon Elasticsearch Service

2016年8月現在の情報です。

fluentdのバージョンが古かったり（型まわりとか）、前提が複雑だったり、おびたすき状態だったので、色々調べながら動くようになるまでのメモです。自分用なので端折ってます。

# nginx

## インスタンス
Amazon Linux AMI 2016.03.3 (HVM), SSD Volume Type - ami-374db956
t2.micro（無料利用枠の対象）
SSH MyIP
HTTP AllIP
その他デフォルト

Puttyにキーファイル設定
ログインユーザ名はec2-userね。いつも忘れるのでメモ……

## Amazon Linux 初期設定
http://qiita.com/yangci/items/ef2ab9b6f0d28bad0881
※この中の一部のみ反映

## ネットワーク回りの制限緩和
```bash:コンフィグファイル
$ sudo sysctl -w net.ipv4.ip_local_port_range="18000 65535"
net.ipv4.ip_local_port_range = 18000 65535
$ sudo sysctl -w net.core.somaxconn=65535
net.core.somaxconn = 65535
```

## nginxのインストール
```bash:インストール
$ sudo yum install nginx
```

## nginxの設定
```bash:コンフィグファイル
$ sudo vi /etc/nginx/nginx.conf
```
ソースからとか、リポジトリ入れたりとか、バージョン指定したりとか、色々な情報あったんですけど、yum一発で行けました。

設定内容は以下の通り。

冒頭のeventsブロックは以下の通り、パフォーマンス対策を入れる。

```bash:/etc/nginx/nginx.conf
events {
    worker_connections 10240;
    accept_mutex_delay 100ms;
}
```

httpブロックは、ログフォーマット部分を以下のように変更する。
デフォルトフォーマットはコメントアウトしています。
ログフォーマットは公式サイトの推奨通り。
nginxのバージョン情報は出さないようにした。
ファイルキャッシュも有効にしています。

```bash:/etc/nginx/nginx.conf
#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
#                  '$status $body_bytes_sent "$http_referer" '
#                  '"$http_user_agent" "$http_x_forwarded_for"';
#access_log  /var/log/nginx/access.log  main;

log_format ltsv "time:$time_local"
                "\thost:$remote_addr"
                "\tforwardedfor:$http_x_forwarded_for"
                "\treq:$request"
                "\tstatus:$status"
                "\tsize:$body_bytes_sent"
                "\treferer:$http_referer"
                "\tua:$http_user_agent"
                "\treqtime:$request_time"
                "\tcache:$upstream_http_x_cache"
                "\truntime:$upstream_http_x_runtime"
                "\tvhost:$host";
access_log  /var/log/nginx/access.log  ltsv;
server_tokens off;
open_file_cache max=100 inactive=20s;
```

ファビコンまわり。
これやらないと、faviconのワーニングがアクセスログに残ります……

```bash:/etc/nginx/nginx.conf
#server {...}の中に以下を追加。

location /favicon {
    empty_gif;
    access_log    off;
    log_not_found off;
}
```

## デフォルトページ削除
```bash:デフォルトページを削除
$ sudo vi /usr/share/nginx/html/index.html
```

以下のような内容に変更。

```bash:/usr/share/nginx/html/index.html
NOT FOUND
```

## fluentdのために権限解放

```bash:
$ sudo chmod o+x /var/log/nginx
```

これやっておかないと、td-agentのログがエラーだらけになります。

## 起動設定

```bash:
$ sudo chkconfig --add nginx
$ sudo chkconfig nginx on
$ sudo /etc/init.d/nginx start
```

## いちおうベンチ

```bash:
$ wrk -t10 -c100 -d10s http://localhost/index.html
Running 10s test @ http://localhost/index.html
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   170.68ms  230.16ms 828.58ms   79.39%
    Req/Sec     2.46k     2.45k    9.26k    83.95%
  136546 requests in 10.03s, 30.99MB read
Requests/sec:  13609.18
Transfer/sec:      3.09MB
```

microのインスタンスでも意外といけますね。
外からのアクセスだと、ボトルネックが別にあるのかもですけど……

# Amazon Elasticsearch Service

## インスタンス
ドメイン名
Ver2.3
t2.micro（無料利用枠の対象）
Enable dedicated master
  t2.micro x 3（これは有料）
EBS SSD 10GB
policy IP

## 設定
アクセスポリシーをIPにするのが最もシンプルなようです。
登録するIPアドレスは以下の2つ。

**最初に作ったnginxが動作しているサーバのグローバルIP**
これがないとtd-agentからのPOSTがForbiddenになります。

**管理者のグローバルIP**
これがないとKIBANAにアクセスできなくなります。

# fluentd（td-agent）

## td-agentのインストール
nginxのインスタンスに戻って、td-agentのインストールと設定を進めます。

```bash:インストール
$ sudo curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sh
$ sudo td-agent-gem install fluent-plugin-elasticsearch
$ sudo td-agent-gem install fluent-plugin-woothee
```

最後のwootheeはUserAgent用です。入れなくてもOKです。
実際、この先の設定でも使っていません……

## td-agentの設定

```bash:コンフィグファイル
$ sudo vi /etc/td-agent/td-agent.conf
```

サンプルの内容は全て消して、以下に上書き。

```bash:/etc/td-agent/td-agent.conf
<source>
    type tail
    path /var/log/nginx/access.log
    pos_file /var/log/td-agent/buffer/api.access.log.pos
    format ltsv
    time_format %d/%b/%Y:%H:%M:%S %z
    types size:integer, status:integer, reqtime:float, runtime:float, time:time
    tag nginx.access
</source>
 
<match nginx.access>
    type_name nginx
    type elasticsearch
    include_tag_key true
    tag_key @log_name
    host search-elasticsearch-(>_<).amazonaws.com
    port 443
    scheme https
    logstash_format true
    flush_interval 10s
    retry_limit 5
    buffer_type file
    buffer_path /var/log/td-agent/buffer/casted.nginx.access.buffer
    ##############################################################
    #!!! DO NOT SET THIS PROPERTY TO true FOR Amazon Elasticsearch Service !!!
    #Elasticsearch service doesn't return addresses of nodes and Elasticsearch client
    #fails to reload connections properly.
    ############################################################
    reload_connections false
</match>
```

hostのところの、
**search-elasticsearch-(>_<).amazonaws.com**
には、先ほど作成したElasticSearch ServiceのEndpointに表示されているURLを入れます。

## td-agentの起動

```bash:
$ sudo chkconfig --add td-agent
$ sudo chkconfig td-agent on
$ sudo /etc/init.d/td-agent start
```

これで、nginxのページをブラウザで開くと、KIBANAでログが見られるようになります。
だいたい10秒前後のディレイがあります。

# まだ分からないところ
##fluentd⇒ElasticSearchの型が合わない
最近のバージョンだとコンフィグファイルのTYPESで型の指定ができるんですけど、ログファイルの数字部分について、integerを指定するとKIBANA側ではStringになってしまいます。floatだとNumberになってくれるので、今のところ数値は全てfloatに指定しています。なんか気持ち悪い……

##fluentdが良くわからない
そもそもなんですけど、例えばGETのパラメータのquerystringsから指定の変数を抜き出して、KIBANAで扱いたいって思っていたんですけど、そもそもどのレイヤで実装するのが良いのかってことで、fluentdあたりでやってみようかなって思ったんですが、やり方が分からない……　仕方がないのでとりあえずはnginxのコンフィグで正規表現使って抜き出して、アクセスログの1カラムとして出力するようにしておきました。