Logstash Docker部署的踩坑笔记

这周要开始做埋点日记的分析,初步调研后,准备用filebeat+logstash+mongodb来做。

基于golang写的filebeat比较轻量,解压后就可以直接用了,而logstash还有好多依赖要装,所以毫不犹豫就选择用docker来部署。

因为是现学现用,时间也有些紧,再加上完全是新手入门,看到文档Configuaring Logstash for Docker中Bind-mounted settings files这段后,

就自己定义了一个logstash.yml

input{
  beats {
    port => 5044
  }
}

output{
   mongodb {
    uri => "mongodb://localhost:27017"
    database => "spot_logs"
    collection => "raw_data"
  }
}

心想着这样通过volume挂进去就可以用了。

docker run  --rm -it -v ./logstash.yml:/usr/share/logstash/config/logstash.yml docker.elastic.co/logstash/logstash:7.2.0

然后,悲剧开始了~~~

首先,我定义的其实是一个.conf文件,而不是logstash.yml。

于是,刚一启动就报错了。

当我经过一番搜索,知道这其实是一个conf文件后,就直接改把它的后缀名改成了.conf,然后执行了

docker run --rm --network host -it -v ./logstash.conf:/usr/share/logstash/config/logstash.conf docker.elastic.co/logstash/logstash:7.2.0

然后,“奇迹发生”了~~filebeat发过来日志,logstash都能收到,而且还打印了出来(好神奇,那可是我第一次跑通filebeat+logstash),但是还没开心1分钟,就发现mongodb里根本没数据。

然后,没有方向的我,开始了一通乱试(略去不表,其实都是泪),白白耗费了一个下午加晚上也没找到原因(那时真是心情沉重,想着这个sprint估计有点难交差了!)。

回到家后,洗了澡,重新开始思考这个问题的时候,我突然意识到,可能我设置的配置根本就不起作用,现在的行为没准是logstash镜像的默认行为。(在时间压力下,现学现用,很容易钻牛角尖,这时暂停下来,平静心情,换个思路很重要!

查了一下logstash官方的dockerfile也没发现什么,到是在一篇搜索到文章中,发现可能是e受容器里的pipelines.yml的影响。

当我打开容器里的/usr/share/logstash/config/pipelines.yml的时候,看见:

- pipeline.id: main
  path.config: "/usr/share/logstash/pipeline"

再打开 /usr/share/logstash/pipeline,看到:

input {
  beats {
    port => 5044
  }
}

output {
  stdout {
    codec => rubydebug
  }
}

真是一口老血喷出来~心想好坑呀,隐藏的这么深!

于是,仿造这个pipelines.yml,也写了个pipelines.yml,把config指向自己的配置。

- pipeline.id: main
  path.config: "/usr/share/logstash/config/logstash.conf"
  pipeline.workers: 3

再挂载进docker启动后,看到mongodb的报错信息后,就知道自己的设置终于生效了。

报错的原因,是因为logstash-output-mongodb这个output默认是没有的,需要自己装好,解决方法也很简单,自定义一个dockerfile,做一个安装好logstash-output-mongodb的镜像就好。

同时,在这里我也把自己写的放在config文件里的pipelines.yml和logstash.conf拷了进去,具体内容如下;

FROM docker.elastic.co/logstash/logstash:7.2.0
RUN rm -f /usr/share/logstash/pipeline/logstash.conf
COPY ./config/ /usr/share/logstash/config/
RUN logstash-plugin install logstash-output-mongodb

然后运行:

docker build -f logstash.dockerfile -t mine/logstash:1.0

最后定义了一个docker-compose.logstash.yml文件:

version: '3'

services:
  logstash:
    image: mine/logstash:1.0
    restart: always
    container_name: finxos_logstash
    network_mode: 'host'
    volumes:
      - "$PWD/config/logstash.conf:/usr/share/logstash/config/logstash.conf"
    depends_on:
      - mongodb

  mongodb:
    image: mongo:4.0
    restart: always
    container_name: finxos_mongodb
    volumes:
      - "$PWD/mongodb_data:/data/db"
    network_mode: 'host'

这样就可以通过下面的命令一键启动了。

docker-compose -f docker-compose.logstash.yml up

写在最后

在下笔前,我是心想着写下自己的踩坑经验,估计会对他人有用。

但是写着的时候,才发现我觉得很坑的默认行为,其实在Configuaring Logstash for Docker的Pipeline Configuration章节里有提到。

而当时的我急着赶紧用起来,看到Pipeline也不知道是干什么的(其实现在也不是很清楚),就直接跳到Settings章节了。

真的是要好好看文档!抓住重要信息呀!

但是再一想,即再来一次,以当时的我刚刚接触filebeat+logstash, docker也好久不用了的状态,还面临着完成业务需求的紧迫感,大概率还是会略过这段。

现学现用,真的很痛苦!

这期间,关键是要准确的定位问题,然后逢山开路,遇水搭桥,其实也不失为一次蜕变的体验!

关键的关键在于,要相信自己最终还是会搞定的