目录
一、ELK 平台介绍
1.1 ELK 概述
1.2 Elasticsearch
1.2.1 ElasticSearch 概述
1.2.2 Elasticsearch 核心概念
1.3 Logstash
1.3.1 Logstash 介绍
1.3.2 Logstash 工作的三个阶段
1.4 Kibana
1.4.1 Kibana 介绍
1.4.2 Kibana 主要功能
二、环境设置
2.1 实验拓扑图
2.2 主机清单
三、部署 ES 群集
3.1 基本配置(以 elk1 为例,其它两台操作类似)
3.1.1 设置主机名
3.1.2 在两台 ES 主机上设置 hosts 文件
3.1.3 关闭所有节点的防火墙
3.1.4 创建 es 运行用户
3.1.5 安装 java 环境
3.1.6 为用户设置资源访问限制
3.2 安装 Elasticsearch
3.2.1 更改 Elasticsearch 主配置文件
3.2.2 创建数据存放路径并授权
3.2.3 启动 es
3.2.4 查看节点信息
四、安装 Logstash
4.1 在 logstash 服务器上安装 logstash
4.2 测试安装结果
4.2.1 直接将消息输出到屏幕
4.2.2 将消息输出到 es(如果没有安装 head 组件,此步骤省去)
4.3 Logstash 配置文件
4.3.1 收集系统日志并输出到 elasticsearch
五、Filebeat
5.1 在产生日志的客户端服务器上安装 filebeat(以 elk2 主机为例)
5.2 安装 filebeat
5.3 配置 web01 服务器 filebeat 的输出
5.3.1 修改 filebeat 文件,将 filebeat 输出的日志输入到远程的 logstash
5.3.2 启动 filebeat 服务
5.4 修改 logstash 的配置文件,使日志输出到 elasticsearch
5.5 运行 logstash 并验证
六、安装 Kibana
6.1 在 elk1 上安装 Kibana
6.2 修改 Kibana 主配置文件
6.3 启动 Kibana 服务
6.4 验证 Kibana
6.4.1 浏览器访问
6.4.2 添加索引模式
6.5 删除索引数据
6.5.1 删除单个索引
6.5.2 批量删除
七、ELK 实战应用场景
7.1 微服务日志追踪
7.2 安全合规审计
7.3 性能瓶颈分析
八、ELK 集群优化策略
8.1 Elasticsearch 分片策略优化
8.1.1 分片数量计算
8.1.2 动态调整副本数
8.2 冷热数据分层存储
8.2.1 热数据节点配置
8.2.2 冷数据节点配置
8.3 Logstash 性能调优
8.3.1 批量处理参数
8.3.2 多管道并行处理
九、ELK 与 Beats/APM 集成
9.1 Beats 家族组件
9.2 APM(应用性能监控)集成
9.2.1 部署 APM Server
9.2.2 应用埋点配置(以 Java 为例)
十、常见问题与解决方案
10.1 Elasticsearch 脑裂问题
10.1.1 原因
10.1.2 解决方案
10.2 Logstash 数据丢失问题
10.2.1 原因
10.2.2 解决方案
10.3 Kibana 连接异常
10.3.1 排查步骤
十一、企业级部署最佳实践
11.1 高可用架构设计
11.1.1 三层架构
11.1.2 资源规划
11.2 日志保留策略
11.2.1 按重要性分级
112.2 自动清理脚本
11.3 安全加固
11.3.1 访问控制
11.3.2 传输加密
在数字化转型加速的今天,企业 IT 系统每天都会产生海量的日志数据,这些数据涵盖了应用运行状态、用户行为、安全事件等关键信息。然而,传统的日志管理方式由于分散存储、检索效率低、缺乏深度分析能力等问题,已经难以满足企业高效运维与业务洞察的需求。
ELK(Elasticsearch+Logstash+Kibana)作为业界主流的开源日志分析解决方案,通过 Elasticsearch 的分布式搜索与分析能力、Logstash 的数据管道处理、Kibana 的可视化交互,构建了从日志采集、清洗、存储到实时分析的完整闭环。
日志主要包括系统日志、应用程序日志和安全日志。系统运维和开发人员可以通过日志了解服务器软硬件信息、检查配置过程中的错误及错误发生的原因。经常分析日志可以了解服务器的负荷、性能和安全性,从而及时采取措施纠正错误。
通常,日志被分散存储在不同的设备上。当管理数十上百台服务器时,使用依次登录每台机器的传统方法查阅日志会非常繁琐且效率低下。因此,集中化的日志管理显得尤为重要,例如使用开源的 syslog 将所有服务器上的日志收集汇总。
集中化管理日志后,日志的统计和检索又成为了一件比较麻烦的事情。虽然可以使用 grep、awk 和 wc 等 Linux 命令实现检索和统计,但对于要求更高的查询、排序和统计等要求以及庞大的机器数量,这些方法就显得力不从心了。
开源实时日志分析 ELK 平台能够完美解决上述问题。ELK 由 ElasticSearch、Logstash 和 Kibana 三个开源工具组成:
进行日志处理分析,一般需要经过以下几步:
Elasticsearch 是一个基于 Lucene 的搜索服务器,提供了分布式多用户能力的全文搜索引擎,基于 RESTful web 接口。它用 Java 开发,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。其设计用于云计算中,能够达到实时搜索,具有稳定、可靠、快速、安装使用方便等特点。
Logstash 由 JRuby 语言编写,运行在 Java 虚拟机(JVM)上,是一款强大的数据处理工具,可实现数据传输、格式处理、格式化输出,具有强大的插件功能,常用于日志处理。其设计理念是只做三件事:数据输入、数据加工、数据输出。
Kibana 是一个设计用于和 Elasticsearch 配置工作的开源分析和可视化平台,可以用它进行搜索、查看、集成 Elasticsearch 中的数据索引,利用各种图表、报表、地图组件轻松对数据进行可视化分析。
包括与 Elasticsearch 无缝集成、整合数据、复杂数据分析、让更多团队成员收益、接口灵活、配置简单、可视化多数据源、简单数据导出等。
说明:新版的 logstash 自带缓存功能,不需要再使用 zookeeper+kafka 做消息中间件;elasticsearch 服务器的数量需要奇数个,因为有脑裂的问题。
主机名 | IP 地址 | 操作系统 | 软件包 |
---|---|---|---|
elk1 | 192.168.10.101 | Openeuler 24 | Elasticsearch、logstash、kbana |
elk2 | 192.168.10.102 | Openeuler 24 | Elasticsearch、filebeat、httpd |
elk3 | 192.168.10.103 | Openeuler 24 | Elasticsearch |
按照主机清单为每一台主机设置主机名(elk1、elk2、elk3),命令如下:
hostnamectl set-hostname elk1 # 在elk1上执行
hostnamectl set-hostname elk2 # 在elk2上执行
hostnamectl set-hostname elk3 # 在elk3上执行
cat <>/etc/hosts
192.168.10.101 elk1
192.168.10.102 elk2
192.168.10.103 elk3
EOF
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config
useradd es
dnf -y install java-11
java -version
vim /etc/security/limits.conf
添加以下内容:
es soft nofile 65535
es soft memlock unlimited
es soft nproc 65535
es hard nofile 65535
es hard nproc 65535
es hard memlock unlimited
说明:
es soft nofile 65535
:一个进程最多能打开的文件数。es soft nproc 65535
:一个用户最多能创建的进程数。es soft memlock unlimited
:最大锁定内存地址空间(unlimited 不限制)。vim /etc/sysctl.conf
添加以下配置:
vm.max_map_count=655360
sysctl -p
说明:vm.max_map_count
的默认值是 65536,该参数限制一个进程可以拥有的 VMA(虚拟内存区域)的数量,会影响中间件可以开启的线程数量,值过小可能导致中间件无法开启足够线程而报错。
tar zxvf elasticsearch-7.10.0-linux-x86_64.tar.gz
mv elasticsearch-7.10.0 /usr/local/elasticsearch
vim /usr/local/elasticsearch/config/elasticsearch.yml
修改内容如下:
node.name: elk1 # 本节点主机名,以elk1节点为例,其它节点请改成相对应的节点名称
cluster.name: kgc-elk-cluster # 群集名称
path.data: /elk/data # 数据文件路径
path.logs: /elk/logs # 日志文件路径
bootstrap.memory_lock: false # 锁定物理内存
network.host: 0.0.0.0 # 监听地址
http.port: 9200 # 监听端口
discovery.seed_hosts: ["elk1", "elk2", "elk3"] # 群集中的主机列表
cluster.initial_master_nodes: ["elk1"] # master主机名称,群集初始化会将此节点选举为master
mkdir -p /elk/data
mkdir -p /elk/logs
chown -R es:es /elk/
chown -R es:es /usr/local/elasticsearch/
su - es # es限制使用root启动,需要切换至es用户
nohup /usr/local/elasticsearch/bin/elasticsearch &
sudo netstat anpt | grep 9200
curl http://192.168.10.103:9200/_cat/nodes
输出结果中带有星号的是 master 节点。
systemctl stop firewalld
setenforce 0
tar zxvf logstash-7.10.0-linux-x86_64.tar.gz
yum -y install java-11
mv logstash-7.10.0 /usr/local/logstash
chmod -R 777 /usr/local/logstash/data/
/usr/local/logstash/bin/logstash -e 'input { stdin {} } output { stdout { codec => rubydebug } }'
执行该命令后稍等,出现消息格式,可输入字符串作为消息内容,退出按 Ctrl+C。若命令失败,删除 logstash 目录的 data 子目录。
/usr/local/logstash/bin/logstash -e 'input { stdin {} } output { stdout { codec => rubydebug } output { elasticsearch { hosts => ["192.168.10.103:9200"] } }'
输入字符串作为消息,使用以下方法查看 es 中索引信息:
curl -XGET "http://localhost:9200/_cat/indices?v"
curl -XGET "http://localhost:9200/_cat/shards?v"
curl -XGET "http://localhost:9200/索引名/_search?pretty" -H 'Content-Type: application/json' -d '{"query":{"match_all":{}},"size":10}'
Logstash 配置文件基本由 input、output 以及 filter(根据需要)三部分组成。标准配置文件格式如下:
input {...}
filter {...}
output {...}
chmod o+r /var/log/messages # 让Logstash可以读取日志
touch /usr/local/logstash/system.conf
vim /usr/local/logstash/system.conf
输入以下内容:
input {
file {
path => "/var/log/messages"
type => "system"
start_position => "beginning"
}
}
output {
elasticsearch {
hosts => ["192.168.10.101:9200"]
index => "system-%{+YYYY.M.dd}"
}
}
运行 logstash:
/usr/local/logstash/bin/logstash -f /usr/local/logstash/system.conf
查看索引列表,会发现多出一个索引。
yum -y install httpd
systemctl start httpd
echo "www.kec.com" > /var/www/html/index.html
curl 192.168.10.102 www.kgc.com
cat /var/log/httpd/access_log
cat /var/log/httpd/error_log
tar zxvf filebeat-7.10.0-linux-x86_64.tar.gz
mv filebeat-7.10.0-linux-x86_64 /usr/local/filebeat
mv filebeat.yml filebeat.yml.bak
cd /usr/local/filebeat/
vim filebeat.yml
修改内容如下:
filebeat.inputs:
- type: log
paths:
- /var/log/httpd/access_log
output.logstash:
hosts: ["192.168.10.102:5044"]
/usr/local/filebeat/filebeat -c /usr/local/filebeat/filebeat.yml &
如果 logstash 处于开启状态,先关闭:
netstat -anpt | grep 5044 # 查看logstash进程
kill -9 进程号 # 杀死进程
修改配置文件:
vim /usr/local/logstash/config/beats.conf
输入以下内容:
input {
beats {
port => "5044"
codec => "json"
}
}
output {
elasticsearch {
hosts => ["192.168.10.103:9200"]
index => "weblog-beat-%{+YY.M.dd}"
}
}
说明:Codec 是 logstash 从 1.3.0 版开始新引入的概念,用于 decode、encode 事件,使得 logstash 可以更好地与其他有自定义数据格式的运维产品共存。
/usr/local/logstash/bin/logstash -f /usr/local/logstash/config/beats.conf --path.data=/usr/local/logstash/config.d/web01 &
查看索引,会发现新增了一个 weblog-beat-2025.04.28 的索引。
tar zxvf kibana-7.10.0-linux-x86_64.tar.gz
mv kibana-7.10.0-linux-x86_64 /usr/local/kibana
vim /usr/local/kibana/config/kibana.yml
修改内容如下:
server.port: 5601 # 监听端口
server.host: "0.0.0.0" # 监听地址
elasticsearch.hosts: "http://192.168.10.103:9200" # ES主机的IP地址
kibana.index: ".kibana"
chown -R es:es /usr/local/kibana/
su - es
nohup /usr/local/kibana/bin/kibana &
在浏览器中输入http://192.168.10.103:5601
,进入 Kibana 界面。
将 elk1 主机的系统日志添加到 kibana,若看不到日志,可访问网站生成日志信息后刷新 kibana。添加第二个日志时,在主菜单中找到 Management--》Stack Management,然后点击 Kibana 下的 Index Patterns,再点击右上角的 Create index pattern。
curl -XDELETE "http://localhost:9200/索引名"
使用通配符(如 logs-*)或逗号分隔索引名,例如:
curl -XDELETE "http://localhost:9200/system-2025.04.28"
在微服务架构中,一个请求可能会经过多个服务节点,传统日志分散存储难以追踪完整链路。ELK 通过以下方实现日志追踪:
实战命令示例:
# 在微服务容器中启动Filebeat收集日志
docker run -d --name filebeat \
-v /var/log/microservice:/var/log/microservice \
-v /path/to/filebeat.yml:/usr/share/filebeat/filebeat.yml \
docker.elastic.co/beats/filebeat:7.10.0
ELK 在安全日志分析中的应用:
安全日志配置示例:
# Logstash配置解析防火墙日志
input {
file {
path => "/var/log/firewall.log"
type => "firewall"
}
}
filter {
grok {
match => { "message" => "%{IP:src_ip} %{WORD:action} %{NUMBER:port} -> %{IP:dest_ip}" }
}
geoip {
source => "src_ip"
target => "src_geo"
}
}
output {
elasticsearch {
hosts => ["es-cluster:9200"]
index => "security-%{+YYYY.MM.dd}"
}
}
ELK 用于系统性能监控的关键能力:
性能分析仪表盘配置:
{
"query": {
"range": {
"response_time": {
"gte": 500 # 响应时间超过500ms触发告警
}
}
}
}
主分片数 = 节点数 × 3 ~ 5
(每个节点建议承载 3-5 个主分片)。# 修改索引副本数为2
PUT /my-index/_settings
{
"number_of_replicas": 2
}
注意:分片数在索引创建后无法修改,需通过 reindex 重建索引。
# /usr/local/elasticsearch/config/jvm.options
-Xms16g
-Xmx16g
-XX:MaxDirectMemorySize=16g
# kibana.yml中启用ILM
xpack.il.m.enabled: true
# 创建生命周期策略
PUT /_ilm/policy/cold_data_policy
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"set_priority": {
"priority": 100
}
}
},
"cold": {
"min_age": "7d",
"actions": {
"move_to": {
"node_attr": "cold"
},
"set_priority": {
"priority": 50
}
}
}
}
}
}
# logstash.yml配置
pipeline.batch.size: 1000 # 每次处理1000条日志
pipeline.batch.delay: 50ms # 最大等待50ms凑满批量
# 启动多管道
/usr/local/logstash/bin/logstash -f /config/pipeline1.conf -f /config/pipeline2.conf
组件 | 功能 | 应用场景 |
---|---|---|
Filebeat | 日志文件采集 | 服务器日志、应用日志 |
Metricbeat | 系统指标采集 | 服务器 CPU / 内存 / 磁盘监控 |
Packetbeat | 网络流量分析 | 网络性能监控、协议解析 |
Auditbeat | 系统审计日志 | 安全合规审计 |
Metricbeat 安装示例:
yum install metricbeat
vim /etc/metricbeat/metricbeat.yml
# 配置发送到ELK
output.elasticsearch:
hosts: ["192.168.10.103:9200"]
service.start
docker run -d --name apm-server \
-e "APM_SECRET_TOKEN=my-token" \
-e "ELASTICSEARCH_HOSTS=http://192.168.10.103:9200" \
-p 8200:8200 \
docker.elastic.co/apm/apm-server:7.10.0
co.elastic.apm
elastic-apm-agent
1.20.0
# 启动参数
java -javaagent:/path/to/elastic-apm-agent-1.20.0.jar \
-Delastic.apm.service_name=my-service \
-Delastic.apm.server_urls=http://192.168.10.103:8200 \
-Delastic.apm.secret_token=my-token \
-jar my-app.jar
discovery.zen.minimum_master_nodes
为(节点数/2)+1
# elasticsearch.yml
discovery.zen.minimum_master_nodes: 2 # 3节点集群设置为2
cluster.join.timeout: 60s
# logstash.yml
queue.type: persisted
queue.directory: /var/logstash/queue
queue.max_size: 1024gb
# output配置
elasticsearch {
hosts => ["es1:9200", "es2:9200"]
retry_max: 30
retry_interval: 5s
}
elasticsearch.hosts
是否正确grep "elasticsearch.hosts" /usr/local/kibana/config/kibana.yml
curl -XGET http://192.168.10.103:9200/_cluster/health?pretty
tail -f /usr/local/kibana/logs/kibana.log
组件 | 最低配置(单节点) | 建议配置(生产) |
---|---|---|
Elasticsearch | 8 核 CPU/16GB 内存 / 200GB SSD | 16 核 CPU/64GB 内存 / 1TB SSD |
Logstash | 4 核 CPU/8GB 内存 | 8 核 CPU/16GB 内存 |
Kibana | 2 核 CPU/4GB 内存 | 4 核 CPU/8GB 内存 |
#!/bin/bash
# clean_logs.sh
DATE=$(date -d "30 days ago" +%Y.%m.%d)
INDEX_PATTERN="system-*"
# 删除30天前的索引
curl -XDELETE "http://localhost:9200/${INDEX_PATTERN}-${DATE}"
# 添加定时任务
crontab -e
0 0 * * * /path/to/clean_logs.sh >/dev/null 2>&1
# 启用安全模块
bin/elasticsearch-setup-passwords auto
# kibana.yml
xpack.security.enabled: true
xpack.security.encryptionKey: "your-encryption-key"
bin/elasticsearch-certutil ca
bin/elasticsearch-certutil cert --ca ca.crt
# elasticsearch.yml
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p12