Docker搭建Elasticsearch+Redis+Logstash+Filebeat日志分析系统完整指南
一、系统架构概述
本方案构建一个完整的ELK(Elasticsearch、Logstash、Kibana)日志分析系统,并引入Redis作为消息队列缓冲,Filebeat作为轻量级日志采集器。整体架构如下:
Web服务器(Filebeat) → Logstash2 → Redis → Logstash1 → Elasticsearch集群 → Kibana
架构优势:
- Filebeat采集日志后发送至Logstash进行初步处理
- Redis作为消息队列,起到缓冲和削峰填谷的作用
- 双Logstash架构支持大规模集群日志采集
- Elasticsearch集群提供高可用存储和检索能力
- Kibana提供可视化分析界面
二、环境规划
服务器清单
| IP地址 | 主机名 | 部署组件 |
|---|---|---|
| 172.16.1.100 | node-1 | Elasticsearch、Kibana、Logstash、Filebeat、Nginx、Redis、Kafka |
| 172.16.1.101 | node-2 | Elasticsearch |
| 172.16.1.102 | node-3 | Elasticsearch |
端口规划
| 组件 | 端口 | 说明 |
|---|---|---|
| Elasticsearch | 9200/9300 | HTTP/RPC通信端口 |
| Kibana | 5601 | Web访问端口 |
| Logstash | 5044 | Beats输入端口 |
| Redis | 6379 | 消息队列端口 |
| Kafka | 9092 | 消息队列端口 |
| Nginx | 80 | Web服务器端口 |
三、准备工作
拉取所需镜像
在三台服务器上分别拉取以下镜像:
bash
# Elasticsearch镜像
docker pull elasticsearch:8.17.4
# Kibana镜像(仅在node-1拉取)
docker pull kibana:8.17.4
# Logstash镜像(仅在node-1拉取)
docker pull logstash:8.17.4
# Filebeat镜像(仅在node-1拉取)
docker pull docker.elastic.co/beats/filebeat:8.17.4
# Redis镜像(仅在node-1拉取)
docker pull redis:latest
# Kafka镜像(仅在node-1拉取)
docker pull wurstmeister/kafka:latest
docker pull wurstmeister/zookeeper:latest
# Elasticsearch-Head插件(仅在node-1拉取)
docker pull mobz/elasticsearch-head:5
四、部署Elasticsearch集群
4.1 创建数据目录(三台服务器均需执行)
bash
mkdir -pv /data/elk/elasticsearch/{logs,data,conf}
chmod -R 775 /data/elk/elasticsearch/
chown -R 1000:1000 /data/elk/elasticsearch/
4.2 配置elasticsearch.yml
node-1 (172.16.1.100) 配置
bash
vim /data/elk/elasticsearch/conf/elasticsearch.yml
yaml
cluster.name: es-cluster
node.name: node-1
network.host: 172.16.1.100
http.port: 9200
transport.port: 9300
discovery.seed_hosts: ["172.16.1.100:9300", "172.16.1.101:9300", "172.16.1.102:9300"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
xpack.security.enabled: false
xpack.security.autoconfiguration.enabled: false
http.cors.enabled: true
http.cors.allow-origin: "*"
bootstrap.memory_lock: true
node-2 (172.16.1.101) 配置
bash
vim /data/elk/elasticsearch/conf/elasticsearch.yml
yaml
cluster.name: es-cluster
node.name: node-2
network.host: 172.16.1.101
http.port: 9200
transport.port: 9300
discovery.seed_hosts: ["172.16.1.100:9300", "172.16.1.101:9300", "172.16.1.102:9300"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
xpack.security.enabled: false
xpack.security.autoconfiguration.enabled: false
http.cors.enabled: true
http.cors.allow-origin: "*"
bootstrap.memory_lock: true
node-3 (172.16.1.102) 配置
bash
vim /data/elk/elasticsearch/conf/elasticsearch.yml
yaml
cluster.name: es-cluster
node.name: node-3
network.host: 172.16.1.102
http.port: 9200
transport.port: 9300
discovery.seed_hosts: ["172.16.1.100:9300", "172.16.1.101:9300", "172.16.1.102:9300"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
xpack.security.enabled: false
xpack.security.autoconfiguration.enabled: false
http.cors.enabled: true
http.cors.allow-origin: "*"
bootstrap.memory_lock: true
4.3 启动Elasticsearch容器(三台服务器分别执行)
bash
docker run -d \
--name elasticsearch \
--restart unless-stopped \
--network host \
--ulimit memlock=-1:-1 \
-v /data/elk/elasticsearch/conf/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /data/elk/elasticsearch/data/:/usr/share/elasticsearch/data/ \
-v /data/elk/elasticsearch/logs/:/usr/share/elasticsearch/logs/ \
-e "ES_JAVA_OPTS=-Xms2g -Xmx2g" \
elasticsearch:8.17.4
4.4 安装Elasticsearch-Head(仅node-1)
bash
docker run -d \
--name es-head \
--restart unless-stopped \
-p 9100:9100 \
mobz/elasticsearch-head:5
4.5 验证集群状态
访问以下地址验证集群是否正常:
bash
# 查看集群健康状态
curl -XGET "http://172.16.1.100:9200/_cluster/health?pretty"
# 查看节点列表
curl -XGET "http://172.16.1.100:9200/_cat/nodes?v"
浏览器访问 Elasticsearch-Head:
http://172.16.1.100:9100
五、部署Redis消息队列(仅node-1)
5.1 启动Redis容器
bash
docker run -d \
--name redis \
--restart unless-stopped \
--network host \
-v /data/redis/data:/data \
-v /etc/localtime:/etc/localtime \
redis:latest \
redis-server --requirepass "your_redis_password" --appendonly yes
5.2 验证Redis
bash
docker exec -it redis redis-cli -a your_redis_password ping
# 返回 PONG 表示正常
六、部署Logstash(仅node-1)
6.1 创建配置目录和文件
bash
mkdir -p /data/elk/logstash/{conf,pipeline,logs,data}
6.2 创建logstash主配置文件
bash
vim /data/elk/logstash/conf/logstash.yml
yaml
http.host: "0.0.0.0"
path.data: /usr/share/logstash/data
path.logs: /usr/share/logstash/logs
config.reload.automatic: true
config.reload.interval: 3s
6.3 创建日志采集Pipeline配置
bash
vim /data/elk/logstash/pipeline/logstash.conf
ruby
input {
# 从Filebeat接收日志
beats {
port => 5044
client_inactivity_timeout => 3600
}
# 也可直接读取文件(备选)
file {
type => "nginxaccesslog"
path => "/var/log/nginx/access.log"
start_position => "beginning"
sincedb_path => "/usr/share/logstash/data/sincedb"
}
}
filter {
# 解析Nginx日志
if [type] == "nginxaccesslog" {
grok {
match => {
"message" => "%{COMBINEDAPACHELOG}"
}
}
date {
match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
target => "@timestamp"
}
useragent {
source => "agent"
target => "useragent"
}
}
# 解析系统日志
if [type] == "syslog" {
grok {
match => { "message" => "%{SYSLOGLINE}" }
}
date {
match => [ "timestamp", "MMM dd HH:mm:ss" ]
}
}
}
output {
# 输出到Elasticsearch
if [type] == "nginxaccesslog" {
elasticsearch {
hosts => ["172.16.1.100:9200", "172.16.1.101:9200", "172.16.1.102:9200"]
index => "nginx-log-%{+YYYY.MM.dd}"
user => "elastic"
password => "your_elastic_password"
}
}
if [type] == "syslog" {
elasticsearch {
hosts => ["172.16.1.100:9200", "172.16.1.101:9200", "172.16.1.102:9200"]
index => "syslog-%{+YYYY.MM.dd}"
user => "elastic"
password => "your_elastic_password"
}
}
# 调试输出到控制台
stdout {
codec => rubydebug
}
}
6.4 启动Logstash
bash
docker run -d \
--restart unless-stopped \
--name logstash \
--network host \
-v /etc/localtime:/etc/localtime \
-v /data/elk/logstash/data:/usr/share/logstash/data \
-v /data/elk/logstash/logs:/usr/share/logstash/logs \
-v /data/elk/logstash/pipeline/logstash.conf:/usr/share/logstash/pipeline/logstash.conf \
-v /data/elk/logstash/conf/logstash.yml:/usr/share/logstash/config/logstash.yml \
logstash:8.17.4
6.5 验证Logstash
bash
docker logs -f logstash
七、部署Filebeat(仅node-1)
7.1 安装和配置Nginx(用于生成测试日志)
bash
# 安装Nginx
yum install -y nginx
# 配置Nginx日志格式
vim /etc/nginx/nginx.conf
在http块中添加以下内容:
nginx
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
bash
# 创建测试页面
mkdir -p /var/www/html
echo "Welcome to ELK Test Site" > /var/www/html/index.html
# 创建测试配置
vim /etc/nginx/conf.d/test.conf
nginx
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/access.log main;
location / {
root /var/www/html;
index index.html;
}
}
bash
# 启动Nginx
systemctl start nginx
systemctl enable nginx
systemctl status nginx
7.2 创建Filebeat配置文件
bash
mkdir -p /data/elk/filebeat/conf
vim /data/elk/filebeat/conf/filebeat.yml
yaml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/access.log
fields:
type: nginxaccesslog
fields_under_root: true
ignore_older: 10h
scan_frequency: 10s
- type: log
enabled: true
paths:
- /var/log/messages
fields:
type: syslog
fields_under_root: true
# 输出到Logstash
output.logstash:
hosts: ["172.16.1.100:5044"]
enabled: true
worker: 2
compression_level: 3
# 处理字段
processors:
- drop_fields:
fields: ["input", "host", "agent.type", "agent.ephemeral_id",
"agent.id", "agent.version", "ecs"]
logging.level: info
7.3 启动Filebeat
bash
docker run -d \
--name filebeat \
--restart unless-stopped \
--network host \
-v /data/elk/filebeat/conf/filebeat.yml:/usr/share/filebeat/filebeat.yml \
-v /var/log/nginx:/var/log/nginx \
-v /var/log/messages:/var/log/messages \
-v /etc/localtime:/etc/localtime \
docker.elastic.co/beats/filebeat:8.17.4
7.4 生成测试日志
bash
# 访问Nginx生成日志
for i in {1..100}; do
curl http://localhost/
sleep 1
done
7.5 验证Filebeat
bash
docker logs -f filebeat
八、部署Kibana(仅node-1)
8.1 创建Kibana配置目录
bash
mkdir -p /data/elk/kibana/{conf,logs}
chmod 777 /data/elk/kibana/conf
chmod 777 /data/elk/kibana/logs
8.2 创建Kibana配置文件
bash
vim /data/elk/kibana/conf/kibana.yml
yaml
server.port: 5601
server.host: "0.0.0.0"
server.publicBaseUrl: "http://172.16.1.100:5601"
elasticsearch.hosts: ["http://172.16.1.100:9200", "http://172.16.1.101:9200", "http://172.16.1.102:9200"]
elasticsearch.username: "elastic"
elasticsearch.password: "your_elastic_password"
elasticsearch.ssl.verificationMode: "none"
xpack.reporting.csv.maxSizeBytes: 20971520
xpack.security.encryptionKey: "something_at_least_32_characters"
logging:
appenders:
file:
type: file
fileName: /usr/share/kibana/logs/kibana.log
layout:
type: json
root:
appenders:
- default
- file
i18n.locale: "zh-CN"
8.3 启动Kibana
bash
docker run -d \
--restart unless-stopped \
--name kibana \
--hostname kibana \
--network host \
-v /etc/localtime:/etc/localtime \
-v /data/elk/kibana/logs:/usr/share/kibana/logs \
-v /data/elk/kibana/conf/kibana.yml:/usr/share/kibana/config/kibana.yml \
kibana:8.17.4
8.4 验证Kibana
bash
docker logs -f kibana
浏览器访问:
http://172.16.1.100:5601
九、部署Kafka(可选,替换Redis方案)
如需使用Kafka作为消息队列,可按以下步骤部署:
9.1 启动Zookeeper
bash
docker run -d \
--name zookeeper \
--restart unless-stopped \
--network host \
-e ZOOKEEPER_CLIENT_PORT=2181 \
wurstmeister/zookeeper:latest
9.2 启动Kafka
bash
docker run -d \
--name kafka \
--restart unless-stopped \
--network host \
-e KAFKA_BROKER_ID=1 \
-e KAFKA_ZOOKEEPER_CONNECT=172.16.1.100:2181 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://172.16.1.100:9092 \
-e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 \
-v /data/kafka/data:/kafka \
wurstmeister/kafka:latest
9.3 验证Kafka
bash
# 创建Topic
docker exec -it kafka kafka-topics.sh --create --topic nginx-access \
--bootstrap-server 172.16.1.100:9092 --partitions 3 --replication-factor 1
# 查看Topic列表
docker exec -it kafka kafka-topics.sh --list --bootstrap-server 172.16.1.100:9092
# 消费消息测试
docker exec -it kafka kafka-console-consumer.sh \
--bootstrap-server 172.16.1.100:9092 \
--topic nginx-access --from-beginning
十、系统验证
10.1 验证Elasticsearch集群
bash
# 查看集群健康状态
curl -XGET "http://172.16.1.100:9200/_cluster/health?pretty"
# 查看索引列表
curl -XGET "http://172.16.1.100:9200/_cat/indices?v"
10.2 验证日志数据
在Kibana中创建数据视图(Index Pattern):
- 进入 Management → Stack Management → Kibana → Data Views
- 点击 "Create data view"
- 输入索引模式:
nginx-log-* - 选择时间戳字段:
@timestamp - 点击 "Create data view"
10.3 查看日志
- 进入 Analytics → Discover
- 选择刚才创建的数据视图
- 设置时间范围为最近1小时
- 即可看到Nginx访问日志
十一、索引管理
11.1 查看所有索引
bash
curl -XGET "http://172.16.1.100:9200/_cat/indices?v"
11.2 删除过期索引
bash
# 删除指定日期的索引
curl -XDELETE "http://172.16.1.100:9200/nginx-log-2026.06.16"
11.3 设置索引生命周期管理(ILM)
建议配置ILM策略自动管理索引生命周期,防止索引无限增长。
十二、常见问题排查
12.1 Filebeat无法连接Logstash
- 检查Logstash是否监听5044端口:
netstat -tlnp | grep 5044 - 检查防火墙规则
- 查看Filebeat日志:
docker logs filebeat
12.2 Logstash无法连接Elasticsearch
- 确认Elasticsearch集群状态正常
- 检查认证信息是否正确
- 查看Logstash日志:
docker logs logstash
12.3 Kibana无法访问
- 检查5601端口是否监听
- 确认Kibana配置中的Elasticsearch地址正确
- 查看Kibana日志:
docker logs kibana
12.4 内存不足问题
调整Elasticsearch JVM内存参数:
bash
-e "ES_JAVA_OPTS=-Xms2g -Xmx2g"
十三、优化建议
- JVM调优:根据服务器内存调整ES和Logstash的堆内存大小
- 索引优化:使用ILM策略管理索引生命周期
- 性能监控:部署Metricbeat监控各组件性能
- 安全加固:启用X-Pack安全认证,配置TLS加密
- 高可用:将Redis/Logstash/Kibana也部署为集群模式
总结
通过本指南,我们成功部署了一套完整的ELK日志分析系统,包括:
- 3节点的Elasticsearch集群提供高可用存储
- Logstash负责日志采集和处理
- Filebeat作为轻量级日志采集器
- Kibana提供可视化分析界面
- Redis/Kafka作为消息缓冲队列
这套系统可支持大规模日志采集和分析场景,并可根据实际需求进行横向扩展。在实际生产环境中,建议根据日志量动态调整各组件资源配置,并建立完善的监控告警体系。