集群部署EFK+Kafka+Logstash
软件包连接
filbeat:https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-9.2.0-linux-x86_64.tar.gz
kafka:https://archive.apache.org/dist/kafka/4.1.0/kafka_2.13-4.1.0.tgz
logstash:https://artifacts.elastic.co/downloads/logstash/logstash-9.2.0-linux-x86_64.tar.gz
kibana:https://artifacts.elastic.co/downloads/kibana/kibana-9.2.0-linux-x86_64.tar.gz
Elasticsearch:https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-9.2.0-linux-x86_64.tar.gz
注意:
三台服务器需要java环境
jdk:
环境说明
三台linux服务器,系统为rocky9
| nginx | filbeat | kafka | logstash | kibana | Elasticsearch | ||
|---|---|---|---|---|---|---|---|
| 192.168.75.134(elk-master01) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
| 192.168.75.135(elk-master02) | ✅ | ✅ | ✅ | ||||
| 192.168.75.133(elk-node) | ✅ | ✅ | ✅ |
三台服务器需要做如下准备
1 # 关闭 SELinux
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
2 # 关闭防火墙(或开放 9200、9300 端口,9300 为节点间通信端口)
systemctl stop firewalld
systemctl disable firewalld
3 # 配置主机名(每台机器分别设置,如主节点设为 master,从节点设为 data1、data2)
hostnamectl set-hostname elk-master01 # 192.168.75.134
hostnamectl set-hostname elk-master02 #192.168.75.135
hostnamectl set-hostname elk-node # 192.168.75.133
4 # 配置 hosts 解析(3台机器均添加)
cat >> /etc/hosts << EOF
192.168.75.134 elk-master01
192.168.75.135 elk-master02
192.168.75.133 elk-node
EOF
5 #部署java环境
下载并解压 Temurin 17
wget https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.11%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.11_9.tar.gz
tar -zxvf OpenJDK17U-jdk_x64_linux_hotspot_17.0.11_9.tar.gz -C /usr/local/
mv /usr/local/jdk-17.0.11+9 /usr/local/jdk17
配置环境变量
echo 'export JAVA_HOME=/usr/local/jdk17' >> /etc/profile
echo 'export PATH=$JAVA_HOME/bin:$PATH' >> /etc/profile
source /etc/profile
验证
java -version # 输出 17.0.11 即为成功
6 # 调整系统参数
调整虚拟内存
echo 'vm.max_map_count=262144' >> /etc/sysctl.conf
sysctl -p
调整文件描述符和进程限制(为 es 用户)
echo 'es soft nofile 65536' >> /etc/security/limits.conf
echo 'es hard nofile 65536' >> /etc/security/limits.conf
echo 'es soft nproc 4096' >> /etc/security/limits.conf
echo 'es hard nproc 4096' >> /etc/security/limits.conf
echo 'es soft memlock unlimited' >> /etc/security/limits.conf
echo 'es hard memlock unlimited' >> /etc/security/limits.conf
部署过程
1.部署Elasticsearch
1 创建es用户
useradd -M -r -s /sbin/nologin es
# 三台机器全部执行
2 安装es软件包
# 下载 9.2.0 版本
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-9.2.0-linux-x86_64.tar.gz
# 解压到 /opt 并授权
tar -zxvf elasticsearch-9.2.0-linux-x86_64.tar.gz -C /opt/
mv /opt/elasticsearch-9.2.0 /opt/elasticsearch
chown -R es:es /opt/elasticsearch
# 三台机器全部执行
3 创建目录
mkdir -p /var/lib/elasticsearch /var/log/elasticsearch
chown -R es:es /var/lib/elasticsearch /var/log/elasticsearch
# 三台机器全部执行
4 配置文件
vi /opt/elasticsearch/config/elasticsearch.yml
###
### 三台主机都要配置,不过有些配置不同,具体在###中标注
# 集群名称(所有节点必须一致)
cluster.name: es-cluster
# 节点名称(当前为主节点,需唯一)
node.name:elk-master01
### 这里的node.name需要参考主机名填写,如果当前主机hostname为elk-master01 ,这里就写elk-master01
# 节点角色(仅作为主节点,不存储数据)
node.roles: [data, master]
# 数据存储路径
path.data: /var/lib/elasticsearch
# 日志存储路径
path.logs: /var/log/elasticsearch
# 绑定当前主节点IP
network.host: 192.168.75.134
### 输入本机IP地址
# HTTP访问端口(默认9200)
http.port: 9200
# 节点间通信端口(默认9300)
transport.port: 9300
# 集群所有节点的通信地址(含自身及从节点)
discovery.seed_hosts: ["192.168.75.134", "192.168.75.135:9300", "192.168.75.133:9300"]
### 这里输入集群内的三台机器IP+端口
# 首次启动时参与主节点选举的候选节点
cluster.initial_master_nodes: ["node-master", "node-data-1", "node-data-2"]
### 这里依次填上
# 启用内存锁定(需配合系统配置)
bootstrap.memory_lock: true
# 允许跨域访问(方便Kibana连接)
http.cors.enabled: true
# 允许所有来源跨域(测试环境用)
http.cors.allow-origin: "*"
# 测试阶段关闭安全验证(生产环境需开启并配置证书)
xpack.security.enabled: false
# 禁用机器学习功能(解决启动失败问题)
xpack.ml.enabled: false
5 启动elasticsearch
### elasticsearch不允许root启动,所以需要先切换到es用户
su - es -c '/opt/elasticsearch/bin/elasticsearch -d'
# 检查服务是否启动,三台都要启动,先启动elk-master1
[root@elk-master1 bin]# ps -ef | grep 9200
root 351585 222680 0 15:57 pts/3 00:00:00 watch -n 2 curl -s -X GET "192.168.75.134:9200/_cat/indices?v" | grep -E "es-|payment|order"
root 404810 211538 0 18:10 pts/1 00:00:00 grep --color=auto 9200
# 检测集群是否健康
[root@elk-master1 bin]# curl http://192.168.75.134:9200/_cluster/health?pretty
{
"cluster_name" : "es-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"active_primary_shards" : 63,
"active_shards" : 126,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 0,
"unassigned_primary_shards" : 0,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 100.0
}
[root@elk-master1 bin]# curl http://192.168.75.134:9200/_cat/nodes?v
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.75.133 11 80 0 0.00 0.00 0.00 dm * elk-node
192.168.75.135 37 73 0 0.08 0.02 0.01 dm - elk-master2
192.168.75.134 21 84 1 0.11 0.14 0.08 dm - elk-master1
2.部署kibana
是一款开源的数据可视化和分析平台,常被用于日志分析、运维监控、业务数据分析等
由于kibana只需要在其中一台机器部署,所以部署在elk-master1上
1下载安装包
# 创建kibana用户
useradd -r -s /sbin/nologin kibana
# 解压
tar -zxvf kibana-9.2.0-linux-x86_64.tar.gz -C /opt/
mv /opt/kibana-9.2.0 /opt/kibana
# 授权(与 Elasticsearch 同用户,避免权限问题)
chown -R kibana.kibana /opt/kibana
# 创建kibana日志目录
mkdir -p /var/log/kibana
chown -R kibana.kibana /var/log/kibana
2.编辑配置文件
vi /opt/kibana/config/kibana.yml
# 服务器端口(默认 5601)
server.port: 5601
# 绑定地址(允许外部访问,生产环境建议指定具体 IP)
server.host: "0.0.0.0"
# 服务器名称(自定义)
server.name: "kibana-node"
# Elasticsearch 地址(需与 Elasticsearch 配置的地址一致)
# 若 Elasticsearch 启用了 HTTPS,此处需用 https:// 并指定端口
# 注意:与 Elasticsearch 协议一致(HTTP/HTTPS)
elasticsearch.hosts: ["http://192.168.75.134:9200"]
### 输入本机IP
# Elasticsearch 认证信息(若启用了安全功能,需配置)
# 因为 elastic 属于 ES 中的超级管理员;Kibana是需要给外部人员使用。
# 为了安全 ES 本身直接拒绝 Kibana 使用 elastic 用户
elasticsearch.username: "kibana_system"
elasticsearch.password: "Chen123456!"
# 若 Elasticsearch 用了自签名证书,Kibana 需信任该证书(可选)
# elasticsearch.ssl.certificateAuthorities: ["/opt/elasticsearch/config/ssl/DigiCert+Global+Root+G2+Cross+G1.crt"]
# 日志路径(可选,默认在安装目录下)
# Enables you to specify a file where Kibana stores log output.
logging.appenders.default:
# 保存日志的类型
type: file
# kibana 的日志路径
fileName: /var/log/kibana/kibana.log
# kibana 日志的格式
layout:
type: json
# 中文显示(Kibana 9.x 已支持自动检测,若需强制中文可添加)
i18n.locale: "zh-CN"
3 修改密码
Elasticsearch 9.x 禁止使用 elastic 账户直接作为 Kibana 的服务账户(出于安全和权限控制的考虑)。
# 跳过证书域名验证,重置 kibana_system 密码(交互式)
# --ssl-verify-hostnames false 跳过证书认证
su -s /bin/bash -c "/opt/elasticsearch/bin/elasticsearch-reset-password -u kibana_system -i --ssl-verify-hostnames false" es
#【重要】如果没有HTTPS,就不需要增加 --ssl-verify-hostnames false
#【重要】这条命令需要再ES服务器中执行
su -s /bin/bash -c "/opt/elasticsearch/bin/elasticsearch-reset-password -u kibana_system -i" es
4 启动kibana
su -s /bin/bash - kibana -c '/opt/kibana/bin/kibana'
检查是否可以在浏览器中访问http:///192.168.75.134:5601
3 部署kafka
Kafka 是一款高吞吐、低延迟的分布式消息队列,核心用于数据的异步传输与缓冲,能接收多源数据
- Topic(主题):消息的分类容器,生产者向 Topic 写消息,消费者从 Topic 读消息(类似 "消息队列名称")。
- Partition(分区):每个 Topic 分为多个分区(可理解为 "子队列"),是并行处理的最小单位,消息按规则分配到不同分区。
- Producer(生产者):发送消息到 Topic 的应用(如 Filebeat 收集日志后发送到 Kafka)。
- Consumer(消费者):从 Topic 读取消息的应用(如 Logstash 消费 Kafka 消息并转发到 Elasticsearch)
1 下载安装包
# 创建kafka用户
useradd kafka -s /sbin/nologin
mkdir -p /var/lib/kafka /var/log/kafka
chown -R kafka.kafka /var/lib/kafka /var/log/kafka
wget https://dlcdn.apache.org/kafka/4.1.0/kafka_2.13-4.1.0.tgz
tar -xf kafka_2.13-4.1.0.tgz -C /usr/local/
mv /usr/local/kafka_2.13-4.1.0 /usr/local/kafka
chown -R kafka.kafka /usr/local/kafka
2 配置文件
vim /usr/local/kafka/config/server.properties
# The send buffer (SO_SNDBUF) used by the socket server
socket.send.buffer.bytes=102400
# The receive buffer (SO_RCVBUF) used by the socket server
socket.receive.buffer.bytes=102400
# The maximum size of a request that the socket server will accept (protection against OOM)
socket.request.max.bytes=104857600
############################# Log Basics #############################
# A comma separated list of directories under which to store log files
log.dirs=/tmp/kraft-combined-logs
# The default number of log partitions per topic. More partitions allow greater
# parallelism for consumption, but this will also result in more files across
# the brokers.
num.partitions=1
# The number of threads per data directory to be used for log recovery at startup and flushing at shutdown.
# This value is recommended to be increased for installations with data dirs located in RAID array.
num.recovery.threads.per.data.dir=1
############################# Internal Topic Settings #############################
# The replication factor for the group metadata internal topics "__consumer_offsets", "__share_group_state" and "__transaction_state"
# For anything other than development testing, a value greater than 1 is recommended to ensure availability such as 3.
offsets.topic.replication.factor=1
share.coordinator.state.topic.replication.factor=1
share.coordinator.state.topic.min.isr=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
3 初始化
# 生成集群ID(保存输出的UUID,如:3S9R9A0XTyO8Z7L8cX7J-A)
su -s /bin/bash -c "/usr/local/kafka/bin/kafka-storage.sh random-uuid" kafka
rErtsYPdTS2vxcfmNDtRpQ
# 标记为单机模式,自动配置初始控制器
su -s /bin/bash -c "/usr/local/kafka/bin/kafka-storage.sh format -t rErtsYPdTS2vxcfmNDtRpQ -c /usr/local/kafka/config/server.properties --standalone" kafka
4 启动服务
su - kibana -c '/usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/server.properties'
5 验证功能
# 测试 Kafka 功能
/usr/local/kafka/bin/kafka-topics.sh --bootstrap-server 192.168.75.134:9092 --list
[root@elk-master1 kibana]# /usr/local/kafka/bin/kafka-topics.sh --bootstrap-server 192.168.75.134:9092 --list
__consumer_offsets
filebeat-logs
nginx-access
test-topic
yzh-test
### 创建测试topics
/usr/local/kafka/bin/kafka-topics.sh --create \
--topic test-kraft-healthy3 \
--bootstrap-server 192.168.20.19:9092 \
--partitions 3 \
--replication-factor 1
[root@elk-master1 kibana]# /usr/local/kafka/bin/kafka-topics.sh --create --topic test-kraft-healthy2 3 --bootstrap-server 192.168.75.134:9092
Created topic test-kraft-healthy2.
[root@elk-master1 kibana]#
### 测试能否通过kafka发送消息,这里有两个概念为生产者和消费者,由filebeat收集的数据作为生产者,然后通过在终端显示出来(或者将消息发送给elasticearch作为消费者)
开启两个终端,分别执行

4 部署 filebeat
Filebeat是轻量级日志采集器,部署于服务器端
1下载安装包
# 下载安装包
wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-9.2.0-linux-x86_64.tar.gz
# 解压
tar -xf filebeat-9.2.0-linux-x86_64.tar.gz -C /usr/local/
mv /usr/local/filebeat-9.2.0-linux-x86_64 /usr/local/filebeat
useradd -M -r -s /sbin/nologin es
# 授权给 es 用户(与 Elasticsearch 同用户,避免日志读取权限问题)
chown -R es:es /usr/local/filebeat
2
filebeat.inputs:
- type: filestream
id: ok-log
enabled: true
paths:
- /usr/local/createlog/templates/logs/*.log
### 这里/usr/local/createlog/templates/logs/下面有很多日志文件,例如log_1778815185647044814_8064.log
# ---- NDJSON 解析配置(适配你的JSON日志) -------------------
parsers:
- ndjson:
# 核心:解析后的字段放到根层级(可直接用%{[project]}等字段)
target: ""
# 覆盖Filebeat默认的message字段(你的日志有自定义message,需保留)
overwrite_keys: true
# 展开带点的key(如日志中有a.b.c格式的字段时生效,兼容未来扩展)
expand_keys: true
# 解析失败时添加error字段,便于排查格式异常
add_error_key: true
# 忽略单条日志解析失败(避免一条坏日志导致批量丢数据)
ignore_decoding_error: true
# 无需配置message_key:你的日志是完整JSON,非"包裹式JSON"
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- drop_fields:
fields: ["service"]
ignore_missing: true
output.kafka:
hosts: ["192.168.75.134:9092"]
topic: "yzh-test"
required_acks: 1
compression: gzip
### 这里output.kafka中分别定义主机名和topic,topic意为主题,可以理解为musql中的数据库
### # 列出 Kafka 中的所有 Topic
###/usr/local/kafka/bin/kafka-topics.sh --list --bootstrap-server 192.168.75.134:9092
5部署logstash
1 安装logstash包
wget https://artifacts.elastic.co/downloads/logstash/logstash-9.2.0-linux-x86_64.tar.gz
tar -xf logstash-9.2.0-linux-x86_64.tar.gz -C /usr/local/
mv /usr/local/logstash-9.2.0 /usr/local/logstash
useradd -M -r -s /sbin/nologin logstash
chown -R logstash.logstash /usr/local/logstash
2 修改配置文件
# input,数据从哪里进入logstach,下面为kafka,需要填写kafka服务所在IP+端口,还有在filubeat中定义的主题
input {
kafka {
bootstrap_servers => "192.168.75.134:9092"
topics => ["yzh-test"]
group_id => "logstash-yzh-consumer"
codec => "json"
auto_offset_reset => "earliest"
}
}
# 定义数据去往哪里,这里显示将数据传输到elasticsearch,需要填写IP地址和index的格式,index在elasticsearch中指索引,方便进行数据隔离。其中{project是日志文件中的json中的值,可以通过这种方式生成多个索引
output {
elasticsearch {
hosts => ["http://192.168.75.134:9200"]
#index => "es-%{server}-%{+YYYY.MM.dd}"
index => "es-%{project}-%{+YYYY.MM.dd}"
}
stdout { codec => rubydebug }
}
6 kibana 链接 ES


上面的就是logstach中output中的index中定义的index => "es-%{project}-%{+YYYY.MM.dd}"


部署问题
1 测试的日志文件没有在kibana界面中显示
排查过程
-
检查日志文件是否生成,这里以cd /usr/local/createlog/templates/logs/,检查日志文件是否有增加
-
检查日志文件是否被filebeat收集
查看服务是否正常/usr/local/filebeat/filebeat test config -c /usr/local/filebeat/filebeat.yml输出是否是ok
先查看filebeat中output定义的topic(这里是yzh-test,前面需要输入IP地址),然后输入
/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server 192.168.75.134:9092 --topic yzh-test ,此时生成日志文件,检查上面的命令是否有输出,如果有,则数据正常通过filebeat,如果没有,检查日志文件路径,IP,配置文件格式等
-
检查日志文件是否被kafka收集
跟上面类似,执行下面命令,同时手动生成日志文件,检查kafka是否能作为消费者过滤数据,需要执行topic,如果有输出,则继续下一步
/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server 192.168.75.134:9092 --topic yzh-test
-
检查日志文件是否被logstash收集
跟上面类似,执行journalctl -u logstash -f,同时手动写入测试日志,观察命令是否有输出
检查日志文件是否被elasticsearch收集
输入一下命令,curl -s "http://192.168.75.134:9200/_cat/count/es-\*?v",其中es-*是logstach中output中的index配置,查看当前命令是否有输出,同时,手动测试生成日志文件,观察输出的数字是否会增长
2 启动服务尽量使用./xxx.sh,不要编写service后混合启动,容易出问题
志文件路径,IP,配置文件格式等
-
检查日志文件是否被kafka收集
跟上面类似,执行下面命令,同时手动生成日志文件,检查kafka是否能作为消费者过滤数据,需要执行topic,如果有输出,则继续下一步
/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server 192.168.75.134:9092 --topic yzh-test
-
检查日志文件是否被logstash收集
跟上面类似,执行journalctl -u logstash -f,同时手动写入测试日志,观察命令是否有输出
检查日志文件是否被elasticsearch收集
输入一下命令,curl -s "http://192.168.75.134:9200/_cat/count/es-\*?v",其中es-*是logstach中output中的index配置,查看当前命令是否有输出,同时,手动测试生成日志文件,观察输出的数字是否会增长
2 启动服务尽量使用./xxx.sh,不要编写service后混合启动,容易出问题