ES原理与Filebeat日志采集全攻略

ES原理与Filebeat日志采集全攻略

一、概述

本文全面覆盖ElasticSearch(ES)核心原理与Filebeat日志采集实战,包含ES倒排索引底层机制、节点角色分类与主从分离部署、Filebeat两种安装方式(RPM/二进制)、多类型输入插件(stdin/tcp/log)、数据处理器配置、Nginx/Tomcat/ES/Docker等多场景日志采集,以及Filebeat数据丢失故障处理方案。内容从原理到实操层层递进,命令清晰、案例丰富,助力快速掌握ES集群角色规划与日志采集标准化配置能力。

二、核心知识点

2.1 ES核心原理(底层存储与检索)

索引类型 核心定义 检索方式 适用场景 性能对比
正排索引(正向索引) 按文档ID关联数据,如MySQL主键索引 全表扫描(无索引时) 关系型数据库(如MySQL) 10亿文档查询耗时久
倒排索引(反向索引) 按词条关联文档ID,含词典+倒排表 词条匹配→倒排表查询→文档定位 ES全文检索 10亿文档查询毫秒级响应

倒排索引核心组成

  1. 词条:最小查询单元(英文为单词,中文为词组);
  2. 词典:词条集合,底层基于Btree+HashMap实现,快速匹配词条;
  3. 倒排表:记录词条出现的文档ID、频率、位置,每条记录为倒排项。

2.2 ES节点角色分类(常用)

角色标识 角色名称 核心功能 配置参数
m 主节点(master node) 维护集群状态、管理索引元数据、主分片选举 node.master: true
d 数据节点(data node) 存储数据、执行数据读写、分片管理 node.data: true
c 协调节点(coordinating node) 接收客户端请求、分发任务、聚合结果 所有节点默认是协调节点,不可取消
i 预处理节点(ingest node) 数据写入前预处理(如过滤、转换) node.ingest: true
h 热节点(hot node) 存储热点数据(高频读写) 需配合索引生命周期管理(ILM)
w 温节点(warm node) 存储温数据(低频读写) 需配合ILM
c 冷节点(cold node) 存储冷数据(只读) 需配合ILM

2.3 Filebeat核心概念

组件 核心作用 关键特性
Input 数据输入端,采集源数据 支持stdin/tcp/log/file等多种类型
Output 数据输出端,发送处理后的数据 支持console/elasticsearch/kafka等
Processors 数据处理器,预处理数据 支持过滤、字段修改、类型转换等
Modules 预配置模块,快速采集主流软件日志 内置Nginx/Tomcat/MySQL等模块

2.4 Filebeat Input插件类型(常用)

插件类型 适用场景 核心配置
stdin 标准输入测试,快速验证配置 type: stdin
tcp 采集TCP端口接收的数据 type: tcp + host: 0.0.0.0:端口
log 采集文件日志(核心场景) type: log + paths: 日志路径

2.5 Filebeat核心处理器(常用)

处理器类型 功能 适用场景
drop_event 丢弃符合条件的事件 过滤无效日志(如以linux开头的消息)
drop_fields 丢弃指定字段 移除冗余字段(如自定义标签、临时字段)
rename 重命名字段 规范字段名称(如school→学校)
convert 转换字段类型 如字符串IP→ip类型、字符串端口→整数类型

三、步骤/命令

3.1 ES主从角色分离实战(生产推荐)

操作场景:分离主节点与数据节点,提升集群稳定性(主节点专注集群管理,数据节点专注数据存储)

# 前提:已部署3节点ES集群(elk101/102/103),当前为混合角色

# 1. 所有节点停止ES服务
⭐️systemctl stop es7

# 2. 所有节点清空历史数据(避免角色切换冲突)
rm -rf /oldboya/{data,logs}/es7/* /tmp/*

# 3. 分别修改各节点配置文件
# 3.1 数据节点(elk101/102):仅开启data角色,关闭master角色
cat > /oldboya/softwares/es7/elasticsearch-7.17.5/config/elasticsearch.yml << EOF
cluster.name: oldboya-linux85-binary
path.data: /oldboya/data/es7
path.logs: /oldboya/logs/es7
network.host: 0.0.0.0
discovery.seed_hosts: ["elk101.oldboya.com","elk102.oldboya.com","elk103.oldboya.com"]
cluster.initial_master_nodes: ["elk103.oldboya.com"]  # 指定主节点候选
node.master: false  # 关闭master角色
node.data: true     # 开启data角色
EOF

# 3.2 主节点(elk103):仅开启master角色,关闭data角色
cat > /oldboya/softwares/es7/elasticsearch-7.17.5/config/elasticsearch.yml << EOF
cluster.name: oldboya-linux85-binary
path.data: /oldboya/data/es7
path.logs: /oldboya/logs/es7
network.host: 0.0.0.0
discovery.seed_hosts: ["elk101.oldboya.com","elk102.oldboya.com","elk103.oldboya.com"]
cluster.initial_master_nodes: ["elk103.oldboya.com"]
node.master: true  # 开启master角色
node.data: false   # 关闭data角色
EOF

# 4. 所有节点启动ES服务
systemctl start es7

# 5. 效果验证(查看节点角色)
⭐️curl 10.0.0.101:9200/_cat/nodes
# 输出说明:elk103标识含"m"(主节点),不含"d"(非数据节点);elk101/102含"d"(数据节点),不含"m"

# 6. 创建索引测试(验证主节点不存储分片)
curl -X PUT 10.0.0.101:9200/oldboya-linux85 -H "Content-Type: application/json" -d '{
    "settings":{
        "number_of_shards": 10,
        "number_of_replicas":0
    }
}'
# 验证分片分配:主节点(elk103)无分片,分片仅分配在elk101/102
curl 10.0.0.101:9200/_cat/shards/oldboya-linux85

3.2 Filebeat安装(RPM/二进制)

3.2.1 RPM安装(快速部署)

# 1. 下载Filebeat RPM包(与ES版本一致:7.17.5)
⭐️wget http://192.168.15.253/ElasticStack/day04-/filebeat-7.17.5-x86_64.rpm

# 2. 安装Filebeat
rpm -ivh filebeat-7.17.5-x86_64.rpm  # -i:安装,-v:显示过程,-h:进度条

# 3. 效果验证(查看帮助文档)
filebeat -h  # 输出帮助信息即为安装成功

3.2.2 二进制安装(自定义路径,生产推荐)

# 1. 下载Filebeat二进制包
wget http://192.168.15.253/ElasticStack/day04-/filebeat-7.17.5-linux-x86_64.tar.gz

# 2. 解压到自定义目录
⭐️tar xf filebeat-7.17.5-linux-x86_64.tar.gz -C /oldboya/softwares/

# 3. 创建软链接(方便全局调用)
ln -svf /oldboya/softwares/filebeat-7.17.5-linux-x86_64/filebeat /usr/local/sbin/

# 4. 效果验证
filebeat -h  # 输出帮助信息即为安装成功

3.3 Filebeat Input插件实操

3.3.1 标准输入(stdin)→ 控制台输出

操作场景:快速验证Filebeat配置是否生效

# 1. 创建配置文件(二进制安装路径为例)
cd /oldboya/softwares/filebeat-7.17.5-linux-x86_64
mkdir -p config
⭐️cat > config/01-stdin-to-console.yaml << EOF
filebeat.inputs:
- type: stdin  # 输入类型:标准输入
output.console:
  pretty: true  # 格式化输出,便于查看
EOF

# 2. 启动Filebeat
filebeat -e -c config/01-stdin-to-console.yaml  # -e:日志输出到控制台,-c:指定配置文件

# 3. 效果验证
# 在启动后的终端输入任意内容(如"test filebeat stdin input"),控制台会输出格式化的日志数据

3.3.2 TCP输入 → 控制台输出

操作场景:采集TCP端口接收的日志数据

# 1. 创建配置文件
cat > config/02-tcp-to-console.yaml << EOF
filebeat.inputs:
- type: tcp
  host: 0.0.0.0:8888  # 监听所有网卡的8888端口
output.console:
  pretty: true
EOF

# 2. 启动Filebeat
filebeat -e -c config/02-tcp-to-console.yaml

# 3. 客户端测试(另一台节点执行)
# 3.1 安装测试工具
yum -y install nc telnet

# 3.2 发送测试数据
echo "Filebeat TCP input test" | nc 10.0.0.103 8888  # 10.0.0.103为Filebeat部署节点IP

# 4. 效果验证:Filebeat控制台会输出接收到的TCP数据

3.3.3 日志文件(log)→ 控制台输出

操作场景:采集指定路径的日志文件(支持递归匹配)

# 1. 创建配置文件
cat > config/03-log-to-console.yaml << EOF
filebeat.inputs:
- type: log
  paths:
    - /tmp/oldboya-linux85/*.log  # 匹配/tmp下的.log文件
    - /tmp/oldboya-linux85/**/*.json  # 递归匹配所有子目录的.json文件
output.console:
  pretty: true
EOF

# 2. 启动Filebeat
filebeat -e -c config/03-log-to-console.yaml

# 3. 测试数据(创建测试日志)
mkdir -p /tmp/oldboya-linux85
echo '{"message":"test log input","time":"2024-01-01 10:00:00"}' > /tmp/oldboya-linux85/test.log

# 4. 效果验证:Filebeat控制台会输出解析后的日志数据

3.4 Filebeat处理器配置(数据预处理)

操作场景:对采集的TCP数据进行标签添加、字段转换、过滤

# 1. 创建配置文件
⭐️cat > config/04-input-common-options.yaml << EOF
filebeat.inputs:
- type: tcp
  enabled: true
  host: "0.0.0.0:8888"
  tags: ["jiaoshi05","linux85","oldboya"]  # 添加标签字段
  fields:  # 自定义字段
    school: oldboya
    class: linux85
    ip: 219.141.136.10
    port: 13306
  fields_under_root: true  # 自定义字段提升为顶级字段(默认在fields下)
  processors:
    # 丢弃以"linux"开头的消息
  - drop_event:
      when:
        regexp:
          message: "^linux"
    # 消息含"error"时,丢弃class和tags字段
  - drop_fields:
      when:
        contains:
          message: "error"
      fields: ["class","tags"]
      ignore_missing: false  # 字段不存在时报错(默认true忽略)
    # 重命名字段
  - rename:
      fields:
        - from: "school"
          to: "学校"
        - from: "log"
          to: "日志"
    # 转换字段类型(ip→ip类型,port→整数类型)
  - convert:
      fields:
        - {from: "ip", to: "oldboya-linux85.jiaoshi07_ip", type: "ip"}
        - {from: "port", to: "oldboya-linux85.jiaoshi07_port", type: "integer"}
output.console:
  pretty: true
EOF

# 2. 启动Filebeat
filebeat -e -c config/04-input-common-options.yaml

# 3. 测试验证
# 3.1 发送以"linux"开头的消息(会被丢弃)
echo "linux test drop event" | nc 10.0.0.103 8888

# 3.2 发送含"error"的消息(class和tags字段被丢弃)
echo "test error drop fields" | nc 10.0.0.103 8888

# 3.3 发送正常消息(字段重命名和类型转换生效)
echo "test processor success" | nc 10.0.0.103 8888

3.5 多场景日志采集实战

3.5.1 采集Nginx日志(JSON格式)

# 1. 搭建Nginx环境(若未安装)
# 1.1 添加Nginx YUM源
cat > /etc/yum.repos.d/nginx.repo <<'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF

# 1.2 安装并启动Nginx
yum -y install nginx
systemctl start nginx

# 1.3 配置Nginx输出JSON格式日志
⭐️vim /etc/nginx/nginx.conf
# 注释原有log_format,添加JSON格式配置
log_format oldboya_nginx_json '{"@timestamp":"$time_iso8601",'
                              '"host":"$server_addr",'
                              '"clientip":"$remote_addr",'
                              '"SendBytes":$body_bytes_sent,'
                              '"responsetime":$request_time,'
                              '"upstreamtime":"$upstream_response_time",'
                              '"upstreamhost":"$upstream_addr",'
                              '"http_host":"$host",'
                              '"uri":"$uri",'
                              '"domain":"$host",'
                              '"xff":"$http_x_forwarded_for",'
                              '"referer":"$http_referer",'
                              '"tcp_xff":"$proxy_protocol_addr",'
                              '"http_user_agent":"$http_user_agent",'
                              '"status":"$status"}';
access_log  /var/log/nginx/access.log  oldboya_nginx_json;

# 1.4 热加载Nginx配置
systemctl reload nginx
> /var/log/nginx/access.log  # 清空原有日志

# 2. 创建Filebeat配置文件
cat > config/07-nginx-json-to-console.yaml << EOF
filebeat.inputs:
- type: log
  paths:
    - /var/log/nginx/access.log*
  json.keys_under_root: true  # JSON字段提升为顶级字段
  json.add_error_key: true    # 解析失败时添加error字段
output.console:
  pretty: true
EOF

# 3. 启动Filebeat并测试
filebeat -e -c config/07-nginx-json-to-console.yaml
# 访问Nginx生成日志
curl http://10.0.0.103/
# 效果验证:Filebeat控制台输出解析后的JSON格式Nginx日志

3.5.2 采集Tomcat日志(访问日志+错误日志多行匹配)

# 1. 搭建Tomcat环境
# 1.1 下载并解压Tomcat
wget http://192.168.15.253/ElasticStack/day04-/apache-tomcat-9.0.73.tar.gz
tar xf apache-tomcat-9.0.73.tar.gz -C /oldboya/softwares/

# 1.2 配置Tomcat输出JSON格式访问日志
⭐️vim /oldboya/softwares/apache-tomcat-9.0.73/conf/server.xml
# 修改Host节点配置(约133-149行)
<Host name="tomcat.oldboya.com"  appBase="webapps"
      unpackWARs="true" autoDeploy="true">
  <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
         prefix="tomcat.oldboya.com_access_log" suffix=".txt"
pattern="{&quot;clientip&quot;:&quot;%h&quot;,&quot;ClientUser&quot;:&quot;%l&quot;,&quot;authenticated&quot;:&quot;%u&quot;,&quot;AccessTime&quot;:&quot;%t&quot;,&quot;request&quot;:&quot;%r&quot;,&quot;status&quot;:&quot;%s&quot;,&quot;SendBytes&quot;:&quot;%b&quot;,&quot;Query?string&quot;:&quot;%q&quot;,&quot;partner&quot;:&quot;%{Referer}i&quot;,&quot;http_user_agent&quot;:&quot;%{User-Agent}i&quot;}"/>
</Host>

# 1.3 配置环境变量并启动Tomcat
cat > /etc/profile.d/tomcat.sh <<EOF
export TOMCAT_HOME=/oldboya/softwares/apache-tomcat-9.0.73
export PATH=\$PATH:\$TOMCAT_HOME/bin
EOF
source /etc/profile.d/tomcat.sh
catalina.sh start

# 2. 采集Tomcat访问日志(JSON格式)
cat > config/08-tomcat-access-to-console.yaml << EOF
filebeat.inputs:
- type: log
  paths:
    - /oldboya/softwares/apache-tomcat-9.0.73/logs/tomcat.oldboya.com_access_log*.txt
  json.keys_under_root: true
  json.add_error_key: true
output.console:
  pretty: true
EOF
filebeat -e -c config/08-tomcat-access-to-console.yaml

# 3. 采集Tomcat错误日志(多行匹配,合并堆栈信息)
⭐️cat > config/09-tomcat-error-to-es.yaml << EOF
filebeat.inputs:
- type: log
  paths:
    - /oldboya/softwares/apache-tomcat-9.0.73/logs/catalina*
  # 多行匹配配置:合并以非数字开头的行(堆栈信息)
  multiline.type: pattern
  multiline.pattern: '^\d{2}'  # 匹配以两位数字开头的行(日志时间)
  multiline.negate: true       # 否定匹配(非数字开头的行)
  multiline.match: after       # 合并到上一行之后
output.elasticsearch:
  hosts: ["http://10.0.0.101:9200","http://10.0.0.102:9200","http://10.0.0.103:9200"]
EOF

# 4. 启动Filebeat并验证
filebeat -e -c config/09-tomcat-error-to-es.yaml
# 效果验证:ES中会创建filebeat索引,包含合并后的Tomcat错误日志
curl 10.0.0.101:9200/_cat/indices?v | grep filebeat

3.5.3 采集ES启动日志并写入ES

# 1. 创建Filebeat配置文件
cat > config/10-es-log-to-es.yaml << EOF
filebeat.inputs:
- type: log
  paths:
    - /oldboya/logs/es7/elasticsearch.log*  # ES日志路径
  tags: ["es-log","elk-cluster"]
output.elasticsearch:
  hosts: ["http://10.0.0.101:9200","http://10.0.0.102:9200","http://10.0.0.103:9200"]
  index: "es-logs-%{+yyyy.MM.dd}"  # 按日期拆分索引
EOF

# 2. 启动Filebeat
filebeat -e -c config/10-es-log-to-es.yaml

# 3. 效果验证
curl 10.0.0.101:9200/_cat/indices?v | grep es-logs-$(date +%Y.%m.%d)

3.6 Filebeat数据丢失故障处理

故障案例:Filebeat崩溃导致4-5点数据未采集

现象:Filebeat在16:00崩溃,16:00-17:00的日志未采集到ES,仅存16点前和17点后的数据。
原因:Filebeat崩溃后停止日志采集,源日志文件未丢失,可通过重新读取日志文件恢复数据。
解决方案

# 1. 修复Filebeat故障(如重启服务、修复配置)
systemctl restart filebeat  # RPM安装
# 或二进制安装:pkill filebeat && filebeat -e -c 配置文件

# 2. 配置Filebeat重新读取历史日志(启用回溯采集)
⭐️cat > config/11-recover-logs.yaml << EOF
filebeat.inputs:
- type: log
  paths:
    - /var/log/nginx/access.log*  # 源日志文件路径
  ignore_older: 24h  # 读取24小时内的日志(覆盖丢失时段)
  scan_frequency: 10s  # 扫描频率
  harvester_limit: 1000  # 最大并发采集数
output.elasticsearch:
  hosts: ["http://10.0.0.101:9200"]
  index: "nginx-recover-logs-%{+yyyy.MM.dd}"
EOF

# 3. 启动Filebeat执行数据恢复
filebeat -e -c config/11-recover-logs.yaml

# 4. 验证恢复结果
curl 10.0.0.101:9200/nginx-recover-logs-$(date +%Y.%m.%d)/_search -H "Content-Type: application/json" -d '{
    "query": {
        "range": {
            "@timestamp": {
                "gte": "2024-01-01T16:00:00",
                "lte": "2024-01-01T17:00:00"
            }
        }
    }
}'

四、原理说明

4.1 倒排索引工作机制

倒排索引是ES实现快速全文检索的核心,工作流程分为“索引构建”和“检索”两步:

  1. 索引构建
    • 对文档内容进行分词,提取词条(如“我爱Linux”分词为“我”“爱”“Linux”);
    • 将词条存入词典(Btree+HashMap),建立词条与倒排表的映射;
    • 记录每个词条在文档中的位置、频率,生成倒排项,组成倒排表。
  2. 检索流程
    • 用户输入查询词,分词后匹配词典中的词条;
    • 若词条存在,获取对应的倒排表,得到包含该词条的文档ID;
    • 按词条频率、位置计算文档相关性得分,返回排序后的结果。

4.2 ES文档读写流程

文档写入流程:

  1. 客户端请求发送到协调节点;
  2. 协调节点通过hash(文档ID) % 主分片数计算目标主分片;
  3. 协调节点将请求转发到目标主分片所在的数据节点;
  4. 主分片写入数据并同步到所有副本分片;
  5. 所有副本分片写入成功后,主分片返回成功响应给协调节点,再由协调节点返回给客户端。

文档读取流程:

  1. 客户端请求发送到协调节点;
  2. 协调节点计算目标主分片,随机选择一个主分片或副本分片作为读取节点;
  3. 读取节点返回数据给协调节点;
  4. 协调节点返回数据给客户端(若需聚合,协调节点会汇总所有分片数据后返回)。

4.3 Filebeat日志采集原理

Filebeat通过“采集器(Harvester)”和“ prospector”实现日志采集:

  1. Prospector:扫描配置的日志路径,发现新文件并为每个文件启动一个Harvester;
  2. Harvester:打开文件句柄,逐行读取日志内容,发送到输出端;
  3. 状态持久化:Filebeat会记录每个文件的读取位置(offset),存储在data/registry目录,重启后可从上次位置继续读取,避免重复采集;
  4. 多行匹配原理:通过pattern匹配日志起始行,将非起始行合并到上一行,解决错误日志堆栈信息拆分问题(如Tomcat错误日志的多行堆栈)。

4.4 Filebeat处理器工作原理

Processors是Filebeat的数据预处理模块,在数据从Input到Output的传输过程中执行操作,核心原理:

  1. 数据按处理器配置的顺序依次处理(如先过滤再转换);
  2. 每个处理器独立工作,修改后的字段会传递给下一个处理器;
  3. 处理器仅修改内存中的数据,不改变源日志文件;
  4. 支持条件判断(when),仅对符合条件的事件执行处理操作,提升效率。

五、注意事项

  1. ES角色分离配置:主节点建议单独部署,避免数据节点负载过高影响集群稳定性;生产环境主节点至少配置2个(候选主节点),防止单点故障;
  2. Filebeat配置语法:YAML配置严格区分缩进(建议2空格),字符串含特殊字符需加引号,避免语法错误;
  3. 日志路径配置:使用paths时,避免配置过大的目录(如/var/log/*),建议精准匹配(如/var/log/nginx/access.log*),提升扫描效率;
  4. 多行匹配规则pattern需精准匹配日志起始行(如Tomcat错误日志以日期开头),否则会导致日志合并异常;
  5. 数据去重:Filebeat依赖registry文件记录读取位置,若删除该文件,会导致日志重复采集,生产环境需备份data/registry目录;
  6. 性能优化:采集大量日志时,可增加harvester_limit(并发采集数)、worker(输出线程数),避免队列阻塞;
  7. JSON日志解析:确保源日志为标准JSON格式,否则json.keys_under_root: true会解析失败,需启用json.add_error_key: true排查错误;
  8. 权限控制:Filebeat需拥有日志文件的读取权限,若日志文件权限为600(root仅读),需配置filebeat.yml中的user: root(RPM安装)或使用sudo启动(二进制安装)。

六、结尾

总结

本文核心覆盖两大模块:一是ES底层原理与集群配置,包括倒排索引机制、节点角色分类、主从分离部署,为日志存储与检索提供基础;二是Filebeat日志采集实战,涵盖两种安装方式、多类型输入插件、数据处理器配置,以及Nginx/Tomcat/ES/Docker等主流场景的日志采集方案,同时包含数据丢失故障的恢复方法。通过“原理+实操”的组合,形成了从日志采集、传输到存储的完整链路解决方案,可直接应用于生产环境的ELK/EFK架构搭建。

避坑指南(核心坑点+解决方案)

  1. 坑点:ES主从分离后,主节点无法选举;解决方案:确保cluster.initial_master_nodes配置的节点node.master: true,且所有节点的cluster.name一致,关闭防火墙或开放9300端口;
  2. 坑点:Filebeat采集不到日志,无报错;解决方案:检查日志路径是否正确、Filebeat是否有读取权限、日志文件是否被ignore_older过滤(默认72小时);
  3. 坑点:Tomcat错误日志被拆分为多行,无法查看完整堆栈;解决方案:配置multiline参数,精准匹配日志起始行,合并非起始行;
  4. 坑点:JSON日志解析后字段缺失;解决方案:启用json.add_error_key: true,查看error字段排查JSON格式错误(如引号不匹配、逗号缺失);
  5. 坑点:Filebeat重启后重复采集日志;解决方案:避免删除data/registry目录,若需重新采集,可通过clean_inactive参数清理过期状态;
  6. 坑点:ES索引分片仅分配在部分数据节点;解决方案:检查数据节点的node.data: true配置,确保节点正常加入集群,且磁盘空间充足(磁盘使用率超过85%会停止分配分片)。
posted @ 2026-03-22 22:49  gzjwo  阅读(2)  评论(0)    收藏  举报