Docker搭建Elasticsearch+Redis+Logstash+Filebeat日志分析系统完整指南

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):

  1. 进入 Management → Stack Management → Kibana → Data Views
  2. 点击 "Create data view"
  3. 输入索引模式:nginx-log-*
  4. 选择时间戳字段:@timestamp
  5. 点击 "Create data view"

10.3 查看日志

  1. 进入 Analytics → Discover
  2. 选择刚才创建的数据视图
  3. 设置时间范围为最近1小时
  4. 即可看到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"

十三、优化建议

  1. JVM调优:根据服务器内存调整ES和Logstash的堆内存大小
  2. 索引优化:使用ILM策略管理索引生命周期
  3. 性能监控:部署Metricbeat监控各组件性能
  4. 安全加固:启用X-Pack安全认证,配置TLS加密
  5. 高可用:将Redis/Logstash/Kibana也部署为集群模式

总结

通过本指南,我们成功部署了一套完整的ELK日志分析系统,包括:

  • 3节点的Elasticsearch集群提供高可用存储
  • Logstash负责日志采集和处理
  • Filebeat作为轻量级日志采集器
  • Kibana提供可视化分析界面
  • Redis/Kafka作为消息缓冲队列

这套系统可支持大规模日志采集和分析场景,并可根据实际需求进行横向扩展。在实际生产环境中,建议根据日志量动态调整各组件资源配置,并建立完善的监控告警体系。