Logstash的容器化与Ansible多环境下单配置文件发布

文章目录

[隐藏]

  • 原因
  • 官方logstash镜像
  • pipeline.conf
  • 日志文件检测脚本 detect_logfiles.py
  • ansible剧本
  • docker-compose
原因

为了发布、迁移方便,最近决定将公司项目中用的logstash容器化,最初原打算沿用原多进程方案,在容器内通过supervisor启动多个不同配置进程,但使用官方容器时并支持启动多个实例。

最终解决方式:将集群的配置文件组装在一起,不同的path对应不同的filter与output;由于不同主机上组件不同,日志也不同。因此在ansible发布时通过脚本检测生成log file 的path列表,适配集群上的不同组件。这样的好处是只需要维护一份配置,操作简单。

官方logstash镜像

在dockerhub上搜索了到一个即将被废弃的镜像:https://hub.docker.com/_/logstash/。
最新版镜像在es官方进行维护: https://www.elastic.co/guide/en/logstash/current/docker.html
由于直接使用原版镜像时映射到容器内部的pipeline.conf一直提示No permission,明明都已经设置成755,宿主机上并没有logstash这一用户,chown不方便。所以决定对官方镜像稍加修改,再推送到公司内的dockerhub私有docker registry上。

FROM docker.elastic.co/logstash/logstash:5.6.1  MAINTAINER CodingCrush  ENV LANG en_US.UTF-8  # Disable ES monitoring in the official image  ENV XPACK_MONITORING_ENABLED false  # TimeZone: Asia/Shanghai  ENV TZ Asia/Shanghai  ENV PIPELINE_WORKERS 5  # Default user is logstash  USER root  

这个Dockerfile很简单,主要设置了User为root,解决conf文件的权限不足问题。另外关闭容器自带的es xpack检查功能,设置时区与pipeline的 worker数量。
然后打个tag,推到私有docker registry上。

docker build -t dockerhub.xxx.net/logstash:5.6.1  docker push dockerhub.xxx.net/logstash:5.6.1  

容器便修改好了,在生产集群上可pull。

pipeline.conf

这个简化的配置文件中path应该是一个列表,但目前用了一个占位字符串,发布时动态检测通过sed进行更换,实际项目中的组件配置更多,这里写4个意思一下。
值得注意的是: 通过if else 对path进行匹配时如果出现/,需要进行转义,否则ruby进行正则匹配时会报错。

input {      file {          path => LOG_FILES_PLACEHOLDER          type => "nginx"          start_position => "beginning"          sincedb_path => "/data/projects/logstash/data/logstash.db"          codec=>plain{charset=>"UTF-8"}      }  }  filter {      if [path] =~ "component1/logs/access" {          grok & mutate      } else if [path] =~ "component1/logs/error" {          grok & mutate      } else if [path] =~ "component2/logs/access" {          grok & mutate      } else if [path] =~ "component2/logs/error" {          grok & mutate      }  }  output {      if [path] =~ "component1/logs/access" {          stdout{codec=>rubydebug}      }  else if [path] =~ "component1/logs/error" {          stdout{codec=>rubydebug}      } else if [path] =~ "component2/logs/access.log" {          stdout{codec=>rubydebug}      } else if [path] =~ "component2/logs/error" {          stdout{codec=>rubydebug}      }  }  
日志文件检测脚本 detect_logfiles.py

检测脚本同样很简单,用os.path.exists进行过滤。往标准输出打一个列表的string。
此处注意,需要用re.escape进行转义,因为后面还需要用sed进行替换。

import os  import sys  import re  paths = [      "/data/projects/component1/logs/access.log*",      "/data/projects/component1/logs/error.log",      "/data/projects/component2/logs/access.log*",      "/data/projects/component2/logs/error.log*",      ......  ]  available_paths = [path for path in paths if os.path.exists(path.replace("*", ""))]  sys.stdout.write(re.escape(str(available_paths)))  
ansible剧本

在发布时通过sed替换占位串,之所以大费周章搞这么个方式,主要因为我们环境比较复杂,将来横向拓展时组件布局不定,多配置文件维护起来挺麻烦。
为什么用shell?而不用ansible的module? 因为我不会,还懒得去学ansible发明的DSL

- name: Modify lostash.conf    args:      chdir: "/data/projects/logstash/"    shell: 'sed -i "s|LOG_FILES_PLACEHOLDER|$(python detect_logfiles.py)|" logstash.conf'    become: true    become_method: sudo  - name: Modify docker-compose.yml    args:      chdir: "/data/projects/logstash/"    shell: 'sed -i "s|HOST_PLACEHOLDER|{{ host }}|" docker-compose.yml'    become: true    become_method: sudo  
docker-compose

挂载整个文件卷,HOST_PLACEHOLDER占位符是因为我希望通过container名字直观看到组件所在的主机名,而避免生产服务器上误操作。

version: '2'  services:    logstash:      image: dockerhub.xxx.net/logstash:5.6.1      volumes:         - /etc/localtime:/etc/localtime:ro         - /data/projects/logstash/hosts:/etc/hosts         - /data/projects:/data/projects      container_name: HOST_PLACEHOLDER.logstash      command: logstash -f /data/projects/logstash/logstash.conf --path.data=/data/projects/logstash/data  

启动的command时指定工作目录,将运行状态持久化到外部存储上,方便迁移。

原文出处:codingcrush -> http://codingcrush.me/2017/09/24/logstash-dockerinaztion-and-ansible-deploy/

本站所发布的一切资源仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如果侵犯你的利益,请发送邮箱到 [email protected],我们会很快的为您处理。