ELBのアクセスログをfluentd(fluent-plugin-elb-access-log)+Elasticsearch+kibanaで可視化する

ELBログを解析する機会が多くなりました。。。

```
$sed -e 's/:[0-9][0-9]\.[0-9][0-9][0-9][0-9][0-9][0-9]Z//g' access.log |awk -F " " '{ print $1,$8; }'| sort | uniq -c
```

のようなコマンドを作って解析しても良いのですが、色々面倒なので、よくあるツール群を使って可視化します。


# 構成

+ Amazon Linux AMI 2015.03 (HVM)(S3へのRead権限を持ったIAMRoleが設定されていること)
+ td-agent-2.2.0-0.x86_64
+ ElasticSearch-1.4.5
+ nginx-1.6.2-1.23.amzn1.x86_64
+ Kibana3.1.2

なお、ELBのアクセスログは事前に有効にしておくこと。

# 参考

+ [ELBのアクセスログをfluent-plugin-elb-logを使ってkibanaで表示する](http://dev.classmethod.jp/cloud/aws/fluent-plugin-elb-log-to-kibana/)
+ [ELB s3 Log + Fluentd + Elasticsearch + Kibana + Ubuntu 14.04 LTS PV + EC2 on AWS](http://qiita.com/kiyotaman/items/6021c0794185065dd0ca)
+ [[技術ブログVol.11] ELBのアクセスログをfluentd+Elasticsearch+kibanaで解析](http://www.denet.ad.jp/technology/2014/04/vol11-elbfluentdelasticsearchkibana.html)
+ [fluent-plugin-elb-access-logを作った](http://so-wh.at/entry/2015/05/24/fluent-plugin-elb-access-log%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%9F)
+ [fluentd-v2+elasticsearch+kibana3をEC2上で実施する](http://toshihirock.blogspot.jp/2015/04/fluentd-v2elasticsearchkibana3ec2.html)

# nginx

インストール、サービス起動、自動起動設定をします

```
$sudo yum install nginx
$sudo service nginx start
$sudo chkconfig --add nginx
```

# fluentd

インストール、サービス自動起動設定

```
$curl -L http://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sudo sh
$sudo chkconfig --add td-agent
```

ELBのアクセスログを取得するために[fluent-plugin-elb-access-log](https://github.com/winebarrel/fluent-plugin-elb-access-log)をインストールし、elastcisearchへ登録するために[fluent-plugin-elasticsearch](https://github.com/uken/fluent-plugin-elasticsearch)をインストールします。また、事前に必要なパッケージ群もインストールしておきます。


```
$sudo yum groupinstall 'Development tools'
$sudo yum install curl-devel
$sudo /opt/td-agent/embedded/bin/fluent-gem install fluent-plugin-elasticsearch
$sudo /opt/td-agent/embedded/bin/fluent-gem install fluent-plugin-elb-access-log
```

# ElasticSearch

GPG-KEYの追加

```
$sudo rpm --import https://packages.elasticsearch.org/GPG-KEY-elasticsearch
```

リポジトリの追加のために下記ファイルを作成。

```lang:/etc/yum.repos.d/elasticsearch.repo
[elasticsearch-1.4]
name=Elasticsearch repository for 1.4.x packages
baseurl=http://packages.elasticsearch.org/elasticsearch/1.4/centos
gpgcheck=1
gpgkey=http://packages.elasticsearch.org/GPG-KEY-elasticsearch
enabled=0
```

インストール、サービス起動、自動起動設定

```
$sudo yum --enablerepo=elasticsearch-1.4 install elasticsearch
$sudo chkconfig --add elasticsearch
$sudo service elasticsearch start
```

起動したクラスタを確認

```
$curl -s -XGET http://localhost:9200/_cluster/health | jq .
{
  "cluster_name": "elasticsearch",
  "status": "green",
  "timed_out": false,
  "number_of_nodes": 1,
  "number_of_data_nodes": 1,
  "active_primary_shards": 0,
  "active_shards": 0,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 0
}
```

# ELBのログをfluentdで取得

**fluent-plugin-elb-access-log**を使って、ELBのログを取得します。

```lang:/etc/td-agent/td-agent.conf
<source>
  type elb_access_log
  account_id 111111
  region ap-northeast-1
  s3_bucket toshihirock-elb-test
  tag elb.access_log
  debug true
</source>

<match **>
  type stdout
</match>
```

各設定の詳細及びオプションは[fluent-plugin-elb-access-log](https://github.com/winebarrel/fluent-plugin-elb-access-log)のREADME参照のこと。

確認のためトレースモードで起動します。


```
$sudo td-agent -vv &
```

この状態でELBのURLにアクセスし、少し待ちます。
うまくいっていると標準出力にログが表示されるのが確認できるのですが、以下の証明書エラーとなってしまいました。。。

```
before_shutdown failed error="SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed"
```

こちらの問題の調査、解決方法は以下にまとめました。

[fluentdのプラグインでcertificate verify failedエラーが発生した話](http://qiita.com/toshihirock/items/ce85c5b66b0236839ec0)

詳細は上記を見ていただくということでこちらは最終的な対応方法である証明書の差し替えのみ行います。

```
# AmazonLinuxの証明書の位置を確認
$ruby -ropenssl -e 'puts OpenSSL::X509::DEFAULT_CERT_FILE'
/etc/pki/tls/cert.pem
# バックアップ
$cp /opt/td-agent/embedded/ssl/cert.pem /opt/td-agent/embedded/ssl/cert.pem.original
# 差し替え
$cp /etc/pki/tls/cert.pem /opt/td-agent/embedded/ssl/cert.pem
```

一度、td-agentのプロセスをkillして再度実行します。

```
$ps aux|grep ruby|awk '{print $2;}'|sudo xargs kill -KILL
$sudo td-agent -vv &
```

再度ELBのサイトにアクセスし、5分ほど待ちます。
問題なく解析できていれば、ログが出力されます。

```
2015-05-30 09:58:23 +0000 elb.access_log: {"timestamp":"2015-05-30T09:58:23.682447Z","elb":"LoadBlancer","client_port":3781,"backend_port":80,"request_processing_time":4.2e-05,"backend_processing_time":0.000791,"response_processing_time":2.7e-05,"elb_status_code":404,"backend_status_code":404,"received_bytes":0,"sent_bytes":3696,"request":"GET http://fuga:80/manager/html HTTP/1.1","client":"boyo","backend":"hoge","request.method":"GET","request.uri":"http://hogefuga:80/manager/html","request.http_version":"HTTP/1.1","request.uri.scheme":"http","request.uri.user":null,"request.uri.host":"abcd","request.uri.port":80,"request.uri.path":"/manager/html","request.uri.query":null,"request.uri.fragment":null}
```

確認が終わったのでプロセスは終了します。

```
$ps aux|grep ruby|awk '{print $2;}'|sudo xargs kill -KILL
```
# ELBのログをElasticSearchに保存する

fluentdの設定にelasticsearchに関する内容を追記して、ELBのログを保存するようにします。

```lang:/etc/td-agent/td-agent.conf
<source>
  type elb_access_log
  account_id 11111111
  region ap-northeast-1
  s3_bucket toshihirock-elb-test
  tag elb.access_log
  debug true
</source>

<match elb.access_log>
  type elasticsearch
  type_name access_log
  host localhost
  port 9200
  logstash_format true
  include_tag_key true
  tag_key @log_name
</match>
```

サービス起動。

```
$sudo service td-agent start
```

ELBサイトにアクセスし、ログを確認しておきます。

```
$tail -f  /var/log/td-agent.log
```

５分ぐらい経過すると以下のようなログが流れます。

```
2015-05-29 14:51:19 +0000 [info]: Connection opened to Elasticsearch cluster => {:host=>"localhost", :port=>9200, :scheme=>"http"}
```

ElastciSearchに本当に登録されているか確認します。
まず、現在存在するインデックス情報一覧を取得します。

```
$curl -XGET http://localhost:9200/_aliases?pretty
```

結果。

```
{
  "logstash-2015.05.29" : {
    "aliases" : { }
  },
  "logstash-2015.05.30" : {
    "aliases" : { }
  }
}
```

5月30日の方を確認します。もしjqを事前にインストールしていない場合、`sudo yum install jq`を実施するか、パイプ以降のコマンドを削除してください。

```
$curl -XGET http://localhost:9200/logstash-2015.05.30/_search -d '
{
  "query": {
    "match_all" : {}
  }
}' | jq .
```

結果

```

  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 18,
    "max_score": 1,
    "hits": [
      {
        "_index": "logstash-2015.05.30",
        "_type": "access_log",
        "_id": "hogefuga",
        "_score": 1,
        "_source": {
          "timestamp": "2015-05-30T10:34:08.552001Z",
          "elb": "LoadBlancer",
          "client_port": 54931,
          "backend_port": 80,
          "request_processing_time": 5.1e-05,
          "backend_processing_time": 0.00074,
          "response_processing_time": 2.1e-05,
          "elb_status_code": 304,
          "backend_status_code": 304,
          "received_bytes": 0,
          "sent_bytes": 0,
          "request": "GET http://loadblancer-11111.ap-northeast-1.elb.amazonaws.com:80/ HTTP/1.1",
          （以下略)
```

無事登録されていました。

# kibana

kibanaのインストール及び配置。

```
$wget https://download.elastic.co/kibana/kibana/kibana-3.1.2.tar.gz
$tar -zxvf kibana-3.1.2.tar.gz
$mv kibana-3.1.2 kibana
$sudo mv kibana /usr/share/nginx/html
```

elasticsearch1.4からセキュリティ向上が目的で設定が追加で必要になったようで、それを追加します。

```
$sudo vi /etc/elasticsearch/elasticsearch.yml 
```

以下を末尾に追加

```lang:/etc/elasticsearch/elasticsearch.yml
http.cors.allow-origin: "/.*/"
http.cors.enabled: true
```


また、SecurityGroupで80番と9200番のポートが空いているか確認します。9200番はKibana が検索クエリを投げるポートのようです。

elasticsearch,nginxの再起動

```
$sudo service elasticsearch restart
$sudo service nginx restart
```

この状態で **http://[hostname]/kibana/** にアクセスすることで画面が表示されました。