美文网首页ElasticSearch
Prometheus指标写入ES间断问题排查

Prometheus指标写入ES间断问题排查

作者: 王勇1024 | 来源:发表于2019-12-17 17:53 被阅读0次

背景

由于Prometheus自身容量有限,不适合存储大量数据,所以需要将数据写入远端存储。由于我对ES比较熟悉,所以选择了ES作为远端存储,adapter为 prometheus-es-adapter
环境搭建好后,很快就看到ES中已经有数据流入,就以为大功告成了,但第二天发现数据只写了半个小时就中断了。

1.增大cpu和内存

通过初步排查后,发现是 prometheus-es-adapter挂掉了,原因是OOMKilled(内存溢出),所以就将cpu增加到1000m,内存增加到1Gi,之后运行正常了。
但观察半天后,发现数据写入经常出现长时间间断,如下图:

打点间断

2. 增大队列容量

由于我目前对Prometheus接触还比较少,于是带着问题去请教运维同学,运维同学检查完Prometheus配置后,指出可能是remote_write.queue_config.capacity设置过小,导致大量数据来不及写入ES而被丢弃。下面默认capacity是10:

remote_write:
- url: http://prometheus-es-adapter-service.kube-system.svc.cluster.local:8000/write
  remote_timeout: 30s
  queue_config:
    capacity: 10   # 默认capacity是10
    max_shards: 1000
    min_shards: 1
    max_samples_per_send: 100
    batch_send_deadline: 5s
    min_backoff: 30ms
    max_backoff: 100ms

于是我将remote_write.queue_config.capacity增大为1000:

remote_write:
- url: http://prometheus-es-adapter-service.kube-system.svc.cluster.local:8000/write
  remote_timeout: 30s
  queue_config:
    capacity: 10000  # capacity设置为10000
    max_shards: 1000
    min_shards: 1
    max_samples_per_send: 100
    batch_send_deadline: 5s
    min_backoff: 30ms
    max_backoff: 100ms

3. 启动调试

但发现并没有起作用。这是把这个过程看成是生产者-消费者模式的话,那Prometheus就是生产者,prometheus-es-adapter是消费者,既然问题不在Prometheus,很可能就在prometheus-es-adapter这边。于是我按照说明文档,设置环境变量DEBUG=true开启调试模式。

Env Variables Default Description
ES_URL http://localhost:9200 Elasticsearch URL
ES_USER Elasticsearch User
ES_PASSWORD Elasticsearch User Password
ES_WORKERS 1 Number of batch workers
ES_BATCH_MAX_AGE 10 Max period in seconds between bulk Elasticsearch insert operations
ES_BATCH_MAX_DOCS 1000 Max items for bulk Elasticsearch insert operation
ES_BATCH_MAX_SIZE 4096 Max size in bytes for bulk Elasticsearch insert operation
ES_ALIAS prom-metrics Elasticsearch alias pointing to active write index
ES_INDEX_DAILY false Create daily indexes and disable index rollover
ES_INDEX_SHARDS 5 Number of Elasticsearch shards to create per index
ES_INDEX_REPLICAS 1 Number of Elasticsearch replicas to create per index
ES_INDEX_MAX_AGE 7d Max age of Elasticsearch index before rollover
ES_INDEX_MAX_DOCS 1000000 Max number of docs in Elasticsearch index before rollover
ES_INDEX_MAX_SIZE Max size of index before rollover eg 5gb
ES_SEARCH_MAX_DOCS 1000 Max number of docs returned for Elasticsearch search operation
ES_SNIFF false Enable Elasticsearch sniffing
STATS true Expose Prometheus metrics endpoint
DEBUG false Display extra debug logs

可以看到有日志正常输出,说明prometheus-es-adapter确实接收到了数据,并尝试写入ES,但为什么ES没有收到数据呢?(后来仔细观察,发现ES是有数据写入的,只不过速度很慢)


prometheus-es-adapter 日志

4. 监控内存

于是我猜想:是不是prometheus-es-adapter把数据写入了队列中,等待数据达到一定数量后再批量写入呢?或者是消费线程太少,导致消息处理不过来而造成大量堆积呢?如果是这样,那必定会占用大量内存,内存空闲率必然要不断下降,这也可以解释之前遇到的OOMKilled。
于是我通过watch命令去监控prometheus-es-adapter容器的内存空闲率:

$ watch -n 1 'free -m'

下面两张图是观察了5分钟的结果,可以看到内存空闲率在不断下降。


2019-12-17 09:12:20 2019-12-17 09:17:56

于是我尝试着将ES_WORKERS增加为20,果然一段时间后数据就追上来了。

效果展示

总结

这个问题的根本原因是:prometheus-es-adapter处理线程太少,导致数据不能及时写入ES而致使Prometheus队列爆满,数据被大量丢弃或堆积在prometheus-es-adapter的处理队列中。这也是为什么只有一段时间有数据的原因及prometheus-es-adapter发生OOMKilled的原因。
要解决这个问题,需要修改两个地方:

  1. 增大Prometheus队列大小,避免队列爆满导致数据被丢弃
  2. 增加prometheus-es-adapter处理线程数量,使数据被快速写入远端存储
  3. 如果想让数据快速追上来,而历史数据又不太重要,可以尝试重启Prometheus

相关文章

网友评论

    本文标题:Prometheus指标写入ES间断问题排查

    本文链接:https://www.haomeiwen.com/subject/fgasnctx.html