ELK+Filebeat介绍

ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称(但是后期出现的filebeat(beats中的一种)可以用来替代logstash的数据收集功能,比较轻量级)。市面上也被成为Elastic Stack。

Filebeat是用于转发和集中日志数据的轻量级传送工具。Filebeat监视您指定的日志文件或位置,收集日志事件,并将它们转发到Elasticsearch或 Logstash进行索引。Filebeat的工作方式如下:启动Filebeat时,它将启动一个或多个输入,这些输入将在为日志数据指定的位置中查找。对于Filebeat所找到的每个日志,Filebeat都会启动收集器。每个收集器都读取单个日志以获取新内容,并将新日志数据发送到libbeat,libbeat将聚集事件,并将聚集的数据发送到为Filebeat配置的输出。

Logstash是免费且开放的服务器端数据处理管道,能够从多个来源采集数据,转换数据,然后将数据发送到您最喜欢的“存储库”中。Logstash能够动态地采集、转换和传输数据,不受格式或复杂度的影响。利用Grok从非结构化数据中派生出结构,从IP地址解码出地理坐标,匿名化或排除敏感字段,并简化整体处理过程。

Elasticsearch是Elastic Stack核心的分布式搜索和分析引擎,是一个基于Lucene、分布式、通过Restful方式进行交互的近实时搜索平台框架。Elasticsearch为所有类型的数据提供近乎实时的搜索和分析。无论您是结构化文本还是非结构化文本,数字数据或地理空间数据,Elasticsearch都能以支持快速搜索的方式有效地对其进行存储和索引。

Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana,可以通过各种图表进行高级数据分析及展示。并且可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以汇总、分析和搜索重要数据日志。还可以让海量数据更容易理解。它操作简单,基于浏览器的用户界面可以快速创建仪表板(dashboard)实时显示Elasticsearch查询动态。

这4个组件的流程图如下:

TypeError: Cannot read properties of undefined (reading 'v')

简单说明他们的关系就是:

  1. Filebeat负责收集应用写到磁盘上的日志,并将日志发送给Logstash。
  2. Logstash处理来自Filebeat的日志,并将处理后的日志保存到Elasticsearch索引库。
  3. Elasticsearch存储来自logstash的日志。
  4. Kbana从Elasticsearch搜索日志,并展示到页面。

与平常普通的ELK相比,Filebeat结合Logstash带来的优势:

  1. 水平可扩展性,高可用性和可变负载处理:filebeat和logstash可以实现节点之间的负载均衡,多个logstash可以实现logstash的高可用
  2. 消息持久性与至少一次交付保证:使用Filebeat或Winlogbeat进行日志收集时,可以保证至少一次交付。从Filebeat或Winlogbeat到Logstash以及从Logstash到Elasticsearch的两种通信协议都是同步的,并且支持确认。Logstash持久队列提供跨节点故障的保护。对于Logstash中的磁盘级弹性,确保磁盘冗余非常重要。
  3. 具有身份验证和有线加密的端到端安全传输:从Beats到Logstash以及从 Logstash到Elasticsearch的传输都可以使用加密方式传递 。与Elasticsearch进行通讯时,有很多安全选项,包括基本身份验证,TLS,PKI,LDAP,AD和其他自定义领域
  4. ELK结构因为需要在各个服务器上部署 Logstash,而它比较消耗 CPU 和内存资源,所以比较适合计算资源丰富的服务器,否则容易造成服务器性能下降,甚至可能导致无法正常工作。ELK+Filebeat架构解决了 Logstash 在各服务器节点上占用系统资源高的问题。相比 Logstash,Beats 所占系统的 CPU 和内存几乎可以忽略不计。

ELK部署

环境概要:

  1. 指定环境信息版本:7.16.1。
    新建一个.env文件,添加以下内容:
ELK_VERSION=7.16.1
  1. 部署方式
    本文采用docker的形式去部署,Docker 的镜像地址:Docker @ Elastic
  2. 本机的示例IP为:192.168.1.240

部署Elasticsearch

Elasticsearch 是一个实时的分布式搜索和分析引擎,它可以用于全文搜索,结构化搜索以及分析。它是一个建立在全文搜索引擎 Apache Lucene 基础上的搜索引擎,使用 Java 语言编写。

1. docker-compose.yml 新增Elasticsearch内容

version: '3'
services:
  elasticsearch:                    # 服务名称
    image: "elasticsearch:${ELK_VERSION}"      # 使用的镜像
    container_name: elasticsearch   # 容器名称
    restart: always                 # 失败自动重启策略
    environment:
      - node.name=node-1                   # 节点名称,集群模式下每个节点名称唯一
      - network.publish_host=192.168.1.240  # 用于集群内各机器间通信,对外使用,其他机器访问本机器的es服务,一般为本机宿主机IP
      - network.host=0.0.0.0                # 设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0,即本机      
      - discovery.seed_hosts=192.168.1.240          # es7.0之后新增的写法,写入候选主节点的设备地址,在开启服务后,如果master挂了,哪些可以被投票选为主节点
      - cluster.initial_master_nodes=192.168.1.240  # es7.0之后新增的配置,初始化一个新的集群时需要此配置来选举master
      - cluster.name=es-cluster     # 集群名称,相同名称为一个集群, 三个es节点须一致
      - bootstrap.memory_lock=true  # 内存交换的选项,官网建议为true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m" # 设置内存,如内存不足,可以尝试调低点
    ulimits:        # 栈内存的上限
      memlock:
        soft: -1    # 不限制
        hard: -1    # 不限制
    volumes:
      - $PWD/elasticsearch/config:/usr/share/elasticsearch/config  # 将容器中es的配置文件映射到本地,本地必须提前先有该文件,设置跨域, 否则head插件无法连接该节点
      - $PWD/elasticsearch/data:/usr/share/elasticsearch/data  # 存放数据的文件
      - $PWD/elasticsearch/plugins:/usr/share/elasticsearch/plugins  # 存放插件的文件
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 9200:9200    # http端口,可以直接浏览器访问
      - 9300:9300    # es集群之间相互访问的端口,jar之间就是通过此端口进行tcp协议通信,遵循tcp协议。

2. 新建或拷贝elasticsearch.yml 文件到本地

mkdir -p elasticsearch/{data,plugins}
docker run -d --rm --name elasticsearch  docker.elastic.co/elasticsearch/elasticsearch:7.16.1
docker cp elasticsearch:/usr/share/elasticsearch/config/ elasticsearch/
docker stop elasticsearch
chown -R 1000:root elasticsearch/config/
chown 1000:root elasticsearch/data/
chmod 775 elasticsearch/data/
chown 1000:root elasticsearch/plugins/

3. 修改内存设置

/etc/sysctl.conf 添加以下内容:

vm.max_map_count=655360

保存后,执行刷新命令生效:

sysctl -p

4. 在 elasticsearch/config/elasticsearch.yml 文件新增如下内容:

http.cors.enabled: true        # 是否支持跨域
http.cors.allow-origin: "*"    # 表示支持所有域名

5. 执行 elasticsearch

docker-compose up -d

6. 查看状态

浏览器打开:http://192.168.4.5:9200/_cluster/health?pretty
查看状态,"status": "green" 为正常。

{
  "cluster_name": "es-cluster",
  "status": "green",
  "timed_out": false,
  "number_of_nodes": 1,
  "number_of_data_nodes": 1,
  "active_primary_shards": 0,
  "active_shards": 0,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_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
}

部署Filebeat

Filebeat是本地文件的日志数据采集器,可监控日志目录或特定日志文件(tail file),并将它们转发给Elasticsearch或Logstatsh进行索引、kafka等。带有内部模块(auditd,Apache,Nginx,System和MySQL),可通过一个指定命令来简化通用日志格式的收集,解析和可视化。

1. 创建目录

mkdir -p filebeat/{conf,data,logs}

2. 创建自定义文件

创建 filebeat/conf/filebeat.yml 文件,(这里指定容器内nginx的日志目录),添加以下内容:

filebeat.inputs:
- type: log
  enabled: true
  paths:
  - /var/log/nginx/*.log
  fields:
    log_source: nginx

output.logstash:
  hosts: ["192.168.1.240:5044"]

3. docker-compose.yml 新增Filebeat内容

  filebeat:
    image: "docker.elastic.co/beats/filebeat:${ELK_VERSION}"
    container_name: filebeat
    user: root # 必须为root,否则会因为无权限而无法启动
    restart: always
    depends_on:
      - elasticsearch
      - logstash
    environment:
      - strict.perms=false  # 设置是否对配置文件进行严格权限校验
    volumes:
      - $PWD/filebeat/conf/filebeat.yml:/usr/share/filebeat/filebeat.yml
      # 映射到容器中[作为数据源]
      - $PWD/filebeat/logs:/usr/share/filebeat/logs:rw
      #- $PWD/filebeat/data:/usr/share/filebeat/data:rw
      - /etc/localtime:/etc/localtime:ro
      - /usr/local/nginx/logs/:/var/log/nginx/
    # 将指定容器连接到当前连接,可以设置别名,避免ip方式导致的容器重启动态改变的无法连接情况
    links:
      - logstash

这里指定一个本地的/usr/local/nginx/logs/nginx日志目录,映射到容器的/var/log/nginx/里面。

部署Logstash

Logstash 是一个具有实时渠道能力的数据收集引擎,主要用于日志的收集与解析,并将其存入 ElasticSearch中。

1. 新建目录:

mkdir -p logstash/conf.d/

2. 创建logstash配置文件

新建一个 logstash/logstash.yml 文件,并添加以下内容:

path.config: /usr/share/logstash/conf.d/*.conf
path.logs: /var/log/logstash

Logstash的脚本由input,filter,output三个部分构成,同时这三个部分都支持众多的插件。

  • input Logstash的数据来源,可以是文件、Kafka、RabbitMQ、socket等等。
  • filter 从input接收到的数据经过filter进行数据类型转换、字段增减和修改、以及一些逻辑处理。虽然 filter模块是非必选的部分,但由于其可以将收集的日志格式化,合理的字段类型定义和辅助字段的创建可以使得以后的查询统计更加容易和高效。所以filter模块的配置是整个Logstash配置文件最重要的地方。
  • output 将filter得到的结果输出,可以是文件,Elasticsearch,Kafka等等。

收集到的日志能否发挥最大的价值就在filter这里,特别是以后需要统计的一些字段,比如用户id、设备信息、ip地址;
还有就是一些有必要转换成数字类型的字段最好在filter这里就转换完成,数字类型的字段可以在统计的时候使用数学运算,例如求均值、求90Line等。

解析nginx日志通常使用grok组件。表达式使用的基本语法是下面这样的:

%{SYNTAX:SEMANTIC}

用%{} 扩起来的就表示一组正则匹配规则,SYNTAX是指grok里已经预定义好的正则表达式,SEMANTIC是指匹配之后要放的字段名字。
下面是NUMBER表达式的使用示例,NUMBER 表示在grok中该正则表达式匹配的别名。冒号后面的是准备输出的字段名称,duration将在检索时可以被分析到。

%{NUMBER:duration}

在 grok-patterns 里面NUMBER是用下面的正则表达式定义的,它基于了BASE10NUM的定义。

BASE10NUM (?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+)))
NUMBER (?:%{BASE10NUM})

下面我们列举了一段极简的nginx日志片段:

55.3.244.1 GET /index.html 15824 0.043

那么使用下面的正则匹配组合就能成功匹配上面的日志片段:

%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}

grok给我们提供了很多实用的预定义的正则表达式,下面是截取的一小部分。

# Networking
MAC (?:%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC})
CISCOMAC (?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4})
WINDOWSMAC (?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2})
COMMONMAC (?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2})
IPV6 ((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?
IPV4 (?<[外链图片转存失败,源站可能有防盗0-9])(?:!链机(img-V?:[0E1]?[9],2}|2[0-4][0-9]|25[0-{5336])[.](?:[0-8]?[0-)]{1,(}|2[0-:0[0-9]|25[0-5])-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])][.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]))(?![0-9])
IP (?:%{IPV6}|%{IPV4})
HOSTNAME \b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:\.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*(\.?|\b)
IPORHOST (?:%{IP}|%{HOSTNAME})
HOSTPORT %{IPORHOST}:%{POSINT}

想要了解更多的grok正则匹配请参考这里github.com/logstash-plugins/logstash-patterns-core/blob/main/patterns/legacy/grok-patterns

nginx.conf 定义的log格式是:

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"';

实际的nginx日志如下:

192.168.1.137 - - [23/May/2022:14:33:18 +0800] "GET /index.php?m=message&f=ajaxGetMessage&t=html&windowBlur=1 HTTP/1.1" 200 5 "http://192.168.1.240:10003/index.php?m=bug&f=browse&productID=2" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.50"

所以对应的grok表达式是:

%{IPORHOST:remote_ip} - %{DATA:user_name} \[%{HTTPDATE:time}\] \"%{WORD:method} %{DATA:url} HTTP/%{NUMBER:http_version}\" %{NUMBER:response_code} %{NUMBER:body_sent:bytes} \"%{DATA:referrer}\" \"%{DATA:user_agent}\"

可以先拿其中一条日志,使用Grok Debugger 工具在线调试下,看看写的grok是否正确。
3d4e37db896e4bbda4efbd9c4bedd841
没问题后,就可以接着创建 logstash/conf.d/nginx.conf,添加以下内容:

input {
    beats {
        port => 5044
        codec => "json"
    }
}
filter {
    grok {
        match => { "message" => '%{IPORHOST:remote_ip} - %{DATA:user_name} \[%{HTTPDATE:time}\] \"%{WORD:method} %{DATA:url} HTTP/%{NUMBER:http_version}\" %{NUMBER:response_code} %{NUMBER:body_sent:bytes} \"%{DATA:referrer}\" \"%{DATA:user_agent}\"' }
        remove_field => "message"
    }
}
output {
    elasticsearch {
        hosts => ["192.168.1.240:9200"]
        index => "nginx-access-log-%{+YYYY.MM.dd}"
    }
    stdout { codec => rubydebug }
}
  • filter里面有一句remove_field,作用是删除message字段,message字段是默认的字段记录的是原始nginx日志的一整行,删除后可以减少es的存储占用
  • output里的index,按天存储到Elasticsearch索引中。

注意:里面有个 user_agent 字段名,不能用 agent 代替。因为在下面看 logstash 的日志中会发现filebeat 会推送一个 agent 字段名。如果自己定义一个agent字段名,会把 grok 中的 agent 覆盖掉。

"agent" => {
              "id" => "dbfdd21f-edf6-4e04-beca-78d20dbea316",
            "type" => "filebeat",
         "version" => "7.16.1",
    "ephemeral_id" => "35990523-3475-4235-bbae-a577c583b46e",
            "name" => "69760ea94693",
        "hostname" => "69760ea94693"
},

然后可以启动logstash了。

3. docker-compose.yml 新增Logstash内容

  logstash:
    image: "docker.elastic.co/logstash/logstash:${ELK_VERSION}"
    container_name: logstash
    restart: always
    volumes:
      - $PWD/logstash/logstash.yml:/usr/share/logstash/config/logstash.yml
      - $PWD/logstash/conf.d/:/usr/share/logstash/conf.d/
      - /etc/localtime:/etc/localtime:ro
    depends_on:
      - elasticsearch #kibana在elasticsearch启动之后再启动
    links:
      - elasticsearch
    ports:
      - "5044:5044"

4. 启动容器

docker-compose up -d

5. 测试logstash配置

在容器里通过logstash -f /usr/share/logstash/conf.d/nginx.conf --config.test_and_exit测试logstash配置是否正确

# docker exec -it logstash bash
bash-4.2$ logstash -f /usr/share/logstash/conf.d/nginx.conf --config.test_and_exit
Using bundled JDK: /usr/share/logstash/jdk
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.

Sending Logstash logs to /var/log/logstash which is now configured via log4j2.properties
[2022-05-23T09:30:34,217][INFO ][logstash.runner          ] Log4j configuration path used is: /usr/share/logstash/config/log4j2.properties
[2022-05-23T09:30:34,225][INFO ][logstash.runner          ] Starting Logstash {"logstash.version"=>"7.16.1", "jruby.version"=>"jruby 9.2.20.1 (2.5.8) 2021-11-30 2a2962fbd1 OpenJDK 64-Bit Server VM 11.0.13+8 on 11.0.13+8 +indy +jit [linux-x86_64]"}
[2022-05-23T09:30:35,233][WARN ][logstash.config.source.multilocal] Ignoring the 'pipelines.yml' file because modules or command line options are specified
[2022-05-23T09:30:36,796][INFO ][org.reflections.Reflections] Reflections took 154 ms to scan 1 urls, producing 119 keys and 417 values 
[2022-05-23T09:30:38,043][WARN ][deprecation.logstash.codecs.json] Relying on default value of `pipeline.ecs_compatibility`, which may change in a future major release of Logstash. To avoid unexpected changes when upgrading Logstash, please explicitly declare your desired ECS Compatibility mode.
[2022-05-23T09:30:38,114][WARN ][deprecation.logstash.inputs.beats] Relying on default value of `pipeline.ecs_compatibility`, which may change in a future major release of Logstash. To avoid unexpected changes when upgrading Logstash, please explicitly declare your desired ECS Compatibility mode.
[2022-05-23T09:30:38,314][WARN ][deprecation.logstash.codecs.plain] Relying on default value of `pipeline.ecs_compatibility`, which may change in a future major release of Logstash. To avoid unexpected changes when upgrading Logstash, please explicitly declare your desired ECS Compatibility mode.
[2022-05-23T09:30:38,350][WARN ][deprecation.logstash.outputs.elasticsearch] Relying on default value of `pipeline.ecs_compatibility`, which may change in a future major release of Logstash. To avoid unexpected changes when upgrading Logstash, please explicitly declare your desired ECS Compatibility mode.
Configuration OK
[2022-05-23T09:30:38,526][INFO ][logstash.runner          ] Using config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash

最后提示 sing config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash
测试通过。

6. 查看Logstash 日志

通过执行以下命令查看日志

 docker-compose logs -f logstash

出现如下内容表示已经获取到从filebeat传来的nginx访问日志

logstash         |{
logstash         |               "log" => {
logstash         |         "offset" => 2323638,
logstash         |           "file" => {
logstash         |             "path" => "/var/log/nginx/zentaopms.access.log"
logstash         |         }
logstash         |     },
logstash         |      "http_version" => "1.1",
logstash         |         "body_sent" => "0",
logstash         |             "input" => {
logstash         |         "type" => "log"
logstash         |     },
logstash         |         "remote_ip" => "192.168.1.137",
logstash         |             "agent" => {
logstash         |                   "id" => "dbfdd21f-edf6-4e04-beca-78d20dbea316",
logstash         |                 "type" => "filebeat",
logstash         |              "version" => "7.16.1",
logstash         |         "ephemeral_id" => "35990523-3475-4235-bbae-a577c583b46e",
logstash         |                 "name" => "69760ea94693",
logstash         |             "hostname" => "69760ea94693"
logstash         |     },
logstash         |              "host" => {
logstash         |         "name" => "69760ea94693"
logstash         |     },
logstash         |         "user_name" => "-",
logstash         |     "response_code" => "304",
logstash         |          "referrer" => "http://192.168.1.240:10003/js/kindeditor//kindeditor.min.css",
logstash         |            "method" => "GET",
logstash         |               "ecs" => {
logstash         |         "version" => "1.12.0"
logstash         |     },
logstash         |        "@timestamp" => 2022-05-23T09:30:54.385Z,
logstash         |               "url" => "/js/kindeditor//themes/default/default.png",
logstash         |          "@version" => "1",
logstash         |              "tags" => [
logstash         |         [0] "_jsonparsefailure",
logstash         |         [1] "beats_input_codec_json_applied"
logstash         |     ],
logstash         |            "fields" => {
logstash         |         "log_source" => "nginx"
logstash         |     },
logstash         |              "time" => "20/Oct/2021:17:45:41 +0800",
logstash         |        "user_agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36 Edg/94.0.992.47"
logstash         | }

部署Kibana

Kibana 是一个为 Logstash 和 ElasticSearch 提供的日志分析的 Web 接口。可使用它对日志进行高效的搜索、可视化、分析等各种操作。

1. 新建目录

mkdir kibana

拷贝配置文件

docker run -d --rm --name kibana docker.elastic.co/kibana/kibana:7.16.1
docker cp kibana:/opt/kibana/config/kibana.yml kibana/
docker stop kibana

2. docker-compose.yml 新增kibana内容

  kibana:
    image: "docker.elastic.co/kibana/kibana:${ELK_VERSION}"
    container_name: kibana
    restart: always
    depends_on:
      - elasticsearch
    #environment:
    #  - ELASTICSEARCH_URL=http://elasticsearch:9200
    ports:
      - "5601:5601"
    volumes:
      - $PWD/kibana/kibana.yml:/opt/kibana/config/kibana.yml
      - /etc/localtime:/etc/localtime:ro

3. 修改配置文件

修改kibana/kibana.yml配置文件,在 elasticsearch.hosts 上设置 elasticsearch 的IP:

server.host: "0.0.0.0"
server.shutdownTimeout: "5s"
elasticsearch.hosts: [ "http://192.168.1.240:9200" ]
monitoring.ui.container.elasticsearch.enabled: true

如果需要中文,在这个配置文件上加入: i18n.locale: "zh-CN"

4. 启动容器

docker-compose up -d

至此EKL + Filebeat 部署完成,完整docker-compose.yml文件内容如下:

version: '3'
services:
  elasticsearch:                    # 服务名称
    image: "docker.elastic.co/elasticsearch/elasticsearch:${ELK_VERSION}"      # 使用的镜像
    container_name: elasticsearch   # 容器名称
    restart: always                 # 失败自动重启策略
    environment:
      - node.name=node-1                   # 节点名称,集群模式下每个节点名称唯一
      - network.publish_host=192.168.1.240  # 用于集群内各机器间通信,对外使用,其他机器访问本机器的es服务,一般为本机宿主机IP
      - network.host=0.0.0.0                # 设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0,即本机
      - discovery.seed_hosts=192.168.1.240          # es7.0之后新增的写法,写入候选主节点的设备地址,在开启服务后,如果master挂了,哪些可以被投票选为主节点
      - cluster.initial_master_nodes=192.168.1.240  # es7.0之后新增的配置,初始化一个新的集群时需要此配置来选举master
      - cluster.name=es-cluster     # 集群名称,相同名称为一个集群, 三个es节点须一致
      - bootstrap.memory_lock=true  # 内存交换的选项,官网建议为true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m" # 设置内存,如内存不足,可以尝试调低点
    ulimits:        # 栈内存的上限
      memlock:
        soft: -1    # 不限制
        hard: -1    # 不限制
    volumes:
      - $PWD/elasticsearch/config:/usr/share/elasticsearch/config  # 将容器中es的配置文件映射到本地,本地必须提前先有该文件,设置跨域, 否则head插件无法连接该节点
      - $PWD/elasticsearch/data:/usr/share/elasticsearch/data  # 存放数据的文件
      - $PWD/elasticsearch/plugins:/usr/share/elasticsearch/plugins  # 存放插件的文件
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "9200:9200"    # http端口,可以直接浏览器访问
      - "9300:9300"    # es集群之间相互访问的端口,jar之间就是通过此端口进行tcp协议通信,遵循tcp协议。


  filebeat:
    image: "docker.elastic.co/beats/filebeat:${ELK_VERSION}"
    container_name: filebeat
    user: root # 必须为root,否则会因为无权限而无法启动
    depends_on:
      - elasticsearch
      - logstash
    environment:
      - strict.perms=false  # 设置是否对配置文件进行严格权限校验
    volumes:
      - $PWD/filebeat/conf/filebeat.yml:/usr/share/filebeat/filebeat.yml
      # 映射到容器中[作为数据源]
      - $PWD/filebeat/logs:/usr/share/filebeat/logs:rw
      #- $PWD/filebeat/data:/usr/share/filebeat/data:rw
      - /etc/localtime:/etc/localtime:ro
      - /data/chandao/nginx/logs/:/var/log/nginx/
    # 将指定容器连接到当前连接,可以设置别名,避免ip方式导致的容器重启动态改变的无法连接情况
    links:
      - logstash

  logstash:
    image: "docker.elastic.co/logstash/logstash:${ELK_VERSION}"
    container_name: logstash
    restart: always
    volumes:
      - $PWD/logstash/logstash.yml:/usr/share/logstash/config/logstash.yml
      - $PWD/logstash/conf.d/:/usr/share/logstash/conf.d/
      - /etc/localtime:/etc/localtime:ro
    depends_on:
      - elasticsearch #kibana在elasticsearch启动之后再启动
    links:
      - elasticsearch
    ports:
      - "5044:5044"


  kibana:
    image: "docker.elastic.co/kibana/kibana:${ELK_VERSION}"
    container_name: kibana
    restart: always
    depends_on:
      - elasticsearch
    #environment:
    #  - ELASTICSEARCH_URL=http://elasticsearch:9200
    ports:
      - "5601:5601"
    volumes:
      - $PWD/kibana/kibana.yml:/opt/kibana/config/kibana.yml
      - /etc/localtime:/etc/localtime:ro

浏览器进入Kibana

浏览器访问:http://192.168.1.240:5601/ 即可看到欢迎页,点击下面的 Add integrations。
6eab1f1b0f6740579311f5ab21c82ab0

进入后,点击左边的 Discover
bd4bc7cc14bb4d079c03ef69d614dbb0

进入后,创建索引,点击Create index pattern
b1ced520fdd24ae29c9b926d08045605

然后就可以看到右边有一个nginx 的 source
4807e5566adb4df0a9319c1b32fe3976

现在需要填写Name,和 Timestamp field 这两个选项,最后点击 Create index pattern。
4160e15be6d4467fa94738bd1ffd28db

创建完后,重新进入Discover 也就可以看到从 Logstash 保存的日志。
8d2137e471ab40ef93226452bb595abb