ELK 简单实战

elk es kibana filebeat logstash

Posted by gomyck on October 22, 2021

因线上用户量与日俱增, 日志运维工作愈加困难, 日志量以及分布式架构带来的碎片化, 需要使用一种统一管理的方式

下面是我在实际运用中总结的安装调试步骤, 此时此刻 ELK 版本为: v 7.15.1
以下的步骤其实可以简化 input 的链路, 可以直接使用 logstash 的 log4j 组件来作为 input, 但是改造需要动服务, 就作罢了, 而且也会造成服务与服务之间的耦合性

各个服务提供的能力, 在本文就不叙述了, 百度一下到处都有, 阅读本篇文章的前提是至少你了解 ELK 技术栈

elasticsearch

  1. 下载 jdk11+ 并配置 ES_JAVA_HOME
  2. 下载 ES https://www.elastic.co/cn/downloads/elasticsearch 找到 linux 64版本的 使用 curl -O 下载
  3. 创建用户 gomyck 并把 es 所在目录 chown 到 gomyck 上 chown -Rh gomyck:root dir
  4. 在 /etc/sysctl.conf 追加最大虚拟空间限制 vm.max_map_count=655360, 记得 sysctl -p 使系统配置生效
  5. 修改elasticsearch.yml 开启密码验证 允许非本机 IP 访问
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#指定data 存储文件位置
path.data: /usr/share/gomyck/esdata
#关闭 geoip 更新
ingest.geoip.downloader.enabled: false
#指定 master 节点名称
cluster.initial_master_nodes: ["afterservice-log"]
#当前节点名称
node.name: afterservice-log

#开启鉴权
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
network.host: 0.0.0.0
discovery.seed_hosts: ["0.0.0.0"]
  1. 启动 es
    1
    2
    
    # 可执行文件在 bin 文件夹下  -d 为 后台运行
    $ ./elasticsearch -d
    
  2. 添加一个用户
    1
    2
    
    # 可执行文件在 bin 文件夹下
    $ ./elasticsearch-users add gomyck
    
  3. 为用户添加超级管理员权限, 否则 kibana 不能获取 es 版本信息, 导致启动报错
    1
    2
    
    # 可执行文件在 bin 文件夹下
    $ ./elasticsearch-users roles gomyck -a superuser
    
  4. 为 ES 增加堆内存: config/jvm.options.d 添加一个配置: gomyck_es.option -> -Xms2g

kibana

  1. 下载 kibana https://www.elastic.co/cn/downloads/kibana 找到 linux 64版本的 使用 curl -O 下载
  2. 编辑 kibana.yml
    1
    2
    3
    4
    5
    6
    
    xpack.encryptedSavedObjects.encryptionKey: 84FF5616002D30323B2ACDB3C8C0CAC2
    server.host: "0.0.0.0"
    elasticsearch.hosts: ["http://localhost:9200"]
    elasticsearch.username: "gomyck"
    elasticsearch.password: "xxxxxx"
    elasticsearch.requestHeadersWhitelist: [ authorization ]
    
  3. 启动 kibana
    1
    2
    
    # 可执行文件在 bin 文件夹下
    $ nohup ./kibana serve >ck.log 2>&1 &
    

logstash

一开始并没有考虑使用 logstash 作为 es 的 input, 因为 logstash 作为 java 应用程序, 并且功能庞大, 还是比 golang 写的 filebeat 吃系统资源, 后来也是因为它功能强大才不得不使用他, 哈哈
不过最新版的 filebeat 已经支持 grok 了, 其实可以不用 logstash, 因为链路长还涉及到时钟同步问题, 在后面的配置中会带解决办法
  1. 下载 logstash https://www.elastic.co/cn/downloads/logstash
  2. 编辑 logstash.yml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    ------------ HTTP API Settings -------------
    http.host: 0.0.0.0
    mv logstash.conf.simple logstash.conf vim logstash.conf
    input {
     beats {
         port => 5044
     }
    }
    filter {
     grok {
         match => {
             "message" = > "(?<logTime>(%{YEAR}[./-]%{MONTHNUM}[./-]%{MONTHDAY})\s+%{TIME}) (?<thread>\[.*\]) %{LOGLEVEL:logLevel}.*-%{JAVACLASS:className} (?<logInfo>.*)"
         }
     }
     date {
         match => ["logTime", "ISO8601"]
         target => "@timestamp"
     }
    }
    output {
     elasticsearch {
         hosts => ["http://localhost:9200"]
         index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
         user => "gomyck"
         password => "*****"
     }
    }
    
最恶心的地方就是 grok 的正则编写, 因为 grok 的现有模版都不满足我的日志格式, 所以必须还要学习一下 grok 的 DSL, 其实跟正则差不多, 可以理解为正则的扩展, 因为它可以把正则匹配到的值赋到变量名上
关于时钟不同步问题, 因为 filebeat 的 input 和 output 并不是单线程顺序执行, logstash 也是如此, 所以存在 后生产 的日志先被上送到 es, 这其中, 可能在 logstash 阶段就已经串版了, 也可能在 es 上送阶段串版
为了解决这个问题, 可以在拦截器中定义一个 date 组件, 使用服务日志的时间作为 es 的标准保留字@timestamp(ES 根据此字段来排序消息, 可以在 logs 控制台验证)
  1. 启动 logstash
    1
    2
    
    # 自动应用已修改的配置
    $ ./logstash -f ../conf/logstash.conf --config.reload.automatic
    

filebeat

  1. 在日志采集机器上安装 filebeat (注意 filebeat 的版本号要和 kibana 一致)
    1
    2
    
    $ curl -L -O xxxx.rpm
    $ sudo rpm -vi xxxx.rpm
    
  2. 修改 /etc/filebeat/filebeat.yml 以设置连接信息(注意编辑 input 和 output 就可以了, 这个比较好配置)
  3. 开启 logstash 模块
    1
    
    $ sudo filebeat modules enable logstash
    
  4. 启动 filebeat
    1
    
    $ sudo service filebeat start
    

2022-3-15 补充

关于多服务器自定义索引:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
filebeat.inputs:

- type: log
  enabled: true
  paths:
    - /opt/appWeb/logs/info/*.log
  fields:
    from: jiazhang

- type: log
  enabled: true
  paths:
    - /opt/appOrgan/logs/info/*.log
  fields:
    from: jigou

# 允许自动生成index模板
setup.template.enabled: true
# 如果存在模块则覆盖
setup.template.overwrite: true
# 生成index模板的名称
setup.template.name: "gomyck_log"
# 生成index模板匹配的index格式
setup.template.pattern: "gomyck-*"
# 关闭 ILM 否则模版不生效
setup.ilm.enabled: false

output.elasticsearch:
  hosts: ["xxxxxx:xxxx"]
  index: "gomyck-organ-%{+yyyy.MM.dd}"
  username: "xxxxxx"
  password: "xxxxxx"

自定义索引, 要在 es 中配置索引生命周期策略, 点击 Index Lifecycle Policies -> filebeat -> 选择后面的加号 -> 勾选(Show legacy index templates) -> 选择添加的模版 index

一些其他的说明

  1. grok 的调试工具 http://kibanaIp:5601/app/dev_tools#/grokdebugger

  2. es 索引管理在 management -> stack management 下, 可以配置一些滚动策略防止日志日积月累过大导致的服务器存储空间不足问题

  3. es 索引策略要自己去配置, 如果没有设置索引别名(alias), 不能勾选 Rollover, 该选项意味着在到达某个节点, 会滚动生成新的索引, 因为我们已经有自己的策略了, 所以不要勾他

  4. es 服务器磁盘在占用率达到 90%以上会出现只读的现象, 而且会导致一些未知问题, 比如 kibana 不能登录