公司ELK系統目前的設置是每月自動將日志信息記錄至新的索引中,將日志數據按月分索引保存,在擴展的ELK架構中,利Logstash對接rabbitmq,獲取日志消息,自動持久化至Elasticsearch。而Elasticsearch存在一個關鍵問題就是索引的設置及字段的屬性指定,最常見的問題就是,某個字段我們並不希望ES對其進行分詞,但如果使用自動模板創建索引,那么默認是所有string類型的字段都會被分詞的,因此必須要顯式指定字段的not_analyzed屬性,其它的比如控制索引的備份數,分片數等,也可以通過模板的套用來實現,並且模板可以通過通配符進行模糊匹配,即可對滿足某一通配符的所有新建索引均套用統一模板,不需要為每個索引都建立模板。但也有一點局限性需要注意:模板在設置生效后,僅對ES集群中新建立的索引生效,而對已存在的索引及時索引名滿足模板的匹配規則,也不會生效,因此如果需要改變現有索引的mapping信息,仍需要在正確的mapping基礎上建立新的索引,並將數據從原索引拷貝至新索引,變更新索引別名為原索引這種方式來實現(改方法適用當前ES版本(1.7+~2.4+)),也許未來會有索引的直接遷移方案。
方案選擇:
方案一:可對logstash配置output參數:
如下所示:
這種方案在logstash中指定模板文件,由logstash將template寫入ES集群;
方案二:直接將template寫入ES集群
通過ES提供的API,將JSON格式的template寫入目標ES集群的_template路徑,對新生成的所有符合過濾規則的索引直接套用該模板。
這里我直接選擇了方案二,因為不想修改logstash的docker鏡像中的配置文件...
模板的結構大致分四塊吧:
第一部分:通用設置,主要是模板匹配索引的過濾規則,影響該模板對哪些索引生效;
第二部分:settings:配置索引的公共參數,比如索引的replicas,以及分片數shards等參數;
第三部分:mappings:最重要的一部分,在這部分中配置每個type下的每個field的相關屬性,比如field類型(string,long,date等等),是否分詞,是否在內存中緩存等等屬性都在這部分配置;
第四部分:aliases:索引別名,索引別名可用在索引數據遷移等用途上。
典型的一個template如下所示:

{ "template": "ld.log-*", "order":0, "settings": { "index.number_of_replicas": "1", "index.number_of_shards": "5" }, "mappings": { "logs": { "properties": { "@timestamp": { "type": "date", "format": "strict_date_optional_time||epoch_millis" }, "@version": { "doc_values": true, "index": "not_analyzed", "type": "string" }, "Exp": { "doc_values": true, "index": "not_analyzed", "type": "string" }, "Guid": { "doc_values": true, "index": "not_analyzed", "type": "string" }, "LogLevel": { "type": "long" }, "LogTime": { "type": "date", "format": "strict_date_optional_time||epoch_millis" }, "LoggerName": { "index": "not_analyzed", "type": "string" }, "Message": { "doc_values": true, "index": "not_analyzed", "type": "string" }, "ProcessId": { "type": "long" }, "StackTrace": { "doc_values": true, "index": "not_analyzed", "type": "string" }, "ThreadId": { "type": "long" }, "exp": { "doc_values": true, "index": "not_analyzed", "type": "string" }, "logLevel": { "type": "long" }, "logTime": { "doc_values": true, "index": "not_analyzed", "type": "string" }, "loggerName": { "doc_values": true, "index": "not_analyzed", "type": "string" }, "message": { "doc_values": true, "index": "not_analyzed", "type": "string" }, "processId": { "type": "long" }, "tags": { "doc_values": true, "index": "not_analyzed", "type": "string" }, "threadId": { "type": "long" } } } }, "aliases": { } }
在這個JSON中可以清楚地看到四個部分,並且對string類型的fields設置了不進行默認分詞信息。
將這個JSON內容作為PUT請求的BODY(如果是修改template則發送POST請求)發送至目標ES集群(需要指定template的名字,如下例的log_template):
成功后將返回如下信息:
{ "acknowledged": true }
現在可以通過對集群_template目錄直接發送請求(也可以加上template名稱)來查看集群當前的模板信息:
按照如上步驟,template正常添加至ES集群之后,在新增索引之前,會自動與模板進行匹配,如果滿足過濾條件,即可套用目標模板來新建索引。