@johtaniの日記 2nd

@johtani ‘s blog 2nd edition

インデックステンプレートとLogstash

前回の「Logstashを利用したApacheアクセスログのインポート」の続きです。 前回の記事では、Logstashの設定ファイルについて説明しました。 今回は「Elasticsearchに設定するインデックステンプレート」について説明します。

テンプレートの設定

Elasticsearchでは、登録するデータの特性に合わせてMappingを定義する方がデータを効率良く扱うことができる場合があります。 この場合、通常ですと、インデックス作成時にMappingを指定します。

ただ、今回は、インデックス名に「年」を含める形で指定してあります。 「年」はLogstashで処理したデータによって決まります。このため、あらかじめMappingを指定してインデックスを作成するのは難しいです。

このような場合に便利な機能として、「インデックステンプレート」があります。

インデックステンプレートとは

実際のテンプレートの説明に入る前に、少しだけ説明を。 インデックステンプレートとは、インデックスが作成されるタイミングで自動的に適用される設定をテンプレートとして登録できる機能のことです。 実際にテンプレートが適用されるかどうかは、インデックス名で判断されます。

例えば、大して重要でもなく、データ量も少ないインデックス用のテンプレートとして、シャード数が1、レプリカ数が0、”_source”を保存しない設定のテンプレートを登録する場合、 次のようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
curl -XPUT localhost:9200/_template/template_1 -d '
{
  "template" : "te*",
  "settings" : {
    "number_of_shards" : 1,
    "number_of_replicas" : 0
  },
  "mappings" : {
    "type1" : {
      "_source" : { "enabled" : false }
    }
  }
}
'

_templateがインデックステンプレートを登録するためのエンドポイントです。 template_1がこのテンプレートのIDです。削除などについては、このIDを利用します。

そして、重要なのは、”template“の設定です。 ”template“には、このテンプレートが適用されるべきインデックス名を記載します。 上記サンプルではte*となっているため、teで始まる名前のインデックスを作成した場合にテンプレートにある設定が適用されます。

今回利用するテンプレート

私がJJUG CCCや第7回Elasticsearch勉強会のKibana4のデモで利用したインデックスのテンプレートは次のものになります。 “template“には、前回の記事で紹介したoutput/elasticsearchの設定 に合致するnew_demo_access_log-*を指定しています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
curl -XPUT localhost:9200/_template/new_access_log_for_demo -d '
{
  "template": "new_demo_access_log-*",
  "settings": {
    "number_of_shards": "2",
    "number_of_replicas": "0"
  },
  "mappings": {
    "_default_": {
      "dynamic_templates": [
        {
          "string_template": {
            "mapping": {
              "index": "not_analyzed",
              "type": "string"
            },
            "match_mapping_type": "string",
            "match": "*"
          }
        }
      ],
      "properties": {
        "path": {
          "type": "multi_field",
          "fields": {
            "no_analyzed": {
              "index": "not_analyzed",
              "type": "string"
            },
            "analyzed": {
              "index": "analyzed",
              "type": "string"
            }
          }
        },
        "referer": {
          "type": "multi_field",
          "fields": {
            "no_analyzed": {
              "index": "not_analyzed",
              "type": "string"
            },
            "analyzed": {
              "index": "analyzed",
              "type": "string"
            }
          }
        },
        "agent": {
          "type": "multi_field",
          "fields": {
            "no_analyzed": {
              "index": "not_analyzed",
              "type": "string"
            },
            "analyzed": {
              "index": "analyzed",
              "type": "string"
            }
          }
        },
        "geoip": {
          "type": "object",
          "properties": {
            "location": {
              "geohash": true,
              "geohash_precision": 10,
              "type": "geo_point",
              "lat_lon": true,
              "geohash_prefix": true
            }
          }
        },
        "response": {
          "copy_to": "response_int",
          "type": "string"
        },
        "bytes": {
          "type": "long"
        },
        "response_int": {
          "type": "integer"
        }
      }
    }
  }
}
'

settings設定

デモ用であり、手元で2台のノードを起動するということもあり、number_of_shards2を、number_of_replicas0を指定してあります。

mappings設定

インデックスのタイプ

Mappingsの指定は通常、特定のタイプを指定します。 今回のデモでは、1種類しかないのですが、タイプ名を特に意識しないために、_default_を使用しました。 この場合、任意のタイプに適用されることとなります。 タイプを指定してMappingの設定を行う場合は_default_の部分に特定のタイプ名を記入します。

1
2
3
"mappings": {
  "_default_": {
    ...
ダイナミックテンプレート

次はダイナミックテンプレートです。 インデックステンプレートはインデックスの設定をテンプレート化しました。ダイナミックテンプレートはフィールドに対してテンプレートを設定できます。

以下のダイナミックテンプレートでは、stringタイプのフィールドのデフォルト設定を変更しています。 通常、stringタイプのフィールドはanalyzedとなりますが、not_analyzedに変更してあります。 詳しく検索したいフィールドの方が少ないためです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
"dynamic_templates": [
  {
    "string_template": {
      "mapping": {
        "index": "not_analyzed",
        "type": "string"
      },
      "match_mapping_type": "string",
      "match": "*"
    }
  }
],
...
multi_field指定

検索もしたいし、Terms Aggregationでも利用したいフィールドについては、multi_fieldを利用して、 analyzednot_analyzedの2種類のフィールドを用意しています。 multi_field設定を用いることで、1つのJSONのデータから、異なる形のフィールドを用意することが可能です。

今回のテンプレートでは、pathrefereragentmulti_fieldを指定しました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
"path": {
  "type": "multi_field",
  "fields": {
    "no_analyzed": {
      "index": "not_analyzed",
      "type": "string"
    },
    "analyzed": {
      "index": "analyzed",
      "type": "string"
    }
  }
},
...

例えば、上記の設定の場合、入力のJSONはpathというデータのみですが、インデックス上にはpath.no_analyzedpath.analyzedというフィールドができあがります。 実際に検索する場合は、path.analyzed:検索したい文字列という形で検索をすることで、いわゆる部分一致のような検索が可能です。 また、完全一致をしたい場合はpath.no_analyzed:検索したい文字列という指定になります。 用途を考えると、requestも指定したほうが良いかもしれません。

geoip

Logstashでgeoipデータを付与していました。 このgeoipのデータをKibana4で利用するために、geoデータとして登録する必要があります。

1
2
3
4
5
6
7
8
9
10
11
12
"geoip": {
  "type": "object",
  "properties": {
    "location": {
      "geohash": true,
      "geohash_precision": 10,
      "type": "geo_point",
      "lat_lon": true,
      "geohash_prefix": true
    }
  }
},

上記の設定がgeoデータの指定です。 typeobjectが指定してありますが、これは、geoipのデータがネストしているためです。 geoipオブジェクトのうち、緯度経度のデータはlocationに入っているため、こちらに緯度経度関係の設定を指定します。

  • "type": "geo_point"geo_pointタイプであることを指定
  • "geohash": true:緯度経度のデータをもとに、geohashの値もインデックス
  • "geohash_precision": 10:geohashの精度の指定
  • "lat_lon": true:緯度経度を個別の.lat.lonというフィールドにもインデックス
  • "geohash_prefix": true:該当するgeohashのみでなく、その親にあたるgeohashについてもインデックスする
response、response_int、bytes

最後は、response、response_int、bytesです。

responseには、HTTPステータスコードが入ります。 文字列としても扱いたいですが、integerとして、Renge Aggregationなどを行いたいので、 response_intというフィールドにも値を入れています。 multi_fieldでも可能ですが、ここでは、copy_toを利用しました。 copy_toを用いることで、異なるフィールドに値をコピーすることができます。

bytesについては、longで扱いたいとういう理由だけです。

1
2
3
4
5
6
7
8
9
10
"response": {
  "copy_to": "response_int",
  "type": "string"
},
"bytes": {
  "type": "long"
},
"response_int": {
  "type": "integer"
}

まとめ

今回はデモに利用したインデックスてプレートについて説明しました。 前回の、Logstashの設定とこのインデックステンプレートを用いることで、Kibanaで解析するデータの準備ができます。 実際の操作などについては、また次回の記事で説明しようかと思います。

不明な点、誤植などありましたら、コメント欄へお願いします。

Comments