ELKスタックを活用したNginxログ収集とデータ分析

背景

フロントエンドのWebサーバーとしてNginxを採用し、filebeat + logstash + elasticsearch + grafanaを使用したデータ収集と可視化を実装します。これにより、クライアントIPの地域統計やサーバー応答時間の監視などが可能になります。

システム全体のアーキテクチャ

Nginxログ出力 → Filebeat → Logstash → Elasticsearch → Grafana(表示)

準備条件

  1. Nginxログの出力形式と各フィールドの意味を理解する必要があります。
  2. Filebeatをインストールします。Filebeatは軽量で、Logstashに比べて機能が限定的です。
  3. 中継サーバーとしてLogstashをセットアップします。当初はLogstashを直接Elasticsearchに送信する計画でしたが、フロントエンドサーバー数が増加するとLogstashの数も増え、Elasticsearchの制限によるエラーが発生することがあります。
  4. Elasticsearchクラスタ。ポイントはインデックステンプレートの作成がgeoipモジュールの操作に影響を与えることです。
  5. Grafanaのインストール。従来のKibanaに代わり、より友好性と美しい表示インターフェースを提供します。

実装プロセス

1. Nginxログ出力設定

Nginxのログ形式とフィールドの内容と順序は高度にカスタマイズ可能です。収集するフィールドの内容を適切に配置します。log_formatを定義します。

実際の定義は、logstash設定でのフィールド抽出のパターンを直接決定します。2つの方法があります。1つはnginxログでJSON形式を直接組み立て、logstashでcodec => "json"を使用して変換する方法です。もう1つは通常のデフォルトの区切り文字の形式で、logstashではgrokを使用してマッチさせる必要があります。後者はより複雑ですが、正確性が向上します。

ここでは最初の方法を採用します。nginxのログ形式定義は以下の通りです:

log_format access_json   '{"timestamp":"$time_iso8601",
                        '"hostname":"$hostname",
                        '"ip":"$remote_addr",
                        '"request_method":"$request_method",
                        '"domain":"XXXX",
                        '"size":$body_bytes_sent,
                        '"status": $status,
                        '"responsetime":$request_time,
                        '"sum":"1"
                        '}';

2. Filebeat設定ファイル

Filebeatの詳細についてはhttps://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.htmlを参照してください。

filebeat.prospectors:
- input_type: log
  paths:
    - /data0/logs/log_json/*.log

output.logstash:
    hosts: ["xxxx.xxxx.xxxx.xxx:12121"]

3. Logstash設定ファイル

JSONがすでに組み立てられている場合、直接JSON変換を行います:

input {
    beats {
    port => 12121
    host => "10.13.0.80"
    codec => "json"
    }
}

filter {
    date {
      match => [ "timestamp", "yyyy-MM-dd'T'HH:mm:ssZZ" ]
      timezone => "Asia/Shanghai"
    }
    mutate {
      convert => [ "status","integer" ]
      convert => [ "sum","integer" ]
      convert => [ "size","integer" ]
      remove_field => "message"
      remove_field => "source"
      remove_field => "tags"
      remove_field => "beat"
      remove_field => "offset"
      remove_field => "type"
      remove_field => "@source"
      remove_field => "input_type"
      remove_field => "@version"
      remove_field => "host"
      remove_field => "client"
      remove_field => "size"
      remove_field => "timestamp"
    }
    geoip {
      source => "ip"
      fields => ["country_name", "city_name", "timezone", "region_name", "location"]
    }
}

output {
    elasticsearch {
       hosts => ["xxx:19200", "xxx:19200", "xxx:19200"]
       user => "xxx"
       password => "xxx"
       index => "logstash-suda-alllog-%{+YYYY.MM.dd}"
       flush_size => 10000
       idle_flush_time => 35
    }
}

Grokを使用した例:

input {
  file {
  type => "access"
  path => ["/usr/local/nginx/logs/main/*.log"]
  }
}
filter {
  if [type] == "access" {
  if [message] =~ "^#" {
    drop {}
  }
  grok {
    match => ["message", "\[%{HTTPDATE:log_timestamp}\] %{HOSTNAME:server_name} \"%{WORD:request_method} %{NOTSPACE:query_string} HTTP/%{NUMBER:httpversion}\" \"%{GREEDYDATA:http_user_agent}\" %{NUMBER:status} %{IPORHOST:server_addr} \"%{IPORHOST:remote_addr}\" \"%{NOTSPACE:http_referer}\" %{NUMBER:body_bytes_sent} %{NUMBER:time_taken} %{GREEDYDATA:clf_body_bytes_sent} %{NOTSPACE:uri} %{NUMBER:m_request_time}"]
  }
  date {
    match => [ "log_timestamp", "dd/MMM/yyyy:mm:ss:SS Z" ]
    timezone => "Etc/UTC"
  }
  mutate {
  convert => [ "status","integer" ]
  convert => [ "body_bytes_sent","integer" ]
  convert => [ "m_request_time","float" ]
  }
}

4. Elasticsearch設定

クラスタのインストール、起動、チューニングについては詳述しません。重要なポイントはgeoip locationの形式です。ここではインデックステンプレートを使用して実装します:

{
  "order": 0,
  "version": 50001,
  "index_patterns": [
    "suda-*"
  ],
  "settings": {
    "index": {
      "number_of_shards": "5",
      "number_of_replicas": "1",
      "refresh_interval": "200s"
    }
  },
  "mappings": {
    "_default_": {
      "dynamic_templates": [
        {
          "message_field": {
            "path_match": "message",
            "mapping": {
              "norms": false,
              "type": "text"
            },
            "match_mapping_type": "string"
          }
        },
        {
          "string_fields": {
            "mapping": {
              "norms": false,
              "type": "text",
              "fields": {
                "keyword": {
                  "ignore_above": 256,
                  "type": "keyword"
                }
              }
            },
            "match_mapping_type": "string",
            "match": "*"
          }
        }
      ],
      "properties": {
        "@timestamp": {
          "type": "date"
        },
        "geoip": {
          "dynamic": true,
          "properties": {
            "ip": {
              "type": "ip"
            },
            "latitude": {
              "type": "half_float"
            },
            "location": {
              "type": "geo_point"
            },
            "longitude": {
              "type": "half_float"
            }
          }
        },
        "@version": {
          "type": "keyword"
        }
      }
    }
  },
  "aliases": {}
}

5. Grafanaのインストールとテンプレート作成

これは比較的簡単で、インストール後は直接クエリを記述できます。変数はカスタマイズする必要があります。

上記の方法により、完全な収集と表示を実現できます。これは実用的なアプローチを提供し、具体的な操作については詳細には触れません。

タグ: ELK Nginxログ収集 grafana filebeat Logstash

7月22日 18:46 投稿