美文网首页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