TL;DR

  • 场景: 搭建集中式日志系统,实现日志采集、存储、分析、可视化
  • 结论: ELK 栈提供完整的日志解决方案,ES 负责存储与搜索,Logstash 负责采集,Kibana 负责可视化
  • 产出: 架构设计、核心概念、查询 DSL、错误速查

集中式日志系统

核心功能

功能说明
收集多源日志采集
传输日志传输管道
存储分布式存储
分析全文搜索与聚合
告警异常监控与告警

架构

日志源 → Logstash → Elasticsearch ← Kibana

Elasticsearch 核心概念

集群(Cluster)与节点(Node)

节点类型职责
Master 节点集群管理、索引创建、负载均衡
Data 节点数据存储、文档 CRUD
Coordinating 节点请求转发、结果聚合

索引(Index)

  • 类似关系型数据库的表
  • 支持动态映射
  • 可设置分片与副本数

分片(Shard)与副本(Replica)

类型作用
主分片数据水平扩展
副本分片高可用、读并发

查询 DSL

// 全文搜索
{"query": {"match": {"content": "error"}}}

// 精确查询
{"query": {"term": {"status": "failed"}}}

// 范围查询
{"query": {"range": {"@timestamp": {"gte": "now-1h"}}}}

// 布尔组合
{"query": {"bool": {"must": [{"match": {"level": "error"}}], "filter": [{"range": {"@timestamp": {"gte": "now-1h"}}}]}}}

聚合

类型用途
Bucket分组统计
Metric数值计算
Pipeline管道聚合

Logstash

作用

实时数据收集引擎,支持多种数据源:

  • 文件日志
  • 网络协议(TCP/UDP/HTTP)
  • 数据库(JDBC)
  • 消息队列(Kafka、Redis)

配置文件结构

input {
  file {
    path => "/var/log/*.log"
    start_position => "beginning"
  }
}

filter {
  grok {
    match => {"message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:content}"}
  }
  date {
    match => ["timestamp", "yyyy-MM-dd HH:mm:ss"]
  }
}

output {
  elasticsearch {
    hosts => ["h121.wzk.icu:9200"]
    index => "app-logs-%{+YYYY.MM.dd}"
  }
}

Kibana

作用

Elasticsearch 可视化分析平台:

  • 索引管理
  • 图形化查询
  • 可视化仪表盘
  • 监控告警

对比 Solr

特性ElasticsearchSolr
分布式协调内置依赖 ZooKeeper
JSON 支持原生需要配置
实时搜索优势需配置近实时
文档模型灵活严格模式

排错清单

集群 Yellow/Red

症状: 集群状态为 Yellow 或 Red

根因:

  • 节点离线
  • 磁盘水位过高
  • 分片分配失败

修复:

# 检查节点状态
curl -XGET 'h121.wzk.icu:9200/_cluster/health'

# 检查磁盘水位
curl -XGET 'h121.wzk.icu:9200/_cat/allocation?v'

# 清理磁盘或调整分片

写入被拒

症状: 写入请求被拒绝

根因:

  • JVM 堆压力
  • 字段爆炸

修复:

# 监控 JVM
curl -XGET 'h121.wzk.icu:9200/_nodes/jvm'

# 限制字段数
index.mapping.total_fields.limit: 1000

慢查询

症状: 查询响应时间长

根因:

  • 通配符查询
  • 深分页
  • 未建索引

修复:

  • 避免通配符开头:*error
  • 使用 scroll 或 search_after 替代 from/size
  • 优化查询条件

时间轴错乱

症状: 日志时间顺序混乱

根因:

  • 时区未统一
  • Logstash 时间解析错误

修复:

filter {
  date {
    match => ["timestamp", "yyyy-MM-dd HH:mm:ss"]
    timezone => "Asia/Shanghai"
  }
}

索引只读

症状: 索引变为 read-only

根因:

  • 磁盘高水位触发(默认 85%)

修复:

# 清理磁盘或调整阈值
curl -XPUT 'h121.wzk.icu:9200/_all/_settings' -d '{"index.blocks.read_only_allow_delete": null}'

# 调整高水位线
cluster.routing.allocation.disk.threshold_enabled: true
cluster.routing.allocation.disk.watermark.low: 85%
cluster.routing.allocation.disk.watermark.high: 90%

ILM 索引生命周期管理

阶段

阶段操作
Hot频繁写入/查询
Warm定期合并,只读
Cold归档存储
Delete删除

配置

{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {"max_age": "1d", "max_size": "50gb"}
        }
      },
      "warm": {
        "min_age": "30d",
        "actions": {"forcemerge": {"max_num_segments": 1}}
      },
      "cold": {
        "min_age": "90d",
        "actions": {"freeze": {}}
      },
      "delete": {
        "min_age": "365d",
        "actions": {"delete": {}}
      }
    }
  }
}