ELK Stack的核心组件与分工
要玩转ELK日志管理,先得把”分工”弄明白——ELK不是单一工具,而是Elasticsearch(存储&检索)+ Logstash(过滤&转发)+ Kibana(可视化)+ Beats(采集)的组合拳。我整理了一份组件分工表,帮你快速理清职责:

组件 | 核心作用 | 为什么选它? |
---|---|---|
Elasticsearch | 日志的”大脑”:存储、检索、分析 | 分布式架构支持PB级数据,秒级检索 |
Logstash | 日志的”清洁工”:过滤、转换、富集 | 200+插件覆盖所有清洗需求(比如解析非结构化日志) |
Kibana | 日志的”展示屏”:可视化、Dashboard | 拖拽式操作,不用写代码也能做报表 |
Filebeat | 日志的”快递员”:轻量采集 | 资源占用仅Logstash的1/10,适合边缘节点 |
记住:别用Logstash采集日志! 它是JVM应用,跑在服务器上会占1-2G内存,换成Filebeat能省出更多资源给Elasticsearch。
快速部署ELK环境(Docker版)
很多人卡在”环境搭建”这一步——要装JDK、配置环境变量、解决版本兼容…其实用Docker能5分钟搞定。我写了一份docker-compose.yml模板,直接复制就能用(以ELK 8.13.0稳定版为例):
version: '3.8'
services:
# Elasticsearch:存储与检索
elasticsearch:
image: elasticsearch:8.13.0
environment:
- discovery.type=single-node # 单节点模式(测试用,生产建议3节点)
- ES_JAVA_OPTS=-Xms2g -Xmx2g # JVM内存(根据服务器配置调整,至少1G)
- xpack.security.enabled=false # 关闭安全验证(测试用,生产要开)
ports:
- "9200:9200" # ES HTTP端口
volumes:
- es_data:/usr/share/elasticsearch/data # 持久化数据
# Logstash:过滤与转发
logstash:
image: logstash:8.13.0
volumes:
- ./logstash/pipeline:/usr/share/logstash/pipeline # 挂载pipeline配置
- ./logstash/config:/usr/share/logstash/config # 挂载logstash.yml
ports:
- "5044:5044" # 接收Filebeat的端口
depends_on:
- elasticsearch
# Kibana:可视化
kibana:
image: kibana:8.13.0
ports:
- "5601:5601" # Kibana Web端口
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200 # 连接ES
depends_on:
- elasticsearch
volumes:
es_data:
driver: local # 本地卷,持久化ES数据
启动步骤:
1. 新建文件夹elk-docker,把上面的yml文件放进去;
2. 在文件夹内运行docker-compose up -d
(后台启动);
3. 访问http://localhost:5601
——看到Kibana的登录页?恭喜,环境跑起来了!
用Filebeat采集日志:避免Logstash性能坑
接下来要解决”怎么把日志送进ELK”的问题。以Nginx访问日志为例,我写了一份Filebeat配置文件(filebeat.yml
),直接改路径就能用:
# Filebeat输入:采集Nginx日志
filebeat.inputs:
- type: log # 日志类型输入
enabled: true
paths:
- /var/log/nginx/access.log # 你的Nginx访问日志路径(要确保Filebeat有权限读)
fields: # 自定义字段,方便后续过滤
log_source: nginx_access
fields_under_root: true # 把自定义字段放到根级别(不用嵌套在fields里)
# 输出到Logstash(别直接发ES!要先清洗)
output.logstash:
hosts: ["localhost:5044"] # Logstash的地址+端口
# 连接Kibana(自动导入索引模式)
setup.kibana:
host: "http://localhost:5601"
启动Filebeat(Linux版):
./filebeat -e -c filebeat.yml
– -e
:把日志输出到终端(方便调试);
– -c
:指定配置文件路径。
如果看到Connected to logstash
的提示,说明采集成功了!
Logstash过滤与清洗:让日志变”干净”
Filebeat把日志送到Logstash后,下一步是把非结构化日志变成结构化数据。比如Nginx的access.log长这样:192.168.1.1 - - [10/May/2024:14:30:00 +0800] "GET /index.html HTTP/1.1" 200 1234 "-" "Mozilla/5.0..."
这种”字符串”没法分析——得用Logstash的grok插件解析成键值对。我写了一份Logstash pipeline配置(logstash/pipeline/nginx.conf
):
# 输入:接收Filebeat的日志
input {
beats {
port => 5044
}
}
# 过滤:只处理Nginx访问日志
filter {
if [log_source] == "nginx_access" { # 匹配Filebeat的自定义字段
# 1. 用grok解析Nginx日志(预定义模式%{NGINX_ACCESS_LOG})
grok {
match => { "message" => "%{NGINX_ACCESS_LOG}" }
remove_field => ["message"] # 解析完删除原始message字段,省空间
}
# 2. 校正时间戳(用日志里的时间代替Logstash接收时间)
date {
match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
target => "@timestamp" # 覆盖默认的@timestamp
}
# 3. 解析User-Agent(比如Chrome、iOS)
useragent {
source => "agent"
target => "user_agent"
}
# 4. 解析IP地理信息(比如中国、北京)
geoip {
source => "clientip"
target => "geoip"
}
}
}
# 输出:把清洗后的日志送进Elasticsearch
output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "nginx_access-%{+YYYY.MM.dd}" # 按天生成索引(比如nginx_access-2024.05.10)
}
}
关键说明:
– grok
是Logstash的”瑞士军刀”——如果预定义模式不够用,可以自己写正则(比如%{IP:clientip} %{USER:ident} %{USER:auth} [%{HTTPDATE:timestamp}] "%{WORD:method} %{URIPATHPARAM:request} HTTP/%{NUMBER:httpversion}" %{NUMBER:response} %{NUMBER:bytes}
);
– date
插件很重要!如果不用它,Elasticsearch会用Logstash的接收时间作为@timestamp
,导致日志时间线混乱;
– geoip
需要联网(或者下载GeoIP数据库到本地),能帮你快速定位异常IP(比如突然有大量美国IP访问你的中国网站)。
Elasticsearch索引管理:不做”存储垃圾桶”
很多人用Elasticsearch当”日志仓库”——不管什么日志都往里面扔,结果几个月后磁盘满了,查询速度慢到无法忍受。索引管理的核心是”按需存储”,我总结了两个必做操作:
1. 用索引模板统一配置
索引模板能帮你”预先定义”索引的设置(比如分片数、副本数)和映射(比如哪些字段是字符串,哪些是数字)。比如针对Nginx日志的模板:
PUT _index_template/nginx_access_template
{
"index_patterns": ["nginx_access-*"], # 匹配所有nginx_access开头的索引
"template": {
"settings": {
"number_of_shards": 1, # 分片数(单节点用1,多节点建议3)
"number_of_replicas": 0 # 副本数(测试用0,生产用1)
},
"mappings": {
"properties": {
"clientip": { "type": "ip" }, # IP类型(支持IP范围查询,比如192.168.0.0/16)
"response": { "type": "integer" }, # 响应状态码(整数类型,节省空间)
"bytes": { "type": "long" }, # 发送字节数(长整型)
"geoip": {
"properties": {
"country_name": { "type": "keyword" }, # 国家名称(不分词,适合聚合)
"city_name": { "type": "keyword" }
}
}
}
}
}
}
2. 用ILM做生命周期管理
ILM(Index Lifecycle Management)是Elasticsearch的”自动管家”——能帮你自动完成索引滚动、热温冷归档、删除。比如我配置了一个Nginx日志的ILM策略:
PUT _ilm/policy/nginx_access_policy
{
"policy": {
"phases": {
"hot": { # 热阶段:最近7天的日志(频繁查询)
"actions": {
"rollover": { "max_size": "50GB", "max_age": "7d" } # 达到50GB或7天就滚动新索引
}
},
"warm": { # 温阶段:7-30天的日志(偶尔查询)
"min_age": "7d",
"actions": {
"allocate": { "require": { "box_type": "warm" } } # 移到性能较低的温节点
}
},
"cold": { # 冷阶段:30-90天的日志(很少查询)
"min_age": "30d",
"actions": {
"freeze": {} # 冻结索引(减少内存占用)
}
},
"delete": { # 删除阶段:超过90天的日志(不用再查)
"min_age": "90d",
"actions": { "delete": {} }
}
}
}
}
效果:
– 热阶段的索引(最近7天)放在高性能SSD上,保证查询速度;
– 温阶段的索引移到普通硬盘,节省成本;
– 冷阶段的索引冻结(不能写,只能读),减少内存占用;
– 超过90天的索引自动删除,不用手动清理。
Kibana可视化:把日志变成可行动的 insights
终于到了最”直观”的一步——用Kibana把日志变成能帮你解决问题的Dashboard。我以Nginx访问日志为例,教你做一个”运维监控Dashboard”,包含5个核心图表:
1. 实时请求数趋势图(Line Chart)
- 作用:快速发现流量峰值(比如晚上8点突然有10倍请求);
- 配置步骤:
- 进入Kibana → Visualize Library → 选择Line Chart;
- 选择索引模式
nginx_access-*
; - X轴选
@timestamp
,间隔设为”1分钟”; - Y轴选”Count”(请求数);
- 保存为”实时请求数趋势”。
2. 响应状态码分布(Vertical Bar Chart)
- 作用:快速定位错误(比如突然有大量500错误,说明后端服务挂了);
- 配置步骤:
- 选择Vertical Bar Chart;
- X轴选
response
(响应状态码); - Y轴选”Count”;
- 保存为”响应状态码分布”。
3. 地理分布热力图(Region Map)
- 作用:发现异常IP(比如突然有大量印度IP访问你的中国网站);
- 配置步骤:
- 选择Region Map;
- 选择”Count”作为聚合方式;
- 选择
geoip.country_name
作为地理位置字段; - 保存为”访问地理分布”。
4. 整合Dashboard
把上面的图表拖进Dashboard,就能得到一个实时监控面板:
– 左边是请求数趋势图,中间是状态码分布,右边是地理热力图;
– 鼠标悬停在图表上能看具体数据(比如2024-05-10 14:30有1200次请求,其中30次是404错误)。
真实场景案例:
我之前用这个Dashboard帮公司解决过一个问题——某天晚上10点,请求数突然涨到平时的5倍,状态码里404占了30%。我通过”地理分布”发现这些请求都来自美国,再看”User-Agent”都是”Python-urllib/3.8″(爬虫)。最后用Nginx配置禁止了美国IP,流量立刻降回正常。
最后想说的话
ELK Stack不是”银弹”——它适合处理结构化/半结构化日志(比如Nginx、Java应用、系统日志),如果是纯文本日志(比如随机生成的字符串),可能需要先做正则解析。另外,生产环境建议用Elastic Cloud(托管版ELK),能省掉运维的麻烦(比如集群扩容、版本升级)。
如果你在部署过程中遇到问题(比如Filebeat连不上Logstash,Kibana看不到索引),可以查这三个日志:
1. Filebeat日志:./filebeat -e -c filebeat.yml
(看有没有报错);
2. Logstash日志:docker logs logstash
(看pipeline有没有语法错误);
3. Elasticsearch日志:docker logs elasticsearch
(看有没有内存不足或权限问题)。
总之,ELK Stack的核心是”数据驱动“——别为了”用ELK”而用ELK,要先想清楚你要解决什么问题(比如定位应用错误、监控系统性能、分析用户行为),再用ELK的组件去实现。
原创文章,作者:,如若转载,请注明出处:https://zube.cn/archives/322