0x01 前言
我最近重建某些服务的时候遇到日志格式发生了变化,某些字段的type也做了修改,这时候需要将以前的索引进行reindex操作。
我刚开始配置elasticsearch的时候并没有设定别名,这里会带来一个问题:当我将索引A的数据reindex到索引B时,logstash依旧会将数据发送到索引A。
对于reindex的操作,可以参考以下文章:
如果想将数据发送到索引B,就需要修改logstash的output配置并且重启服务。这里又会有一个问题:我收集的所有日志都依赖logstash并且只有一个logstash节点在接收。一旦重启logstash服务就会有一小部分的日志丢失。
当然,这些都是我在家里测试用的服务,丢失一点点日志并不会造成任何损失。如果这是发生在生产环境中呢?这肯定是不可接受的。
0x02 别名
为了提高elasticsearch的可用性,建立一个index的别名是必不可少的。在elasticstack 6.x的文档里关于索引别名的文档连接如下:
索引别名就是一个映射关系,可以是一个索引映射到这个别名,也可以多个索引一起映射到一个别名,如:
{ "actions": [ { "add": { "alias": "alias1", "index": "test1" } }, { "add": { "alias": "alias1", "index": "test2" } } ] }
如果在外部通过API写入数据到别名alias1中,那么这些数据将会同时存放在两个索引中。
通过别名也可以很好地解决我已开始所说的reindex问题。我会在一开始就建立以下映射关系:
{ "actions": [ { "add": { "alias": "public-ngx-alias", "index": "public-nginx-main-v1" } } ] }
而logstash的ouput如下:
output { if "server_ngx_access_log" in [tags] { elasticsearch { hosts => ["es6-node1.t.com:9200", "es6-node2.t.com:9200", "es6-node3.t.com:9200"] manage_template => false index => "public-ngx-alias" } } }
如果某天我日志的格式发生了变化,同时某些字段的类型也发生了变化,我只需要新建一个index:
curl -XPUT 'es6-node1.t.com:9200/public-nginx-main-v2?pretty'
然后将旧的index从别名中移除,同时将新的index映射到别名中:
curl -XPOST 'es6-node1.t.com:9200/_aliases?pretty' -H 'Content-Type: application/json' -d' { "actions" : [ { "remove" : { "index" : "public-nginx-main-v1", "alias" : "public-ngx-alias" } }, { "add" : { "index" : "public-nginx-main-v2", "alias" : "public-ngx-alias" } } ] } '
这样就可以实现elasticsearch数据的读写实现无缝对接。成功切换index后就可以进行reindex的操作:
curl -XPOST 'es6-node1.t.com:9200/_reindex?pretty' -H 'Content-Type: application/json' -d' { "source": { "index": "public-nginx-main-v1" }, "dest": { "index": "public-nginx-main-v2" } } '
当然,在kibana中也需要将别名添加到index pattern中,而不是实际的index名称:
别名还提供了其他更多的高级功能,具体请参考官方文档。
0x03 其他
还有一点需要注意的,elasticsearch的索引模板匹配规则请不要匹配上别名的名称。例如我nginx日志在elasticsearch中的索引模板如下:
{ "public_nginx": { "order": 0, "index_patterns": [ "public-nginx-*" ], "settings": { "index": { "number_of_shards": "5" } }, "mappings": { "doc": { "properties": { "bytes": { "type": "long" }, "client_ip": { "type": "ip" }, "geoip": { "dynamic": true, "properties": { "location": { "type": "geo_point" } }, "type": "object" }, "request_time": { "type": "float" }, "upstream_response_time": { "type": "float" } } } }, "aliases": {} } }
index_patterns字段为匹配规则,匹配一切传入public-nginx-*索引的数据,其中就包含public-nginx-main-v1与public-nginx-main-v2这两个索引,但不匹配public-ngx-alias这个别名名称。
如果把别名也匹配上,那么就算你怎样reindex也无法调整旧数据的字段类型。
请不要给别名设置索引模板,所有操作都在索引上操作即可。
0x04 结语
别名的操作起来并不复杂,只是reindex倒腾数据很耗时间而已。