前言
日志是系统的"黑匣子",但在微服务和容器化时代,日志分散在各个服务器上,排查问题往往需要登录多台机器grep,效率极低。ELK Stack(Elasticsearch + Logstash + Kibana + Beats)正是为解决这一痛点而生的业界标准方案。
本文将带您从零开始 ,基于 Elastic Stack 8.18.8 版本,搭建一套三节点分布式 日志采集与可视化平台。架构覆盖 Filebeat(采集)→ Logstash(过滤)→ Elasticsearch(存储)→ Kibana(展示) 完整链路,并对每一环节提供详细配置与验证方法。
📌 适用人群:运维工程师、开发工程师、SRE,以及所有对日志系统感兴趣的技术爱好者。
一、系统架构与主机规划
1.1 整体架构图
text
+----------------+ +----------------+ +----------------+
| Node-3 | | Node-2 | | Node-1 |
| (Filebeat) | ----> | (Logstash) | ----> | (ES + Kibana) |
| 日志采集端 | 5044 | 日志处理端 | 9200 | 存储与展示端 |
+----------------+ +----------------+ +----------------+
1.2 主机规划
| 主机名 | IP 地址 | 部署组件 | 角色说明 |
|---|---|---|---|
| node1 | 192.168.194.10 | Elasticsearch + Kibana | 数据存储与可视化展示 |
| node2 | 192.168.194.11 | Logstash | 日志解析、过滤与路由 |
| node3 | 192.168.194.12 | Filebeat | 业务服务器日志采集 |
生产环境建议 ES 集群至少 3 台,本文为入门演示采用"单ES节点 + 独立Logstash + Filebeat"分布式架构。
二、前置准备(所有节点执行)
2.1 设置主机名
bash
# 各节点分别执行
hostnamectl set-hostname node1 && bash # node1
hostnamectl set-hostname node2 && bash # node2
hostnamectl set-hostname node3 && bash # node3
2.2 关闭 SELinux 与防火墙(测试环境)
bash
# 永久关闭 SELinux
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
2.3 配置主机名解析
bash
cat >> /etc/hosts <<EOF
192.168.194.10 node1
192.168.194.11 node2
192.168.194.12 node3
EOF
2.4 安装 JDK 环境
bash
# 方案一:使用系统源安装 OpenJDK 25
dnf install -y java-25-openjdk
echo "export JAVA_HOME=/usr/lib/jvm/java-25-openjdk" >> /etc/profile
source /etc/profile
# 方案二:手动安装 Oracle JDK(推荐生产环境)
tar -zxf jdk-25_linux-x64_bin.tar.gz -C /usr/local/
vim /etc/profile
# 在文件末尾添加:
export JAVA_HOME=/usr/local/jdk-25.0.3
export PATH=$PATH:$JAVA_HOME/bin
source /etc/profile
# 验证安装
java -version
# 应显示:java version "25.0.3" ...
2.5 创建 ELK 专用用户(禁止 root 运行)
bash
useradd -m -s /bin/bash elk
passwd elk # 设置密码
# 创建相关目录并授权
mkdir -p /opt/elk /opt/logs/{es,logstash,filebeat}
chown -R elk:elk /opt/{elk,logs}
2.6 系统参数调优(必须)
bash
# 1. 最大文件句柄数
cat >> /etc/security/limits.conf <<EOF
elk soft nofile 65535
elk hard nofile 65535
elk soft nproc 40960
elk hard nproc 40960
EOF
# 2. 虚拟内存映射区域(ES 需要)
echo "vm.max_map_count=262144" >> /etc/sysctl.conf
sysctl -p
2.7 下载安装包(各节点分别下载对应组件)
bash
# node1 下载 ES + Kibana
cd /opt/elk
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.18.8-linux-x86_64.tar.gz
wget https://artifacts.elastic.co/downloads/kibana/kibana-8.18.8-linux-x86_64.tar.gz
# node2 下载 Logstash
wget https://artifacts.elastic.co/downloads/logstash/logstash-8.18.8-linux-x86_64.tar.gz
# node3 下载 Filebeat
wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.18.8-linux-x86_64.tar.gz
三、Node1:Elasticsearch + Kibana 部署
3.1 Elasticsearch 安装配置
3.1.1 解压部署
bash
cd /opt/elk
tar -zxvf elasticsearch-8.18.8-linux-x86_64.tar.gz
mv elasticsearch-8.18.8 es
chown -R elk:elk /opt/elk/es
3.1.2 核心配置文件 elasticsearch.yml
bash
cat > /opt/elk/es/config/elasticsearch.yml <<EOF
# 集群名称
cluster.name: elk-cluster
# 节点名称
node.name: node1
# 数据与日志存储路径
path.data: /opt/logs/es
path.logs: /opt/logs/es
# 网络配置
network.host: 0.0.0.0
http.port: 9200
# 单节点模式(生产环境可改为集群模式)
discovery.type: single-node
# 关闭安全认证(简化测试,生产务必开启)
xpack.security.enabled: false
xpack.security.enrollment.enabled: false
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false
EOF
3.1.3 JVM 内存调整
bash
vim /opt/elk/es/config/jvm.options
# 根据物理内存调整(测试环境2G内存设为1G)
-Xms1g
-Xmx1g
3.1.4 创建 Systemd 服务
bash
cat > /usr/lib/systemd/system/elasticsearch.service <<EOF
[Unit]
Description=Elasticsearch Service
After=network.target
[Service]
User=elk
Group=elk
ExecStart=/opt/elk/es/bin/elasticsearch
Restart=always
RestartSec=5
LimitNOFILE=65535
LimitNPROC=40960
[Install]
WantedBy=multi-user.target
EOF
3.1.5 启动并验证
bash
systemctl daemon-reload
systemctl enable elasticsearch --now
# 查看启动日志
tail -f /opt/logs/es/elasticsearch.log
# 验证服务
curl http://127.0.0.1:9200
预期返回:
json
{
"name" : "node1",
"cluster_name" : "elk-cluster",
"version" : { "number" : "8.18.8", ... },
"tagline" : "You Know, for Search"
}
或者直接访问:http://192.168.194.10:9200

3.2 Kibana 安装配置
3.2.1 解压部署
bash
cd /opt/elk
tar -zxvf kibana-8.18.8-linux-x86_64.tar.gz
mv kibana-8.18.8 kibana
chown -R elk:elk /opt/elk/kibana
3.2.2 配置文件 kibana.yml
bash
vim /opt/elk/kibana/config/kibana.yml
# 添加以下内容:
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://192.168.194.10:9200"]
i18n.locale: "zh-CN"
# 注:8.x 版本中 xpack.security.enabled 已在 kibana.yml 中废弃
3.2.3 创建 Systemd 服务
bash
cat > /usr/lib/systemd/system/kibana.service <<EOF
[Unit]
Description=Kibana Service
After=network.target elasticsearch.service
[Service]
User=elk
Group=elk
ExecStart=/opt/elk/kibana/bin/kibana
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
3.2.4 启动并访问
bash
systemctl daemon-reload
systemctl enable kibana --now
# 检查端口
ss -tlnp | grep 5601
浏览器访问 http://192.168.194.10:5601,看到 Kibana 中文界面即为成功。

四、Node2:Logstash 部署(日志处理中间层)
4.1 解压部署
bash
cd /opt/elk
tar -zxvf logstash-8.18.8-linux-x86_64.tar.gz
mv logstash-8.18.8 logstash
mkdir -p /opt/elk/logstash/pipeline /opt/logs/logstash
chown -R elk:elk /opt/elk/logstash /opt/logs/logstash
4.2 配置管道文件
4.2.1 配置 pipelines.yml
bash
cat > /opt/elk/logstash/config/pipelines.yml <<'EOF'
- pipeline.id: filebeat-to-elasticsearch
path.config: "/opt/elk/logstash/pipeline/log-pipeline.conf"
pipeline.workers: 1
pipeline.batch.size: 125
EOF
4.2.2 配置核心管道 log-pipeline.conf
bash
cat > /opt/elk/logstash/pipeline/log-pipeline.conf <<'EOF'
input {
beats {
port => 5044
}
}
filter {
if [type] == "syslog" {
grok {
match => {
"message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}"
}
}
date {
match => [ "syslog_timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss" ]
}
mutate {
remove_field => ["[agent][version]", "ecs"]
}
}
}
output {
elasticsearch {
hosts => ["http://192.168.194.10:9200"]
index => "logs-%{+YYYY.MM.dd}"
}
stdout { codec => rubydebug }
}
EOF
4.2.3 配置日志路径
bash
echo 'path.logs: /opt/logs/logstash' >> /opt/elk/logstash/config/logstash.yml
4.2.4 调整 JVM 内存
bash
vim /opt/elk/logstash/config/jvm.options
-Xms512m
-Xmx512m
4.3 验证配置文件
bash
runuser -u elk -- /opt/elk/logstash/bin/logstash \
--path.settings /opt/elk/logstash/config \
--config.test_and_exit
预期输出包含:Configuration OK. Exiting Logstash
4.4 创建 Systemd 服务
bash
cat > /usr/lib/systemd/system/logstash.service <<'EOF'
[Unit]
Description=Logstash Service
After=network-online.target
Wants=network-online.target
[Service]
User=elk
Group=elk
WorkingDirectory=/opt/elk/logstash
ExecStart=/opt/elk/logstash/bin/logstash --path.settings /opt/elk/logstash/config
Restart=on-failure
RestartSec=10
LimitNOFILE=65535
TimeoutStartSec=300
[Install]
WantedBy=multi-user.target
EOF
4.5 启动服务
bash
systemctl daemon-reload
systemctl enable --now logstash
# 验证端口监听
ss -lntp | grep ':5044'
五、Node3:Filebeat 部署(日志采集客户端)
5.1 解压部署
bash
cd /opt/elk
tar -zxvf filebeat-8.18.8-linux-x86_64.tar.gz
mv filebeat-8.18.8 filebeat
mkdir -p /opt/logs/filebeat /opt/elk/filebeat/data
chown -R elk:elk /opt/elk/filebeat /opt/logs/filebeat
# 授权读取系统日志
setfacl -m u:elk:r /var/log/messages /var/log/secure 2>/dev/null || true
setfacl -m u:elk:r /var/log/nginx/access.log 2>/dev/null || true
5.2 配置 filebeat.yml
bash
cat > /opt/elk/filebeat/filebeat.yml <<'EOF'
filebeat.inputs:
- type: filestream
id: node3-system-logs
enabled: true
paths:
- /var/log/messages
- /var/log/secure
- /var/log/nginx/access.log
fields:
type: syslog
fields_under_root: true
filebeat.registry.path: /opt/elk/filebeat/data/registry
output.logstash:
hosts: ["192.168.194.11:5044"]
logging.to_files: true
logging.files:
path: /opt/logs/filebeat
name: filebeat
keepfiles: 7
EOF
chown elk:elk /opt/elk/filebeat/filebeat.yml
5.3 验证配置与连通性
bash
# 测试配置文件语法
runuser -u elk -- /opt/elk/filebeat/filebeat test config \
-c /opt/elk/filebeat/filebeat.yml
# 测试到 Logstash 的连接
runuser -u elk -- /opt/elk/filebeat/filebeat test output \
-c /opt/elk/filebeat/filebeat.yml
预期分别看到 Config OK 和连接 192.168.194.11:5044 成功。
5.4 创建 Systemd 服务
bash
cat > /usr/lib/systemd/system/filebeat.service <<'EOF'
[Unit]
Description=Filebeat Log Collector
After=network-online.target
Wants=network-online.target
[Service]
User=elk
Group=elk
WorkingDirectory=/opt/elk/filebeat
ExecStart=/opt/elk/filebeat/filebeat -c /opt/elk/filebeat/filebeat.yml
Restart=on-failure
RestartSec=10
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
5.5 启动服务
bash
systemctl daemon-reload
systemctl enable --now filebeat
systemctl status filebeat --no-pager
六、端到端验证
6.1 检查所有服务状态
bash
# node1
systemctl status elasticsearch kibana
# node2
systemctl status logstash
# node3
systemctl status filebeat
6.2 模拟生成测试日志
在 node3 上执行:
bash
logger -p user.notice "ELK_PIPELINE_TEST_$(date +%s)"
6.3 查看 Logstash 实时日志
bash
tail -f /opt/logs/logstash/logstash-plain.log
能看到类似以下输出即表示链路通畅:
json
{
"@timestamp" => 2026-07-21T10:30:01.123Z,
"type" => "syslog",
"message" => "ELK_PIPELINE_TEST_1712345678",
"host" => "node3",
...
}
6.4 验证 Elasticsearch 索引
在 node1 上执行:
bash
# 查看索引列表
curl -sS 'http://127.0.0.1:9200/_cat/indices/logs-*?v'
# 搜索测试日志
curl -sS 'http://127.0.0.1:9200/logs-*/_search?q=ELK_PIPELINE_TEST&pretty'
若能返回命中结果,说明 日志 → Filebeat → Logstash → Elasticsearch 全链路打通!
6.5 Kibana 可视化验证
- 浏览器访问
http://192.168.194.10:5601 - 进入 Management → Stack Management → Kibana → Index Patterns
- 创建索引模式
logs-* - 进入 Analytics → Discover,即可看到实时采集的日志数据
七、常见问题排障
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| ES 无法启动 | vm.max_map_count 未设置 |
执行 sysctl -w vm.max_map_count=262144 |
| Filebeat 无法连接 Logstash | 防火墙未放行 5044 | firewall-cmd --add-port=5044/tcp 或关闭防火墙 |
| Logstash 无法输出到 ES | ES 地址或端口错误 | 检查 elasticsearch.hosts 配置 |
| Kibana 中文不生效 | 版本不支持 zh-CN |
8.x 版本支持,检查配置项是否正确 |
日志中有大量 grokparsefailure |
日志格式与 grok 模式不匹配 | 调整 log-pipeline.conf 中的 grok 匹配规则 |