集中式日志分析平台 - ELK Stack - 踩坑集锦

前言

恩,开这篇文章的目的很明显,就是因为踩坑太多,不知道去哪里记录了,那么也一定会长期更新,遇到一个记录一个。

问题集锦

Kibana 篇

**Question – K001 **:
打开 Kibana 界面遇到 Login is disabled because your license has expired. Please extend your license or disable Security in Elasticsearch.
Answer :
说明体验的 x-pack 功能证书过期,需要 disable 之后才可以恢复使用,在 elasticsearch.yml 中添加:

xpack.security.enabled: false

后进行重启即可。
**Question – K002 **:
修改了 default index pattern 之后打开 Kibana 界面的 Management 页面报错( URL 请求为:http://172.16.134.3:5601/elasticsearch/packetbeat-*/_mapping/field/*?_=1490863194201&ignore_unavailable=false&allow_no_indices=false&include_defaults=true): 404 Not Found.
Answer :
因为设置了一个不存在的 elasticsearch index,情况类似 https://github.com/elastic/kibana/issues/9028, 需要重置 default index:

curl -XPOST 'http://${ES_HOSTNAME}:${ES_HOST_PORT}/.kibana/_update_by_query?pretty&wait_for_completion&refresh' -H 'Content-Type: application/json' -d'
{
  "script": {
    "inline": "ctx._source.defaultIndex = null",
    "lang": "painless"
  },
  "query": {
    "term": {
      "_type": "config"
    }
  }
}
'

**Question – K003 **:
浏览器总是无法显示数据,但是在链路中 debug 数据是正常流转的。
Answer:
可能是操作系统时间问题,Kibana 的时间选取是以操作系统的时间戳作为基础的。
**Question – K004 **:
卸载 ES 和 Kibana 的 X-pack 之后,Kibana 报错:

license information could not be obtained from elasticsearch

Answer:
需要在 kibana.yml 中申明 xpack.security.enabled: false

Logstash 篇

**Question – L001 **:
假设输入是 Kafka,采集端是 filebeat,如何得到 beat 中的相关指标,比如日志源 hostname?
Answer
这个问题困扰了我一会,看到了网上的解法:https://discuss.elastic.co/t/reading-beats-fields-from-kafka-input/76206/3, 那么细节配置大致为修改 logstash.conf 中的 filter 块:

...
filter {
  json {
    source => "message"
    target => "message_json"
  }
  mutate {
    add_field => { "${new_field_name}" => "%{[message_json][beat][hostname]}" }
  }
}
...

还有一种办法是在 input 段中配置:

input {
  kafka {
    codec => "json"
  }
}

**Question – L002 **:
如何把自定义类似时间戳的 pattern 解析到的字段转化成 date 类型,以供排序?
Answer:
官方文档明确说明尽量不要使用 text filed 去做排序聚合,否则会使用大量的内存:https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html
报错类型如下:

Fielddata is disabled on text fields by default. Set fielddata=true on [your_field_name] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory.

所以我们要对自定义时间戳 pattern 解析到的字段转成 date 类型,具体方法如下:
Step1. 在 patterns 目录下新建 extra 文件用于申明自定义 pattern;
Step2. 在 logstash 的 filter 块中,使用 pattern 去匹配字段:

...
filter {
  grok {
    patterns_dir => "./patterns"
    match => [ "message" => "%{TIMESTAMP_PYTHON:log_timestamp}" ]
  }
}
...

Step3. 在 logstash 的 filter 块中,使用 date 去转换字段为 date 类型:

...
filter {
  ...
  date {
    match => [ "log_timestamp", "YYYY-MM-dd HH:mm:ss,SSS" ]
    target => "log_timestamp"
  }
}
...

Question – L003:
采集 cron 日志 ( /var/log/cron ) 时,得到的指令数据中含有 unicode 编码,比如运行指令为 /usr/bin/tsar --cron >/dev/null 2>&1 被解析成了 /usr/bin/tsar --cron \u003e/dev/null 2\u003e\u00261
Answer:
input 配置块中添加 codec => "json",这样可以解码后再进行解析,得到想要的结果。
参考文献:Filebeat error. Returns unicode character code instead of symbol
Question – L004:
ES 索引已经建立的情况下,修改 logstash 解析规则,想让原先已经是 String 类型的 field 转换成 integer,但是做了如下修改(参考文献), ES 中的字段类型却没有改变:

# 方法一:在 pattern 中申明强转
filter {
  grok { 
    match => {
      "message" => "%{NUMBER:your_field_name:int}"
    }
  }
}
# 方法二:在 mutate 中申明强转
filter {
  mutate {
    convert => { "your_field_name" => "integer" }
  }
}

次奥,为什么我遇到了和这个哥们一样的问题:How can convert field to int, float
Answer:
我们使用如下方法首先确认 logstash 中是否有被正常解析,在 logstash.conf 中添加如下配置:

output {
  stdout {
    codec => rubydebug
  }
}

我们在 /var/log/messages 中查看数据格式是否正确,一般来说 logstash 不会有问题,正常输出如下:

# 正常输出
"your_field_name" => 1
# 错误输出
"your_field_name" => "1"

因此我们只需要删除 ES index 即可完成类型更新,原因是在 logstash 端进行了转换之后, ES 仍旧会按照最初的类型进行定义,我们来尝试删除 index:

curl -XDELETE 'localhost:9200/%{index_prefix}-*?pretty'

切记必须删除所有前缀匹配的 index,否则 Kibana 端会报类型冲突。
Question – L005:
Logstash 报错发现写入 ES 时返回 429:

[2017-05-22T15:59:33,624][INFO ][logstash.outputs.elasticsearch] retrying failed action with response code: 429 ({"type"=>"es_rejected_execution_exception", "reason"=>"rejected execution of org.elasticsearch.transport.TransportService$7@4469fa3b on EsThreadPoolExecutor[bulk, queue capacity = 50, org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor@38eb0898[Running, pool size = 12, active threads = 12, queued tasks = 56, completed tasks = 3864]]"})
[2017-05-22T15:59:34,269][ERROR][logstash.outputs.elasticsearch] Action

并且数据统计后发现缺失;
Answer:
请注意看这个 issue,里面提到了类似问题。日志的解释是因为 ES threadpool.bulk.queue_size 受限导致 Logstash 写入被拒绝,对于 bulk action failed 这个事件的报错语义不清晰的问题会在6.X版本修复,但是没有解释问题的本身(为什么有数据缺失)。关键不是这个,是解决方法,调整 ES Xss=10m。
Question – L006:
我想替换掉默认的 @timestamp 字段,不用它进行数据排序,而是使用我的日志时间戳,但是使用业务时间戳在进行报表渲染的时候加载数据非常慢,比如这样的场景:选择 line-chart,Y轴选择任意指标聚合,X轴选择 Date HistogramFiled 选择业务时间戳的情况下,Interval 不能选择 auto。这样在大时间 range 的聚合时,报表会显示非常慢,经常超时无法完成请求。原因是比如我们 Interval 选择分钟,但是我时间跨度选择一个月,那样需要绘制的点就茫茫多自然慢(其实跨度一个月,我按照天去绘制点就够了),怎么办?
Answer:
使用业务时间戳替换掉 @timestamp,因为默认的业务时间戳是支持 auto 的,如下图:

《集中式日志分析平台 - ELK Stack - 踩坑集锦》 屏幕快照 2017-05-23 下午8.46.37.png

解法是在
date 过滤器中进行如下配置:

date {
      match => [ "log_timestamp", "MMM dd HH:mm:ss" ]
    }

其中 MMM dd HH:mm:ss 是业务时间戳的格式。

Filebeat 篇

Question – F001:
Filebeat 5.2.1 在 centOS 7 下无法正常启动,报错如下:

《集中式日志分析平台 - ELK Stack - 踩坑集锦》 image.png

Exiting: Could not start registrar: Error loading state: Error decoding states: EOF

Answer:
类似 Filebeat Fails After Power Failure,在断电或者版本升级之后都可能概率性触发,root couse 是在异常情况下 registry 文件没有 EOF 标识符。这种情况下,需要删除 registry 文件才可以启动成功。

rm -r registry
systemctl reset-failed filebeat
systemctl start filebeat
    原文作者:大数据之心
    原文地址: https://www.jianshu.com/p/2d86eafc3e94
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞