第4章:Logstash安装与基础——架构、Pipeline配置、启动与调试

说到ELK栈,很多人第一反应是Elasticsearch。但我个人认为,真正把数据玩出花样的,其实是Logstash。它就像一个数据,负责把各种各样、奇形怪状的日志,变成我们想要的样子。今天,我们就来好好聊聊它。

4.1 Logstash的核心架构:一条数据的奇幻漂流

Logstash的架构其实不复杂。说白了,就是三条:输入、过滤、输出。业内管这个叫“Pipeline”模型,也就是管道。

我在项目中第一次看到这个模型时,脑子里就浮现出一个画面:一堆乱七八糟的原材料(日志),被丢到传送带上;工人们(过滤器)在传送带两边挑挑拣拣、改改修修;最后成品被打包(输出)送到仓库(Elasticsearch)。嗯,就是这个感觉。

核心要点:Logstash的事件处理是一个单线程Pipeline。每个事件会依次经过输入、多个过滤器、输出。但如果你的机器够强,可以通过多Worker并行处理,这个后面会讲。

那么数据的生命周期长什么样?看下面这张图:

Logstash Pipeline 核心流程 输入插件 Input Plugin 队列(Queue) 内存 / 持久化 过滤插件 Filter Plugin 输出 编解码器(Codec):在输入/输出的同时,完成数据格式的编解码 pipeline.workers:默认1个Worker,每个Worker独占一个线程处理Pipeline

从上图你能看到,一个事件要穿过好几个区域。你想想看,如果其中任何一环出了问题,整个数据流就断了。所以理解这个架构,是你排查问题的第一步。

4.2 Pipeline配置:写你的第一个管道

好了,理论说完了,我们上手干活。Logstash的配置文件,本质上就是用Ruby风格的语法,告诉它「数据从哪来、怎么洗、往哪去」。

我最开始学的时候,总喜欢把三种配置写在一个文件里,结果项目一多,文件变得肥大臃肿。后来我的习惯是:一个场景一个文件,放在/etc/logstash/conf.d/下面,方便管理,也方便调试。

小技巧:在Linux上,/etc/logstash/conf.d/目录下的.conf文件会按字母顺序加载。如果涉及插件依赖,给文件编号是个好习惯,比如10-system.conf、20-nginx.conf。

我们看一个基础例子。假设你要从文件中读取Nginx的access.log,把IP地址提取出来,然后写入Elasticsearch:

input {
    file {
        path => "/var/log/nginx/access.log"
        start_position => "beginning"   # 从文件头开始读
        sincedb_path => "/dev/null"     # 测试时禁用sincedb,避免重复消费
        codec => "plain"                # 纯文本格式
    }
}

filter {
    grok {
        match => { "message" => "%{COMBINEDAPACHELOG}" }
    }
    date {
        match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
    }
    mutate {
        remove_field => [ "message" ]   # 原始消息处理完后,可以丢掉
    }
}

output {
    stdout { codec => rubydebug }       # 先打印到控制台调试
    # elasticsearch {                   # 确认没问题后再打开
    #     hosts => ["localhost:9200"]
    #     index => "nginx-access-%{+YYYY.MM.dd}"
    # }
}

看到了吗?我把Elasticsearch的输出注释掉了,用stdout先看效果。这是我个人的习惯——先跑通,再上线。别看这个小举动,帮我在之前省了不少排查时间。

配置文件里这些块的含义,我整理了一张表:

配置块 角色 常见插件
input 定义数据来源 file、beats、kafka、tcp、syslog
filter 数据清洗与转换 grok、mutate、date、geoip、useragent
output 定义数据目的 elasticsearch、stdout、kafka、file
codec 数据格式的编解码 plain、json、rubydebug、multiline

注意事项:input和output块是必须的,filter块可选。但大多数情况下你会至少需要一个filter,否则原始日志直接进ES,搜索分析会很痛苦。

4.3 启动与调试:让管道跑起来

配置写好了,接下来就是启动和调试。Logstash的启动命令很简单,但参数折腾了我不少时间。

最基本的命令是这样:

/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/nginx.conf

如果一切正常,你会看到Logstash启动并开始监听文件。但如果你直接在终端运行,它会占据前台。我在生产环境一般会通过systemd管理,这是后话了。

调试的时候,有几个参数特别实用:

  • --config.test_and_exit:只检查配置文件语法,不启动。我每次改完配置都会跑一下这个,省得启动报错。
  • --config.reload.automatic:当配置文件变化时自动重载。调试时很有用,但生产环境建议关闭,避免意外触发。
  • -r:同上,是--config.reload.automatic的缩写。
  • -w:指定Worker数量。默认是1,但你的CPU核心数如果多,可以调大,比如-w 4。

举个例子,你写好配置后,先检查语法是否正确:

/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/nginx.conf --config.test_and_exit

看到Configuration OK字样,心里就有底了。然后你可以用-r让它自动重载,边改边看效果。

工程师小贴士:调试阶段,千万别忘了在output里加上stdout { codec => rubydebug }。这样你能直接看到事件经过filter后的样子,哪里解析错了,一目了然。我当初做grok调试时,几乎全靠这个。

还记得我之前提到的sincedb吗?在调试时,我建议像我一样把sincedb_path设为/dev/null。否则Logstash会记住已经读过的文件偏移量,你重启后它以为文件没更新,啥也不会输出。嗯,这个坑我踩过不止一次。

4.4 必知必会:启动参数与配置项速查

最后,我把常用的启动参数和核心配置项整理给你。不求全背,但用的时候知道在哪找。

参数/配置 作用 我的建议值
--config.test_and_exit 验证配置语法 每次修改配置后必须执行
--config.reload.automatic 自动重载配置 调试开,生产关
pipeline.workers 并行处理Worker数 CPU核心数的一半
pipeline.batch.size 每个Worker批次处理事件数 125~500之间调试
queue.type 队列类型(memory/persisted) 小数据量memory,关键数据用persisted

我个人最喜欢的调试流程是:写配置 → --config.test_and_exit验证 → 启动并加上-r和stdout → 灌入一小份测试日志 → 观察输出 → 调优filter → 确认没问题后,换回Elasticsearch输出并取消自动重载。这套流程走下来,基本不会出大乱子。

忍不住再说一句:如果你想测grok解析效果,Logstash自带了grokdiscover工具,也可以在线用 grok debugger。但作为运维,我推荐直接在stdout里看结果,因为能一块儿验证mutate、date等其他过滤器。

Logstash的基础就这些。它不难,但细节很多。