马哥 Linux SRE + AIOps智能运维文档
第 36 章 / 42

企业级日志分析系统 ELK

关于本文档 · 贡献者 · 文档协议 · 致谢

关于本文档

文档名称:《企业级日志分析系统 ELK》

使用协议:《知识共享公共许可协议(CCPL)》

贡献者

贡献者名称 贡献
度
文档变更记录 个人主页
马哥(马永亮) 主编 http://github.com/iKubernet
es/
王晓春 作者 278页,版本迭代升级,修订和内容丰富 http://www.wangxiaochun.c
om

文档协议

署名要求 :使用本系列文档,您必须保留本页中的文档来源信息,具体请参考《知识共享 (Creative Commons) 署名4.0公共许可协议国际版》。

非商业化使用 :遵循《知识共享公共许可协议(CCPL)》,并且您不能将本文档用于马哥教育相关业务之外的其他任何商业用途。

您的权利 :遵循本协议后,在马哥教育相关业务之外的领域,您将有以下使用权限:

共享 — 允许以非商业性质复制本作品。

改编 — 在原基础上修改、转换或以本作品为基础进行重新编辑并用于个人非商业使用。

致谢

本文档中部分素材参考了相关项目的文档,以及通过搜索引擎获得的内容,这里先一并向相关的贡献者表示感谢。

← 上一章:微服务和消列队列 | 返回总目录 | 下一章:DevOps 之 GitLab 的CI →


内容概述

  • ELK 概述

  • Elasticsearch 管理

  • Beats 实现日志收集

  • Logstash 实现日志过滤转换

  • Kibana 实现图形化展示

  • ELK 综合案例

1 ELK 概述

1.1 ELK 介绍

1.1.1 什么是 ELK

ELK是由一家elastic公司开发的三个开源项目的首字母缩写

这三个项目分别是:Elasticsearch、Logstash 和 Kibana。三个项目各有不同的功能

之后又增加了许多新项目, 于是从5.X版本后改名为Elastic Stack

Elastic Stack 是一套适用于数据采集、扩充、存储、分析和可视化的免费开源工具。人们通常将 Elastic Stack 称为 ELK Stack(代指 Elasticsearch、Logstash 和 Kibana),目前 Elastic Stack 包括一系列丰富的轻量型数据采集代理,这些代理统称为 Beats,可用来向 Elasticsearch 发送数据。

Elasticsearch 是一个实时的全文搜索,存储库和分析引擎。

Logstash 是服务器端数据处理的管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到诸如 Elasticsearch 等存储库中。

Kibana 则可以让用户在 Elasticsearch 中使用图形和图表对数据进行可视化。

ELK 版本演进: 0.X,1.X,2,X,5.X,6,X,7.X,8.X ....

官网: https://www.elastic.co/

ELK官方介绍:https://www.elastic.co/cn/what-is/elk-stack

ELK 下载链接:https://www.elastic.co/cn/downloads/

ELK 说明: https://www.elastic.co/guide/cn/index.html

ELK 权威指南: https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html

ELK stack的主要优点:

  • 功能强大:Elasticsearch是实时全文索引,具有强大的搜索功能

  • 配置相对简单:Elasticsearch 全部其于 JSON,Logstash使用模块化配置,Kibana的配置都比较简单。

  • 检索性能高效:基于优秀的设计,每次查询可以实时响应,即使百亿级数据的查询也能达到秒级响应。

  • 集群线性扩展:Elasticsearch 和 Logstash都可以灵活线性扩展前端操作方便:Kibana提供了比较美观UI前端,操作也比较简单

官方下载

https://www.elastic.co/cn/downloads/

EFK 由ElasticSearch、Fluentd和Kiabana三个开源工具组成。Fluentd是一个实时开源的数据收集器,和 logstash功能相似,这三款开源工具的组合为日志数据提供了分布式的实时搜集与分析的监控系统。

Fluentd官网和文档:

https://www.fluentd.org/
https://docs.fluentd.org/

1.1.2 Elasticsearch

1.1.2.1 Elasticsearch 介绍

官方介绍

https://www.elastic.co/cn/what-is/elasticsearch

Elasticsearch 是一个分布式的免费开源搜索和分析引擎,适用于包括文本、数字、地理空间、结构化和非结构化数据等在内的所有类型的数据。Elasticsearch 在 Apache Lucene 的基础上开发而成,由 Elasticsearch N.V.(即现在的 Elastic)于 2010 年首次发布。Elasticsearch 以其简单的 REST 风格 API、分布式特性、速度和可扩展性而闻名,是 Elastic Stack 的核心组件

Elasticsearch 支持数据的实时全文搜索搜索、支持分布式和高可用、提供API接口,可以处理大规模的各种日志数据的处理,比如: Nginx、Tomcat、系统日志等功能。

Elasticsearch 基于 Java 语言开发,利用全文搜索引擎 Apache Lucene 实现

为何使用 Elasticsearch?

  • Elasticsearch 很快。 由于 Elasticsearch 是在 Lucene 基础上构建而成的,所以在全文本搜索方面表现十分出色。Elasticsearch 同时还是一个近实时的搜索平台,这意味着从文档索引操作到文档变为可搜索状态之间的延时很短,一般只有一秒。因此,Elasticsearch 非常适用于对时间有严苛要求的用例,例如安全分析和基础设施监测。

  • Elasticsearch 具有分布式的本质特征。 Elasticsearch 中存储的文档分布在不同的容器中,这些容器称为 ,可以进行复制以提供数据冗余副本,以防发生硬件故障。Elasticsearch 的分布式特性使得它可以扩展至数百台(甚至数千台)服务器,并处理 PB 量级的数据。

  • Elasticsearch 包含一系列广泛的功能。 除了速度、可扩展性和弹性等优势以外,Elasticsearch 还有大量强大的内置功能(例如数据汇总和索引生命周期管理),可以方便用户更加高效地存储和搜索数据。

  • Elastic Stack 简化了数据采集、可视化和报告过程。 通过与 Beats 和 Logstash 进行集成,用户能够在向 Elasticsearch 中索引数据之前轻松地处理数据。同时,Kibana 不仅可针对 Elasticsearch

数据提供实时可视化,同时还提供 UI 以便用户快速访问应用程序性能监测 (APM)、日志和基础设施指标等数据。

Elasticsearch 在速度和可扩展性方面都表现出色,而且还能够索引多种类型的内容,可用于多种场景:

  • 应用程序搜索

  • 网站搜索

  • 企业搜索

  • 日志处理和分析

  • 基础设施指标和容器监测

  • 应用程序性能监测

  • 地理空间数据分析和可视化

  • 安全分析

  • 业务分析

1.1.2.2 原理

原始数据会从多个来源(包括日志、系统指标和网络应用程序)输入到 Elasticsearch 中。数据采集指在 Elasticsearch 中进行索引之前解析、标准化并充实这些原始数据的过程。这些数据在 Elasticsearch 中索引完成之后,用户便可针对他们的数据运行复杂的查询,并使用聚合来检索自身数据的复杂汇总。在 Kibana 中,用户可以基于自己的数据创建强大的可视化,分享仪表板,并对 Elastic Stack 进行管理。

Elasticsearch 索引指相互关联的文档集合。Elasticsearch 会以 JSON 文档的形式存储数据。每个文档都会在一组键(字段或属性的名称)和它们对应的值(字符串、数字、布尔值、日期、数组、地理位置或其他类型的数据)之间建立联系。

Elasticsearch 使用的是一种名为倒排索引的数据结构,这一结构的设计可以允许十分快速地进行全文本搜索。倒排索引会列出在所有文档中出现的每个特有词汇,并且可以找到包含每个词汇的全部文档。

在索引过程中,Elasticsearch 会存储文档并构建倒排索引,这样用户便可以近实时地对文档数据进行搜索。索引过程是在索引 API 中启动的,通过此 API 您既可向特定索引中添加 JSON 文档,也可更改特定索引中的 JSON 文档。

1.1.2.3 基本概念

Near Realtime(NRT) 几乎实时

Elasticsearch是一个几乎实时的搜索平台。意思是,从索引一个文档到这个文档可被搜索只需要一点点的延迟,这个时间一般为毫秒级。

Cluster 集群

群集是一个或多个节点(服务器)的集合, 这些节点共同保存整个数据,并在所有节点上提供联合索引和搜索功能。一个集群由一个唯一集群ID确定,并指定一个集群名(默认为“elasticsearch”)。该集群名非常重要,因为节点可以通过这个集群名加入群集,一个节点只能是群集的一部分。

确保在不同的环境中不要使用相同的群集名称,否则可能会导致连接错误的群集节点。

Node节点

节点是单个服务器实例,它是群集的一部分,可以存储数据,并参与群集的索引和搜索功能。就像一个集群,节点的名称默认为一个随机的通用唯一标识符(UUID),确定在启动时分配给该节点。如果不希望默认,可以定义任何节点名。这个名字对管理很重要,目的是要确定网络服务器对应于ElasticSearch 群集节点。

我们可以通过群集名配置节点以连接特定的群集。默认情况下,每个节点设置加入名为“elasticSearch” 的集群。这意味着如果启动多个节点在网络上,假设他们能发现彼此都会自动形成和加入一个名为 “elasticsearch”的集群。

在单个群集中,您可以拥有尽可能多的节点。此外,如果“elasticsearch”在同一个网络中,没有其他节点正在运行,从单个节点的默认情况下会形成一个新的单节点名为"elasticsearch"的集群。

Index 索引

索引是具有相似特性的文档集合。例如,可以为客户数据提供索引,为产品目录建立另一个索引,以及为订单数据建立另一个索引。索引由名称(必须全部为小写)标识,该名称用于在对其中的文档执行索引、搜索、更新和删除操作时引用索引。在单个群集中,您可以定义尽可能多的索引。

注意: 索引名不支持大写字母

Type类型

在索引中,可以定义一个或多个类型。类型是索引的逻辑类别/分区,其语义完全取决于您。一般来说, 类型定义为具有公共字段集的文档。例如,假设你运行一个博客平台,并将所有数据存储在一个索引中。在这个索引中,您可以为用户数据定义一种类型,为博客数据定义另一种类型,以及为注释数据定义另一类型。

Document 文档

文档是可以被索引的信息的基本单位。例如,您可以为单个客户提供一个文档,单个产品提供另一个文档,以及单个订单提供另一个文档。本文件的表示形式为JSON(JavaScript Object Notation)格式,这是一种非常普遍的互联网数据交换格式。

在索引/类型中,您可以存储尽可能多的文档。请注意,尽管文档物理驻留在索引中,文档实际上必须索引或分配到索引中的类型。

Shards & Replicas 分片与副本

索引可以存储大量的数据,这些数据可能超过单个节点的硬件限制。例如,十亿个文件占用磁盘空间 1TB的单指标可能不适合对单个节点的磁盘, 或者仅从单个节点的搜索请求服务可能太慢

为了解决这一问题,Elasticsearch提供细分指标分成多个块称为分片的能力。当创建一个索引,可以简单地定义想要的分片数量。每个分片本身是一个全功能的、独立的“指数”,可以托管在集群中的任何节点。

Shards分片的重要性主要体现在以下两个特征:

分片允许您水平拆分或缩放内容的大小

分片允许你分配和并行操作的碎片(可能在多个节点上)从而提高性能/吞吐量

这个机制中的碎片是分布式的以及其文件汇总到搜索请求是完全由ElasticSearch管理,对用户来说是透明的。

在同一个集群网络或云环境上,故障是任何时候都会出现的,拥有一个故障转移机制以防分片和结点因为某些原因离线或消失是非常有用的,并且被强烈推荐。为此,Elasticsearch允许你创建一个或多个拷贝,索引分片进入所谓的副本或称作复制品的分片,简称Replicas。

Replicas的重要性主要体现在以下两个特征:

  • 副本为分片或节点失败提供了高可用性。为此,需要注意的是,一个副本的分片不会分配在同一个节点作为原始的或主分片,副本是从主分片那里复制过来的。

  • 副本允许用户扩展你的搜索量或吞吐量,因为搜索可以在所有副本上并行执行。

相关概念在关系型数据库和ElasticSearch中的对应关系

关系型数据库 Elasticsearch
数据库Database 索引Index,支持全文检索
表Table 类型Type
数据行Row 文档Document,但不需要固定结构,不同文档可以具有不同字段集合
数据列Column 字段Field

详细说明:

概念 说明
索引库
(indices)
indices是index的复数,代表许多的索引,
类型(type) 类型是模拟mysql中的table概念,一个索引库下可以有不同类型的索引,比如商品索引,订单索引,其数据格式不同。不过这会导致索引库混乱,因此未来版本中会移除这个概念
文档
(document)
存入索引库原始的数据。比如每一条商品信息,就是一个文档
字段(field) 文档中的属性

1.1.3 Logstash

https://www.elastic.co/cn/what-is/elasticsearch

Logstash 是 Elastic Stack 的核心产品之一,可用来对数据进行聚合和处理,并将数据发送到 Elasticsearch。Logstash 是一个基于Java实现的开源的服务器端数据处理管道,允许您在将数据索引到 Elasticsearch 之前同时从多个来源采集数据,并对数据进行过滤和转换。

可以通过插件实现日志收集和转发,支持日志过滤,支持普通log、自定义json格式的日志解析。

1.1.4 Kibana

Kibana 是一款适用于 Elasticsearch 的基于Javascript语言实现的数据可视化和管理工具,可以提供实时的直方图、线形图、饼状图和地图。Kibana 同时还包括诸如 Canvas 和 Elastic Maps 等高级应用程序; Canvas 允许用户基于自身数据创建定制的动态信息图表,而 Elastic Maps 则可用来对地理空间数据进行可视化。

官方文档

https://www.elastic.co/cn/what-is/kibana

主要是通过接口调用elasticsearch的数据,并进行前端数据可视化的展现。

Kibana 与 Elasticsearch 和更广意义上的 Elastic Stack 紧密的集成在一起,这一点使其成为支持以下场景的理想选择:

搜索、查看并可视化 Elasticsearch 中所索引的数据,并通过创建柱状图、饼图、表格、直方图和地图对数据进行分析。仪表板视图能将这些可视化元素组织到一起,然后通过浏览器进行分享,以提供对海量数据的实时分析视图,所支持的用例如下:

1. 日志处理和分析

2. 基础设施指标和容器监测

3. 应用程序性能监测 (APM)

4. 地理空间数据分析和可视化

5. 安全分析

6. 业务分析

借助网络界面来监测和管理 Elastic Stack 实例并确保实例的安全

针对基于 Elastic Stack 开发的内置解决方案(面向可观测性、安全和企业搜索应用程序),将其访问权限集中到一起

1.2 ELK 应用场景

运维主要应用场景:

  • 将分布在不同主机的日志统一收集,并进行转换,通过集中的Web UI 进行查询和管理通过查看汇总的日志,找到故障的根本原因

  • Web 展示和报表功能

  • 实现安全和事件等管理

大数据运维主要应用场景:

  • 查询聚合, 大屏分析

  • 预测告警, 网络指标,业务指标安全指标

  • 日志查询,问题排查,基于API可以实现故障恢复和自愈

  • 用户行为,性能,业务分析

1.3 ELK 应用架构

  • 2 Elasticsearch 部署和管理

Elasticsearch 是一个分布式的免费开源搜索和分析引擎,适用于包括文本、数字、地理空间、结构化和非结构化数据等在内的所有类型的数据

Elasticsearch 基于 Java 语言实现

2.1 Elasticsearch 安装说明

官方文档

https://www.elastic.co/guide/en/elastic-stack/index.html
https://www.elastic.co/guide/en/elasticsearch/reference/master/install-
elasticsearch.html

部署方式

包安装

二进制安装

Docker 部署

Ansible 批量部署

ES支持操作系统版本和 Java 版本官方说明

https://www.elastic.co/cn/support/matrix

2.2 安装前准备

2.2.1 安装前环境初始化

CPU2C内存4G或更多
操作系统: Ubuntu20.04,Ubuntu18.04,Rocky8.X,Centos 7.X
操作系统盘50G
主机名设置规则为nodeX.wang.org
生产环境建议准备单独的数据磁盘

2.2.1.1 主机名

#各服务器配置自己的主机名
[root@ubuntu1804 ~]# hostnamectl set-hostname es-node1.wang.org
2.2.1.2 关闭防火墙和SELinux

关闭防所有服务器的防火墙和 SELinux

#RHEL系列的系统执行下以下配置
[root@es-node1 ~]# systemctl disable firewalld
[root@es-node1 ~]# systemctl  disable NetworkManager
[root@es-node1 ~]# sed -i '/SELINUX/s/enforcing/disabled/' /etc/selinux/config
[root@es-node1 ~]# reboot
2.2.1.3 各服务器配置本地域名解析
[root@es-node1 ~]# vim /etc/hosts
10.0.0.101 es-node1.wang.org
10.0.0.102 es-node2.wang.org
10.0.0.103 es-node3.wang.org
2.2.1.5 优化资源限制配置
2.2.1.5.1 修改内核参数

内核参数 vm.max_map_count 用于限制一个进程可以拥有的VMA(虚拟内存区域)的数量

使用默认系统配置,二进制安装时会提示下面错误,包安装会自动修改此配置

#查看默认值
[root@es-node1 ~]#sysctl  -a |grep vm.max_map_count
vm.max_map_count =65530
#修改配置
[root@es-node1 ~]#echo "vm.max_map_count = 262144" >> /etc/sysctl.conf
[root@es-node1 ~]#echo "fs.file-max = 1000000" >> /etc/sysctl.conf
[root@es-node1 ~]#sysctl  -p
vm.max_map_count =262144

范例: Ubuntu 基于包安装后会自动修改文件

[root@node1 ~]#cat /usr/lib/sysctl.d/elasticsearch.conf
vm.max_map_count=262144
2.2.1.5.2 修改资源限制配置
[root@es-node1 ~]#vi /etc/security/limits.conf
*                soft    core            unlimited
*                hard    core            unlimited
*                soft    nproc           1000000
*                hard    nproc           1000000
*                soft    nofile          1000000
*                hard    nofile          1000000
*                soft    memlock         32000
*                hard    memlock         32000
*                soft    msgqueue        8192000
*                hard    msgqueue        8192000

2.2.2 安装 Java 环境 (可选)

Elasticsearch 是基于java的应用,所以依赖JDK环境

注意: 安装7.X以后版本官方建议要安装集成JDK的包,所以无需再专门安装 JDK

关于JDK环境说明

1.x 2.x 5.x 6.x都没有集成JDK的安装包,也就是需要自己安装java环境
7.x的安装包分为带JDK和不带JDK两种包,带JDK的包在安装时不需要再安装java,如果不带JDK的包仍然需
要自己去安装java

如果安装no-jdk的包,才需要安装java环境

官网JAVA版支持说明

https://www.elastic.co/cn/support/matrix#matrix_jvm

因为 Elasticsearch 服务运行需要 Java环境,如果要安装没有JDK的包,需要提前安装JAVA环境,可以使用以下方式安装

如果没有java 环间,安装elasticsearch时会出下面错误提示

[root@node1 ~]#dpkg -i elasticsearch-7.14.0-no-jdk-amd64.deb
Selecting previously unselected package elasticsearch.
(Reading database ... 71513 files and directories currently installed.)
Preparing to unpack elasticsearch-7.14.0-no-jdk-amd64.deb ...
Creating elasticsearch group... OK
Creating elasticsearch user... OK
Unpacking elasticsearch (7.14.0) ...
Setting up elasticsearch (7.14.0) ...
### NOT starting on installation, please execute the following statements to
configure elasticsearch service to start automatically using systemd
sudo systemctl daemon-reload
sudo systemctl enable elasticsearch.service
### You can start elasticsearch service by executing
sudo systemctl start elasticsearch.service
could not find java in bundled JDK at /usr/share/elasticsearch/jdk/bin/java
dpkg: error processing package elasticsearch (--install):
 installed elasticsearch package post-installation script subprocess returned
error exit status 1
Processing triggers for ureadahead (0.100.0-21) ...
Processing triggers for systemd (237-3ubuntu10.42) ...
Errors were encountered while processing:
 elasticsearch

方式一:直接使用yum/apt安装openjdk

[root@es-node1 ~]#yum -y install java-1.8.0-openjdk
[root@es-node1 ~]#apt update;apt -y install openjdk-8-jdk

方式二:本地安装在oracle官网下载rpm安装包:

[root@es-node1 ~]# yum -y install jdk-8u92-linux-x64.rpm

方式三:安装二进制包并自定义环境变量

下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151. html

[root@es-node1 ~]# tar xvf jdk-8u121-linux-x64.tar.gz -C /usr/local/
[root@es-node1 ~]# ln -sv /usr/local/jdk1.8.0_121 /usr/local/jdk
[root@es-node1 ~]# ln -sv /usr/local/jdk/bin/java /usr/bin/
[root@es-node1 ~]# vim /etc/profile
exportHISTTIMEFORMAT="%F %T `whoami` "
exportJAVA_HOME=/usr/local/jdk
export
CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools
.jar
exportPATH=$PATH:$JAVA_HOME/bin
[root@es-node1 ~]# source /etc/profile
[root@es-node1 ~]# java -version
java version "1.8.0_121"#确认可以出现当前的java版本号
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

2.3 Elasticsearch 安装

有两种包: 包含jdk和no-jdk的包

注意: 官方提示no-jdk的包将被淘汰,建议使用包含JDK的包

下载地址:

#包含JDK的版本下载
https://www.elastic.co/downloads/elasticsearch
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/
#不包含JDK的版本下载
https://www.elastic.co/cn/downloads/elasticsearch-no-jdk

范例: 查看两种包

[root@node1 ~]#ll -h elasticsearch-7.14.0-*
-rw-r--r--1 root root 329M Aug 1519:39 elasticsearch-7.14.0-amd64.deb
-rw-r--r--1 root root 183M Aug 1519:38 elasticsearch-7.14.0-no-jdk-amd64.deb

2.3.1 包安装 Elasticsearch

2.3.1.1 安装 Elasticsearch 包

下载链接

https://mirrors.tuna.tsinghua.edu.cn/elasticstack/

CentOS 7 安装 Elasticsearch

[root@centos7 ~]#yum -y install elasticsearch-7.6.2-x86_64.rpm

Ubuntu18.04 安装 Elasticsearch

[root@ubuntu1804 ~]#dpkg -i elasticsearch-7.6.2-amd64.deb

范例: Ubuntu 安装包含JDK的elasticsearch 包

[root@node1 ~]#dpkg -i elasticsearch-7.14.0-amd64.deb
[root@node1 ~]#systemctl daemon-reload
[root@node1 ~]#systemctl enable --now elasticsearch.service
[root@node1 ~]#pstree -p |grep java
           |-java(1341)-+-controller(1538)-+-{controller}(1540)
           |            |-{java}(1519)
           |            |-{java}(1520)
           |            |-{java}(1521)
           |            |-{java}(1522)
[root@node1 ~]#ss -ntl
State  Recv-Q  Send-Q       Local Address:Port   Peer Address:Port
LISTEN 0128127.0.0.53%lo:53          0.0.0.0:*
LISTEN 01280.0.0.0:22          0.0.0.0:*
LISTEN 0128127.0.0.1:6010        0.0.0.0:*
LISTEN 0128127.0.0.1:6011        0.0.0.0:*
LISTEN 0128     [::ffff:127.0.0.1]:9200              *:*
LISTEN 0128                  [::1]:9200           [::]:*
LISTEN 0128     [::ffff:127.0.0.1]:9300              *:*
LISTEN 0128                  [::1]:9300           [::]:*
LISTEN 0128                   [::]:22             [::]:*
LISTEN 0128                  [::1]:6010           [::]:*
LISTEN 0128                  [::1]:6011           [::]:*
[root@node1 ~]#ss -ntlp|grep java
LISTEN  0128  [::ffff:127.0.0.1]:9200     *:*       users:
(("java",pid=1341,fd=287))
LISTEN  0128               [::1]:9200  [::]:*       users:
(("java",pid=1341,fd=286))
LISTEN  0128  [::ffff:127.0.0.1]:9300     *:*       users:
(("java",pid=1341,fd=284))
LISTEN  0128               [::1]:9300  [::]:*       users:
(("java",pid=1341,fd=283))
[root@node1 ~]#curl 127.0.0.1:9200
{
"name" : "node1.wang.org",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "vvp4iBkkTfOJPf_rtcE0Og",
"version" : {
"number" : "7.14.0",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "dd5a0a2acaa2045ff9624f3729fc8a6f40835aa1",
"build_date" : "2021-07-29T20:49:32.864135063Z",
"build_snapshot" : false,
"lucene_version" : "8.9.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
  },
"tagline" : "You Know, for Search"
}
[root@node1 ~]#curl 127.0.0.1:9300
This is not an HTTP port

范例: Ubuntu 安装不包含 JDK 的elasticsearch 包

[root@ubuntu1804 ~]#apt update
[root@ubuntu1804 ~]#apt -y install openjdk-8-jdk
#默认无法找到Java,安装失败
[root@ubuntu1804 ~]#dpkg -i elasticsearch-7.14.0-no-jdk-amd64.deb
update-alternatives: using /usr/lib/jvm/java-8-openjdk-amd64/bin/appletviewer to
provide /usr/bin/appletviewer (appletviewer) in auto mode
update-alternatives: using /usr/lib/jvm/java-8-openjdk-amd64/bin/jconsole to
provide /usr/bin/jconsole (jconsole) in auto mode
Processing triggers for libgdk-pixbuf2.0-0:amd64 (2.36.11-2) ...
Processing triggers for libc-bin (2.27-3ubuntu1.2) ...
Errors were encountered while processing:
 elasticsearch
E: Sub-process /usr/bin/dpkg returned an error code (1)
(Reading database ... 88094 files and directories currently installed.)
Preparing to unpack elasticsearch-7.14.0-no-jdk-amd64.deb ...
Unpacking elasticsearch (7.14.0) over (7.14.0) ...
Setting up elasticsearch (7.14.0) ...
### NOT starting on installation, please execute the following statements to
configure elasticsearch service to start automatically using systemd
sudo systemctl daemon-reload
sudo systemctl enable elasticsearch.service
### You can start elasticsearch service by executing
sudo systemctl start elasticsearch.service
could not find java in bundled JDK at /usr/share/elasticsearch/jdk/bin/java
dpkg: error processing package elasticsearch (--install):
 installed elasticsearch package post-installation script subprocess returned
error exit status 1
Processing triggers for ureadahead (0.100.0-21) ...
Processing triggers for systemd (237-3ubuntu10.42) ...
Errors were encountered while processing:
 elasticsearch
[root@ubuntu1804 ~]#java -version
openjdk version "1.8.0_292"
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~18.04-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)
[root@ubuntu1804 ~]#which java
/usr/bin/java
#配置JAVA环境
[root@ubuntu1804 ~]#mkdir /usr/share/elasticsearch/jdk/bin/ -p
[root@ubuntu1804 ~]#ln -s /usr/bin/java /usr/share/elasticsearch/jdk/bin/java
#提示非no-jdk的发行版将被淘汰,建议使用包含JDK的包
[root@ubuntu1804 ~]#dpkg -i elasticsearch-7.14.0-no-jdk-amd64.deb
(Reading database ... 88094 files and directories currently installed.)
Preparing to unpack elasticsearch-7.14.0-no-jdk-amd64.deb ...
Unpacking elasticsearch (7.14.0) over (7.14.0) ...
Setting up elasticsearch (7.14.0) ...
### NOT starting on installation, please execute the following statements to
configure elasticsearch service to start automatically using systemd
sudo systemctl daemon-reload
sudo systemctl enable elasticsearch.service
### You can start elasticsearch service by executing
sudo systemctl start elasticsearch.service
Future versions of Elasticsearch will require Java 11; your Java version from
[/usr/lib/jvm/java-8-openjdk-amd64/jre] does not meet this requirement. Consider
switching to a distribution of Elasticsearch with a bundled JDK. If you are
already using a distribution with a bundled JDK, ensure the JAVA_HOME environment
variable is not set.
warning: no-jdk distributions that do not bundle a JDK are deprecated and will
be removed in a future release
Created elasticsearch keystore in /etc/elasticsearch/elasticsearch.keystore
Processing triggers for ureadahead (0.100.0-21) ...
Processing triggers for systemd (237-3ubuntu10.42) ...
[root@ubuntu1804 ~]#systemctl daemon-reload
[root@ubuntu1804 ~]#systemctl enable --now elasticsearch.service
Synchronizing state of elasticsearch.service with SysV service script with
/lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable elasticsearch
Created symlink /etc/systemd/system/multi-user.target.wants/elasticsearch.service
→ /usr/lib/systemd/system/elasticsearch.service.
[root@ubuntu1804 ~]#curl 127.0.0.1:9200
{
"name" : "node2.wang.org",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "hNlDtBjMTyerjIBt2dNjKg",
"version" : {
"number" : "7.14.0",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "dd5a0a2acaa2045ff9624f3729fc8a6f40835aa1",
"build_date" : "2021-07-29T20:49:32.864135063Z",
"build_snapshot" : false,
"lucene_version" : "8.9.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
  },
"tagline" : "You Know, for Search"
}
2.3.1.2 编辑服务配置文件

参考文档:

https://www.ibm.com/support/knowledgecenter/zh/SSFPJS_8.5.6/com.ibm.wbpm.main.do
c/topics/rfps_esearch_configoptions.html
https://www.elastic.co/guide/en/elasticsearch/reference/index.html
https://www.elastic.co/guide/en/elasticsearch/reference/master/settings.html
https://www.elastic.co/guide/en/elasticsearch/reference/master/important-
settings.html

配置文件说明

[root@es-node1 ~]# grep "^[a-Z]"  /etc/elasticsearch/elasticsearch.yml
#ELK集群名称,同一个集群内每个节点的此项必须相同,新加集群的节点此项和其它节点相同即可加入集群,而
无需再验证
cluster.name: ELK-Cluster
#当前节点在集群内的节点名称,同一集群中每个节点要确保此名称唯一
node.name: es-node1
#ES 数据保存目录
path.data: /data/es-data
#ES 日志保存目录
path.logs: /data/es-logs
#服务启动的时候立即分配(锁定)足够的内存,防止数据写入swap,提高启动速度
bootstrap.memory_lock: true
#指定监听IP,如果绑定了错误的IP,可将此修改为指定IP
network.host: 0.0.0.0
#监听端口
http.port: 9200
#发现集群的node节点列表,可以添加部分或全部节点IP
#在新增节点到集群时,此处需指定至少一个已经在集群中的节点地址
discovery.seed_hosts: ["10.0.0.101","10.0.0.102","10.0.0.103"]
#集群初始化时指定希望哪些节点可以被选举为 master,只在初始化时使用,新加节点到已有集群时此项可不
配置
cluster.initial_master_nodes: ["10.0.0.101","10.0.0.102","10.0.0.103"]
#一个集群中的 N 个节点启动后,才允许进行数据恢复处理,默认是1,一般设为为所有节点的一半以上,防止
出现脑裂现象
#当集群无法启动时,可以将之修改为1,或者将下面行注释掉,实现快速恢复启动
gateway.recover_after_nodes: 2
#设置是否可以通过正则表达式或者_all匹配索引库进行删除或者关闭索引库,默认true表示必须需要明确指
定索引库名称,不能使用正则表达式和_all,生产环境建议设置为 true,防止误删索引库。
action.destructive_requires_name: true
#不参与主节点选举
node.master: false
#存储数据,此值为false则不存储数据而成为一个路由节点
#如果将true改为false,需要先执行/usr/share/elasticsearch/bin/elasticsearch-node
repurpose 清理数据
node.data: true
#7.x以后版本下面指令已废弃,在2.x 5.x 6.x 版本中用于配置节点发现列表
discovery.zen.ping.unicast.hosts: ["10.0.0.101", "10.0.0.102","10.0.0.103"]

范例: 单节点配置

[root@ubuntu2004 ~]#grep -v '#'  /etc/elasticsearch/elasticsearch.yml
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
node.name: node-1
network.host: 0.0.0.0
discovery.seed_hosts: ["10.0.0.100"]
cluster.initial_master_nodes: ["node-1"]

范例: 集群配置

[root@es-node1 ~]#grep -Ev '^$|#' /etc/elasticsearch/elasticsearch.yml
cluster.name: es-cluster
node.name: es-node1
path.data: /data/es-data
path.logs: /data/es-logs
bootstrap.memory_lock: true
network.host: 0.0.0.0
discovery.seed_hosts: ["10.0.0.101","10.0.0.102","10.0.0.103"]
cluster.initial_master_nodes: ["10.0.0.101","10.0.0.102","10.0.0.103"]
gateway.recover_after_nodes: 2
action.destructive_requires_name: true
[root@es-node1 ~]#scp /etc/elasticsearch/elasticsearch.yml es-
node2:/etc/elasticsearch/
[root@es-node1 ~]#scp /etc/elasticsearch/elasticsearch.yml es-
node3:/etc/elasticsearch/
[root@es-node2 ~]#grep -v "#" /etc/elasticsearch/elasticsearch.yml
cluster.name: es-cluster
node.name: es-node2          #只需要修改此行,每个节点都不能相同
path.data: /data/es-data
path.logs: /data/es-logs
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["10.0.0.101", "10.0.0.102","10.0.0.103"]
cluster.initial_master_nodes: ["10.0.0.101", "10.0.0.102","10.0.0.103"]
gateway.recover_after_nodes: 2
[root@es-node3 ~]#grep -v "#" /etc/elasticsearch/elasticsearch.yml
cluster.name: es-cluster     #与es-node1相同
node.name: es-node3          #修改此行,与es-node2不能相同
path.data: /data/es-data
path.logs: /data/es-logs
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["10.0.0.101", "10.0.0.102","10.0.0.103"]
cluster.initial_master_nodes: ["10.0.0.101", "10.0.0.102","10.0.0.103"]
gateway.recover_after_nodes: 2

开启 b ot srap. m e o

导致无法启动的错误解决方法

官方文档:

https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-
configuration-memory.html#bootstrap-memory_lock
https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-system-
settings.html#systemd

[root@node1 ~]#vim /etc/elasticsearch/elasticsearch.yml
#开启此功能导致无法启动
bootstrap.memory_lock: true
[root@node1 ~]#systemctl restart elasticsearch.service
Job for elasticsearch.service failed because the control process exited with
error code.
See "systemctl status elasticsearch.service" and "journalctl -xe"for details.
[root@node1 ~]#tail /data/es-logs/es-cluster.log
[2021-08-15T22:21:13,600][INFO ][o.e.t.TransportService   ] [node-1]
publish_address {10.0.0.101:9300}, bound_addresses {[::]:9300}
[2021-08-15T22:21:13,911][INFO ][o.e.b.BootstrapChecks    ] [node-1] bound or
publishing to a non-loopback address, enforcing bootstrap checks
[2021-08-15T22:21:13,934][ERROR][o.e.b.Bootstrap          ] [node-1] node
validation exception
[1] bootstrap checks failed. You must address the points described in the
following [1] lines before starting Elasticsearch.
bootstrap check failure [1] of [1]: memory locking requested for elasticsearch
process but memory is not locked
[2021-08-15T22:21:13,941][INFO ][o.e.n.Node               ] [node-1] stopping
...
[2021-08-15T22:21:13,955][INFO ][o.e.n.Node               ] [node-1] stopped
[2021-08-15T22:21:13,955][INFO ][o.e.n.Node               ] [node-1] closing ...
[2021-08-15T22:21:13,970][INFO ][o.e.n.Node               ] [node-1] closed
[2021-08-15T22:21:13,971][INFO ][o.e.x.m.p.NativeController] [node-1] Native
controller process has stopped - no new native processes can be started
[root@node1 ~]#systemctl edit elasticsearch
[Service]
LimitMEMLOCK=infinity
[root@node1 ~]#cat /etc/systemd/system/elasticsearch.service.d/override.conf
[Service]
LimitMEMLOCK=infinity
[root@node1 ~]#systemctl daemon-reload
[root@node1 ~]#systemctl restart elasticsearch.service
[root@node1 ~]#systemctl is-active elasticsearch.service
active
2.3.1.3 优化 ELK 资源配置

官方文档:

https://www.elastic.co/guide/en/elasticsearch/reference/current/important-
settings.html#heap-size-settings

推荐使用宿主机物理内存的一半,ES的heap内存最大不超过30G,26G是比较安全的

官方文档:

https://www.elastic.co/guide/en/elasticsearch/reference/master/advanced-
configuration.html#set-jvm-heap-size
The heap size should be based on the available RAM:
Set Xms and Xmx to no more than 50% of your total memory. Elasticsearch requires
memory for purposes other than the JVM heap. For example, Elasticsearch uses off-
heap buffers for efficient network communication and relies on the operating
system’s filesystem cache for efficient access to files. The JVM itself also
requires some memory. It’s normal for Elasticsearch to use more memory than the
limit configured with the Xmx setting.
When running in a container, such as Docker, total memory is defined as the
amount of memory visible to the container, not the total system memory on the
host.
Set Xms and Xmx to no more than the threshold for compressed ordinary object
pointers (oops). The exact threshold varies but 26GB is safe on most systems and
can be as large as 30GB on some systems. To verify you are under the threshold,
check the Elasticsearch log for an entry like this:

堆大小应基于可用 RAM :

将 Xms 和 Xmx 设置为不超过总内存的 50%。 Elasticsearch 需要内存用于 JVM 堆以外的用途。例
如,Elasticsearch 使用堆外缓冲区来实现高效的网络通信,并依靠操作系统的文件系统缓存来高效地访问
文件。 JVM 本身也需要一些内存。 Elasticsearch 使用比 Xmx 设置配置的限制更多的内存是正常的。
在容器(例如 Docker)中运行时,总内存定义为容器可见的内存量,而不是主机上的总系统内存。
将 Xms 和 Xmx 设置为不超过压缩普通对象指针 (oops) 的阈值。确切的阈值会有所不同,但在大多数系
统上 26GB 是安全的,在某些系统上可能高达 30GB。要验证您是否低于阈值,请检查 Elasticsearch
日志中的条目,如下所示:

关于OOPS的说明

Managed pointers in the Java heap point to objects which are aligned on 8-byte
address boundaries. Compressed oops represent managed pointers (in many but not
all places in the JVM software) as 32-bit object offsets from the 64-bit Java
heap base address.
Because they're object offsets rather than byte offsets, they can be used to
address up to four billion objects (not bytes), or a heap size of up to about 32
gigabytes.
To use them, they must be scaled by a factor of 8 and added to the Java heap base
address to find the object to which they refer. Object sizes using compressed
oops are comparable to those in ILP32 mode.
Java 堆中的托管指针指向在 8 字节地址边界上对齐的对象。压缩 oop 将托管指针(在 JVM 软件中的许
多但不是所有地方)表示为相对于 64 位 Java 堆基地址的 32 位对象偏移量。
因为它们是对象偏移量而不是字节偏移量,所以它们可用于处理多达 40 亿个对象(不是字节),或高达约
32 GB 的堆大小。
要使用它们,必须将它们缩放 8 倍并添加到 Java 堆基地址以找到它们所引用的对象。使用压缩 oop 的
对象大小与 ILP32 模式中的对象大小相当。

内存优化建议:

为了保证性能,每个ES节点的JVM内存设置具体要根据 node 要存储的数据量来估算,建议符合下面约定

  • 在内存和数据量有一个建议的比例:对于一般日志类文件,1G 内存能存储48G~96GB数据 JVM 堆内存最大不要超过30GB

对于主分片的数量,单个分片控制在30-50GB

范例:

假设总数据量为1TB,3个node节点,1个副本;那么实际要存储的大小为2TB
每个节点需要存储的数据量为:2TB / 3 = 700GB,然后每个节点需要预留20%的空间,意味着每个node要
存储大约 875GB 的数据;按照内存与存储数据的比率计算:875GB/48GB=18,即需要JVM内存为18GB,小
于30GB
因为要尽量控制主分片的大小为30GB;875GB/30GB=30个主分片,即最多30个主分片

范例:指定heap内存最小和最大内存限制

#建议将heap内存设置为物理内存的一半且最小和最大设置一样大,但最大不能超过30G
[root@es-node1 ~]# vim /etc/elasticsearch/jvm.options
-Xms2g
-Xmx2g
#每天1TB左右的数据量的建议服务器配置
16C 64G 6T硬盘共3台服务器

范例: 修改service文件,做优化配置

[root@es-node1 ~]# vim /usr/lib/systemd/system/elasticsearch.service #修改内存限制
LimitNOFILE=1000000#修改最大打开的文件数,默认值为65535
LimitNPROC=65535#修改打开最大的进程数,默认值为4096
LimitMEMLOCK=infinity #无限制使用内存,以前旧版需要修改,否则无法启动服务,当前版本无需修改

内存锁定的配置参数:

https://discuss.elastic.co/t/memory-lock-not-working/70576
2.3.1.4 目录权限更改

在各个ES服务器创建数据和日志目录并修改目录权限为elasticsearch

#此步可选,可以不用创建下面目录es-data和es-logs,系统可以自动创建
[root@es-node1 ~]# mkdir -p /data/es-{data,logs}
[root@es-node1 ~]# ll /data/
total 0
drwxr-xr-x 2 root root 6 Apr 1818:44 es-data
drwxr-xr-x 2 root root 6 Apr 1818:44 es-logs
#必须分配权限,否则服务无法启动
[root@es-node1 ~]# chown  -R elasticsearch.elasticsearch /data/
[root@es-node1 ~]# ll /data/
total 0
drwxr-xr-x 2 elasticsearch elasticsearch 6 Apr 1818:44 es-data
drwxr-xr-x 2 elasticsearch elasticsearch 6 Apr 1818:44 es-logs
2.3.1.5 启动 Elasticsearch服务并验证
[root@ubuntu-node1 ~]#grep -Ev '^$|#'
/usr/lib/systemd/system/elasticsearch.service
[Unit]
Description=Elasticsearch
Documentation=https://www.elastic.co
Wants=network-online.target
After=network-online.target
[Service]
Type=notify
RuntimeDirectory=elasticsearch
PrivateTmp=true
Environment=ES_HOME=/usr/share/elasticsearch
Environment=ES_PATH_CONF=/etc/elasticsearch
Environment=PID_DIR=/var/run/elasticsearch
Environment=ES_SD_NOTIFY=true
EnvironmentFile=-/etc/default/elasticsearch
WorkingDirectory=/usr/share/elasticsearch
User=elasticsearch
Group=elasticsearch
ExecStart=/usr/share/elasticsearch/bin/systemd-entrypoint -p
${PID_DIR}/elasticsearch.pid --quiet
StandardOutput=journal
StandardError=inherit
LimitNOFILE=65535
LimitNPROC=4096
LimitAS=infinity
LimitFSIZE=infinity
TimeoutStopSec=0
KillSignal=SIGTERM
KillMode=process
SendSIGKILL=no
SuccessExitStatus=143
TimeoutStartSec=75
[Install]
WantedBy=multi-user.target
[root@es-node1 ~]#systemctl enable --now  elasticsearch
[root@es-node1 ~]#tail -f /data/es-logs/es-cluster.log
2.3.1.6 验证端口监听成功
#9200端口集群访问端口,9300集群同步端口
[root@es-node1 ~]#ss -ntlp|grep java
LISTEN   0128                       *:9200                   *:*
users:(("java",pid=2372,fd=225))
LISTEN   0128                       *:9300                   *:*
users:(("java",pid=2372,fd=211))
2.3.1.7 通过浏览器访问 Elasticsearch 服务端口
[root@es-node1 ~]#curl 127.0.0.1:9200
{
"name" : "es-node1",
"cluster_name" : "es-cluster",
"cluster_uuid" : "_na_",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
  },
"tagline" : "You Know, for Search"
}

2.3.2 二进制安装 Elasticsearch

官方文档

https://www.elastic.co/guide/en/elasticsearch/reference/master/targz.html
2.3.2.1 下载二进制文件

下载二进制文件

https://www.elastic.co/cn/downloads/elasticsearch

范例: 基于二进制包含JDK文件安装

[root@ubuntu1804 ~]#ls
elasticsearch-7.6.2-linux-x86_64.tar.gz
[root@ubuntu1804 ~]#tar xf elasticsearch-7.6.2-linux-x86_64.tar.gz  -C
/usr/local/
[root@ubuntu1804 ~]#ls /usr/local/
bin  elasticsearch-7.6.2  etc  games  include  lib  man  sbin  share  src
[root@ubuntu1804 ~]#ln -s /usr/local/elasticsearch-7.6.2/
/usr/local/elasticsearch
[root@ubuntu1804 ~]#ls /usr/local/elasticsearch
bin  config  jdk  lib  LICENSE.txt  logs  modules  NOTICE.txt  plugins
README.asciidoc
2.3.2.2 编辑服务配置文件
[root@es-node1 ~]#vim /usr/local/elasticsearch/config/elasticsearch.yml
[root@es-node1 ~]#grep -v "#" /usr/local/elasticsearch/config/elasticsearch.yml
cluster.name: es-cluster
node.name: es-node1             #在其它节点改为唯一的标识,如es-node2,es-node3
path.data: /data/es-data
path.logs: /data/es-logs
network.host: 10.0.0.101
http.port: 9200
discovery.seed_hosts: ["10.0.0.101", "10.0.0.102","10.0.0.103"]
cluster.initial_master_nodes: ["10.0.0.101", "10.0.0.102","10.0.0.103"]
gateway.recover_after_nodes: 2

# 复制配置文件到其它节点

[root@es-node1 ~]#scp /usr/local/elasticsearch/config/elasticsearch.yml  es-
node2:/usr/local/elasticsearch/config/
[root@es-node1 ~]#scp /usr/local/elasticsearch/config/elasticsearch.yml  es-
node3:/usr/local/elasticsearch/config/
[root@es-node2 ~]#vim /usr/local/elasticsearch/config/elasticsearch.yml
[root@es-node2 ~]#grep -v "#" /usr/local/elasticsearch/config/elasticsearch.yml
cluster.name: es-cluster
node.name: es-node2           #只修改此行即可
path.data: /data/es-data
path.logs: /data/es-logs
network.host: 10.0.0.102
http.port: 9200
discovery.seed_hosts: ["10.0.0.101", "10.0.0.102","10.0.0.103"]
cluster.initial_master_nodes: ["10.0.0.101", "10.0.0.102","10.0.0.103"]
gateway.recover_after_nodes: 2
[root@es-node3 ~]#vim /usr/local/elasticsearch/config/elasticsearch.yml
[root@es-node1 ~]#grep -v "#" /usr/local/elasticsearch/config/elasticsearch.yml
cluster.name: es-cluster
node.name: es-node3         #只修改此行即可
path.data: /data/es-data
path.logs: /data/es-logs
network.host: 10.0.0.103
http.port: 9200
discovery.seed_hosts: ["10.0.0.101", "10.0.0.102","10.0.0.103"]
cluster.initial_master_nodes: ["10.0.0.101", "10.0.0.102","10.0.0.103"]
gateway.recover_after_nodes: 2
2.3.2.3 修改 ELK 内存配置

修改ELK内存配置,推荐使用宿主机物理内存的一半,最大不超过30G

官方文档:

https://www.elastic.co/guide/en/elasticsearch/reference/current/important-
settings.html#heap-size-settings

范例:

[root@es-node1 ~]#vim /usr/local/elasticsearch/config/jvm.options
22-Xms2g
23-Xmx2g
2.3.2.4 创建用户

从ES7.X以后版不允许以root启动服务,需要委创建专用的用户

在所有节点上创建用户

[root@es-node1 ~]#useradd -r elasticsearch
2.3.2.5 目录权限更改

在所有节点上创建数据和日志目录并修改目录权限为elasticsearch

#可以不用创建下面目录es-data和es-logs,系统可以自动创建
[root@es-node1 ~]# mkdir /data/es-{data,logs}
[root@es-node1 ~]# ll /data/
total 0
drwxr-xr-x 2 root root 6 Apr 1818:44 es-data
drwxr-xr-x 2 root root 6 Apr 1818:44 es-logs
#必须分配权限,否则服务无法启动
[root@es-node1 ~]# chown  -R elasticsearch.elasticsearch /data/
[root@es-node1 ~]# ll /data/
total 0
drwxr-xr-x 2 elasticsearch elasticsearch 6 Apr 1818:44 es-data
drwxr-xr-x 2 elasticsearch elasticsearch 6 Apr 1818:44 es-logs
#修改elasticsearch安装目录权限
[root@es-node1 ~]#chown -R elasticsearch.elasticsearch /usr/local/elasticsearch/
2.3.2.6 启动 Elasticsearch服务

在所有节点上配置并启动

[root@es-node1 ~]#echo 'PATH=/usr/local/elasticsearch/bin:$PATH' >
/etc/profile.d/elasticsearch.sh
[root@es-node1 ~]#. /etc/profile.d/elasticsearch.sh
[root@es-node1 ~]#tail -f /data/es-logs/es-cluster.log
#不能以root用户运行,切换用户
[root@es-node1 ~]#su - elasticsearch
No directory, logging in with HOME=/
$ elasticsearch
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in
version 9.0 and will likely be removed in a future release.
[2021-01-21T13:26:40,017][INFO ][o.e.e.NodeEnvironment    ] [es-node1] using [1]
data paths, mounts [[/data (/dev/sda5)]], net usable_space [43.1gb], net
total_space [45.5gb], types [ext4]
[2021-01-21T13:26:40,031][INFO ][o.e.e.NodeEnvironment    ] [es-node1] heap size
[1007.3mb], compressed ordinary object pointers [true]
[2021-01-21T13:26:40,182][INFO ][o.e.n.Node               ] [es-node1] node name
[es-node1], node ID [m__LGOZgTCCK010g6_VcJQ], cluster name
2.3.2.7 验证端口监听成功

在所有节点上验证端口

[root@es-node1 ~]#ss -ntlp|grep java
LISTEN   0128                       *:9200                   *:*
users:(("java",pid=2372,fd=225))
LISTEN   0128                       *:9300                   *:*
users:(("java",pid=2372,fd=211))
2.3.2.8 通过浏览器访问 Elasticsearch 服务端口

在所有节点上验证访问9200/tcp端口

[root@es-node1 ~]#curl 10.0.0.101:9200
{
"name" : "es-node1",
"cluster_name" : "es-cluster",
"cluster_uuid" : "vzp2MIpeQSGtCPzd29C2PA",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
  },
"tagline" : "You Know, for Search"
}
[root@es-node1 ~]#curl -sXGET http://10.0.0.101:9200/_cluster/health?pretty=true
{
"cluster_name" : "es-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"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.0
}
2.3.2.9 创建 service 文件
[root@es-node1 ~]#cat /lib/systemd/system/elasticsearch.service
[Unit]
Description=Elasticsearch
Documentation=http://www.elastic.co
Wants=network-online.target
After=network-online.target
[Service]
RuntimeDirectory=elasticsearch
PrivateTmp=true
Environment=PID_DIR=/var/run/elasticsearch
WorkingDirectory=/usr/local/elasticsearch
User=elasticsearch
Group=elasticsearch
ExecStart=/usr/local/elasticsearch/bin/elasticsearch -p
${PID_DIR}/elasticsearch.pid --quiet
# StandardOutput is configured to redirect to journalctl since
# some error messages may be logged in standard output before
# elasticsearch logging system is initialized. Elasticsearch
# stores its logs in /var/log/elasticsearch and does not use
# journalctl by default. If you also want to enable journalctl
# logging, you can simply remove the "quiet" option from ExecStart.
# Specifies the maximum file descriptor number that can be opened by this
process
LimitNOFILE=65535
# Specifies the maximum number of processes
LimitNPROC=4096
# Specifies the maximum size of virtual memory
LimitAS=infinity
# Specifies the maximum file size
LimitFSIZE=infinity
# Disable timeout logic and wait until process is stopped
TimeoutStopSec=0
# SIGTERM signal is used to stop the Java process
KillSignal=SIGTERM
# Send the signal only to the JVM rather than its control group
KillMode=process
# Java process is never killed
SendSIGKILL=no
# When a JVM receives a SIGTERM signal it exits with code 143
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
# Built for packages-7.6.2 (packages)
[root@es-node1 ~]#systemctl daemon-reload
[root@es-node1 ~]#systemctl enable --now elasticsearch.service

2.3.3 基于 Docker 部署

官方文档

https://www.elastic.co/guide/en/elasticsearch/reference/7.5/docker.html
2.3.3.1 单节点部署
[root@ubuntu1804 ~]#docker run --name es-single-node -d -p 9200:9200 -p
9300:9300 -e "discovery.type=single-node"
docker.elastic.co/elasticsearch/elasticsearch:7.6.2
[root@ubuntu1804 ~]#curl 10.0.0.100:9200
{
"name" : "2d46279f23e3",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "NnmXvLMcS9-fxTsPe0bSMw",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
  },
"tagline" : "You Know, for Search"
}
2.3.3.2 多节点集群部署

2.3.3.2.1 部署前准备

注意:此方式需要3G以上内存,否则会出现OOM下面的信息

修改内核参数,默认无法启动,会出现下面错误提示

[root@ubuntu1804 ~]#echo vm.max_map_count=262144 >>  /etc/sysctl.conf
[root@ubuntu1804 ~]#sysctl -p

2.3.3.2.2 创建docker-compose.yml文件

[root@ubuntu1804 ~]#cat docker-compose.yml
version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.2
    container_name: es01
    environment:
-node.name=es01
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es02,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
-"ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
- data01:/usr/share/elasticsearch/data
    ports:
-9200:9200
    networks:
- elastic
  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.2
    container_name: es02
    environment:
-node.name=es02
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
-"ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
- data02:/usr/share/elasticsearch/data
    networks:
- elastic
  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.2
    container_name: es03
    environment:
-node.name=es03
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es02
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
-"ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
- data03:/usr/share/elasticsearch/data
    networks:
- elastic
volumes:
  data01:
    driver: local
  data02:
    driver: local
  data03:
    driver: local
networks:
  elastic:
    driver: bridge
2.3.3.2.3 启动集群
[root@ubuntu1804 ~]#docker-compose up -d
2.3.3.2.4 验证
[root@ubuntu1804 ~]#curl -sXGET http://10.0.0.100:9200
{
"name" : "es01",
"cluster_name" : "es-docker-cluster",
"cluster_uuid" : "Q0d0L9rCSuyuJyTEo8EE3w",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
  },
"tagline" : "You Know, for Search"
}
[root@ubuntu1804 ~]#curl -sXGET http://10.0.0.100:9200/_cluster/health?
pretty=true
{
"cluster_name" : "es-docker-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"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.0
}

2.4 Elasticsearch 集群状态监控

官方文档

https://www.elastic.co/guide/en/elasticsearch/reference/master/rest-apis.html

Elasticsearch 支持各种语言使用 RESTful API 通过端口 9200 与之进行通信,可以用你习惯的 web 客户端访问 Elasticsearch

可以用三种方式和 Elasticsearch进行交互

curl 命令和其它浏览器: 基于命令行,操作不方便

插件: 在node节点上安装head,Cerebro 等插件,实现图形操作,查看数据方便

Kibana: 需要java环境并配置,图形操作,显示格式丰富

监控下面两个条件都满足才是正常的状态

  • 集群状态为 green

  • 所有节点都启动

2.4.1 Shell 命令

# curl -sXGET http://elk服务器:9200/_cluster/health?pretty=true

获取到的是一个json格式的返回值,那就可以通过python对其中的信息进行分析,例如对status进行分析,如果等于green(绿色)就是运行在正常,等于yellow(黄色)表示副本分片丢失,red(红色)表示主分片丢失

ES集群状态:

  • 绿色状态:表示集群各节点运行正常,而且没有丢失任何数据,各主分片和副本分片都运行正常黄色状态:表示由于某个节点宕机或者其他情况引起的,node节点无法连接、所有主分片都正常分配,有副本分片丢失,但是还没有丢失任何数据

  • 红色状态:表示由于某个节点宕机或者其他情况引起的主分片丢失及数据丢失,但仍可读取数据和存储

#查看支持的指令
curl http://127.0.0.1:9200/_cat
#查看es集群状态
curl http://127.0.0.1:9200/_cat/health
curl'http://127.0.0.1:9200/_cat/health?v'
#查看所有的节点信息
curl'http://127.0.0.1:9200/_cat/nodes?v'
#列出所有的索引以及每个索引的相关信息
curl'http://127.0.0.1:9200/_cat/indices?v'
#查看集群分健康性
curl  http://127.0.0.1:9200/_cluster/health?pretty=true

范例

[root@node1 ~]#curl 127.0.0.1:9200/_cat
=^.^=
/_cat/allocation
/_cat/shards
/_cat/shards/{index}
/_cat/master
/_cat/nodes
/_cat/tasks
/_cat/indices
....
[root@node1 ~]#curl 'http://localhost:9200/_cat/nodes'
10.0.0.103 299300.16 0.07 0.05 cdfhilmrstw - node-3
10.0.0.102 168300.00 0.02 0.00 cdfhilmrstw * node-2
10.0.0.101 189200.10 0.11 0.05 cdfhilmrstw - node-1
[root@node1 ~]#curl 'http://localhost:9200/_cat/nodes?v'
ip         heap.percent ram.percent cpu load_1m load_5m load_15m node.role
master name
10.0.0.103           299300.19    0.07     0.05 cdfhilmrstw -
   node-3
10.0.0.102           168300.00    0.02     0.00 cdfhilmrstw *
   node-2
10.0.0.101           169200.12    0.12     0.05 cdfhilmrstw -
   node-1
[root@node1 ~]#curl 'http://localhost:9200/_cat/nodes?human'
10.0.0.103 299300.16 0.07 0.05 cdfhilmrstw - node-3
10.0.0.102 168300.00 0.02 0.00 cdfhilmrstw * node-2
10.0.0.101 179230.11 0.12 0.05 cdfhilmrstw - node-1

范例:

[root@es-node1 ~]#curl -sXGET http://10.0.0.101:9200/_cluster/health?pretty=true
{
"cluster_name" : "es-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"active_primary_shards" : 6,
"active_shards" : 12,
"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.0
}

范例:

#查看es集群状态
[root@es-node1 ~]#curl 'http://localhost:9200/_cat/health'
162911735912:35:59 es-cluster green 33630000-100.0%
[root@es-node1 ~]#curl '10.0.0.101:9200/_cat/health?v'
epoch      timestamp cluster    status node.total node.data shards pri relo init
unassign pending_tasks max_task_wait_time active_shards_percent
161287799713:39:57  es-cluster green           33804000
00-100.0%

# 查看所有的节点信息

[root@es-node1 ~]#curl '10.0.0.101:9200/_cat/nodes?v'
ip         heap.percent ram.percent cpu load_1m load_5m load_15m node.role
master name
10.0.0.101           204400.03    0.02     0.00 dilm      -
es-node1
10.0.0.102           279740.29    0.14     0.10 dilm      -
es-node2
10.0.0.103           209600.00    0.00     0.00 dilm      *
es-node3
#列出所有的索引以及每个索引的相关信息
[root@es-node1 ~]#curl '10.0.0.101:9200/_cat/indices?v'
health status index                                  uuid                   pri
rep docs.count docs.deleted store.size pri.store.size
green  open   nginx-accesslog-0.107-2021.02.04       fSg_AiIOSaeYPVrjCEABBg   1
15930367.8kb        204.1kb
green  open   nginx-accesslog-0.107-2021.02.03       Hxj6RKkhTIWrW-7b7WE-iw   1
113930562.7kb        281.3kb
green  open   nginx-accesslog-0.107-2021.02.02       8SSfUh5wT0WWcBxAa0UrCQ   1
111810572.8kb        286.4kb
green  open   logfile-2021.01.26                     cBxWy995SrS9LAET660t9w   1
111100496.2kb        248.1kb
green  open   redis-syslog-0.107-2021.02.09          aaw2g8MBSberZFZKCHMQyg   1
1631307.6mb          3.7mb
green  open   metricbeat-7.6.2-2021.02.07-000001     MSq7BXQ6TXWFfvKkSzFUlQ   1
1116861070.3mb         35.2mb
green  open   linux-syslog-tomcat-2021.01.31         6booHIoiThyoui00cmqzOA   1
1118290        5mb          2.5mb
green  open   linux-2021.01.31                       VGGXaz38R0meynC6ciUcOQ   1
138309011.8mb          5.9mb
green  open   linux-2021.02.02                       UkJA4drJRNG3AvNw5cB-dQ   1
1582403.7mb          1.8mb
green  open   .kibana_task_manager_1                 s1zixAaTTX6Zwe1pSFAujw   1
12147.7kb         26.8kb
green  open   linux-2021.02.01                       R1YNBVR8TjW1pYk85UNDBw   1
1336101.9mb        997.6kb
green  open   linux-2021.02.07                       iVWNy0iaT8qggnVVrNVJaA   1
1568803.7mb          1.8mb
green  open   linux-2021.02.04                       xchTONa5TuWtaiOxK3xQVg   1
1531803.4mb          1.7mb
green  open   heartbeat-7.6.2-2021.02.07-000001      NoX252O_RkefMbxAB0Xkqg   1
11487108.3mb          4.1mb
green  open   linux-2021.02.09                       r1asaolISzyDRJCfmrwanQ   1
134470        2mb            1mb
green  open   syslog-0.104-2021.02.09                z9bhHeATTnyc89juzyOz5A   1
1344702.1mb            1mb
green  open   filebeat-7.6.2-2021.02.07-000001       grcnt8nyRUa8tta8vbHA-A   1
11715605.8mb          2.9mb
green  open   .apm-agent-configuration               o8F-g6SXRSaMGYWXMF_gCg   1
100       566b           283b
green  open   syslog-redis-0.107-2021.02.09          J23OBOm_RR6fXN2Iask-fw   1
12080405.8kb        221.6kb
green  open   java-error-log-0.107-2021.05           3k-_LqHJSjugaou0R2UBpQ   1
13200353.6kb        170.6kb
green  open   redis-nginx-errorlog-0.107-2021.02.09  LiJqBQ4fTnG08wEV9bbvGQ   1
1110192.8kb        106.1kb
green  open   .kibana_1                              a3GysbtUS7WlEyeLKuVsvg   1
1359480.7kb        240.3kb
green  open   syslog-0.107-2021.02.04                kz7RCKXtTPa8EqjNATi0ng   1
1258601.5mb        769.1kb
green  open   syslog-0.107-2021.02.07                noUBswW2QFSLIt9B_0Eyzg   1
119130        1mb        537.1kb
green  open   redis-nginx-accesslog-0.107-2021.02.09 pG1f2h_NRUi7VdG9XeqCDg   1
1180283.4kb        154.4kb
green  open   wang-index2                          32A1_WR4QEKmTfKFe61JjA   1
100       566b           283b
green  open   ilm-history-1-000001                   tEhIudx1SUGEKjI5VUzcTw   1
1360100.7kb         50.3kb
green  open   wang-index1                          TPUrqHNdRT2lCNVPMPF2eg   5
1002.7kb          1.3kb
green  open   syslog-0.104-2021.02.01                PyL3mHqJRRuznGu5P-wNjQ   1
1336101.9mb       1017.5kb
green  open   nginx-errorlog-0.107-2021.02.04        -8h-9e1GSJyitqI9kIkQVg1
16019.9kb          9.9kb
green  open   syslog-haproxy-0.107-2021.02.04        XKsuoHPKQR27LdGttZRUiA   1
11320205.8kb        102.9kb
green  open   syslog-0.104-2021.02.02                M0p-uU4XTViN6TJDx10hkw   1
1582403.7mb          1.8mb
green  open   syslog-haproxy-0.107-2021.02.07        mz_fap9DTpGIb9Y_dhr6MQ   1
119130        1mb        514.3kb
green  open   syslog-0.104-2021.02.04                MFjeKZsnR0u1R3onL_2zxA   1
1531803.4mb          1.7mb
green  open   nginx-errorlog-redis-0.107-2021.02.09  V8No1ik3T6mN2FLdDnKYiA   1
11041.2kb         20.6kb
green  open   syslog-0.104-2021.02.07                pXl_MaBkRTi4j7ilt65kPA   1
1568803.6mb          1.8mb
#查看指定索引信息
[root@es-node1 ~]#curl -XPOST 'localhost:9200/nginx-errorlog-0.107-
2021.02.04/_search?pretty'
{
"took" : 7,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
  },

范例: 创建索引

#elasticsearch 7.X 默认创建1个分片1个副本,之前版本默认5分版1副本
#https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-
index.html
#创建索引index1,简单输出
[root@node1 ~]#curl -XPUT '10.0.0.101:9200/index1'
{"acknowledged":true,"shards_acknowledged":true,"index":"index1"}
#创建索引index2,格式化输出
[root@node1 ~]#curl -XPUT '10.0.0.101:9200/index2?pretty'
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "index2"
}
[root@node1 ~]#curl  '10.0.0.101:9200/index1?pretty'
{
"index1" : {
"aliases" : { },
"mappings" : { },
"settings" : {
"index" : {
"routing" : {
"allocation" : {
"include" : {
"_tier_preference" : "data_content"
            }
          }
        },
"number_of_shards" : "1",
"provided_name" : "index1",
"creation_date" : "1629086229360",
"number_of_replicas" : "1",
"uuid" : "t-t7GOq0RSOig6a1Fjv5Ug",
"version" : {
"created" : "7140099"
        }
      }
    }
  }
}
#创建3个分片和2个副本的索引
[root@node1 ~]#curl -XPUT '10.0.0.101:9200/index2' -H 'Content-Type:
application/json' -d '
{
"settings": {
"index": {
"number_of_shards": 3,
"number_of_replicas": 2
    }
  }
}'
{"acknowledged":true,"shards_acknowledged":true,"index":"index2"}
#调整副本数为1,但不能调整分片数
[root@node1 ~]#curl -XPUT '10.0.0.101:9200/index2/_settings' -H 'Content-Type:
application/json' -d '
{
"settings": {
"number_of_replicas": 1
    }
}'
{"acknowledged":true}
#早期版本,如es1.X,2.X可以直在下面数据目录下直接看到index的名称,5.X版本后只会显示下面信息
[root@es-node1 ~]#ll /data/es-data/nodes/0/indices/

total 12

drwxr-xr-x 3 elasticsearch elasticsearch 4096 Jan 2623:19 ./
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2623:19 ../
drwxr-xr-x 7 elasticsearch elasticsearch 4096 Jan 2623:19
TPUrqHNdRT2lCNVPMPF2eg/
[root@es-node2 ~]#ll /data/es-data/nodes/0/indices/
total 20
drwxr-xr-x 5 elasticsearch elasticsearch 4096 Jan 2623:49 ./
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2623:15 ../
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2623:15
32A1_WR4QEKmTfKFe61JjA/
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2623:49
cBxWy995SrS9LAET660t9w/
drwxr-xr-x 6 elasticsearch elasticsearch 4096 Jan 2623:19
TPUrqHNdRT2lCNVPMPF2eg/
[root@es-node3 ~]#ll /data/es-data/nodes/0/indices/
total 20
drwxr-xr-x 5 elasticsearch elasticsearch 4096 Jan 2623:49 ./
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2623:15 ../
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2623:15
32A1_WR4QEKmTfKFe61JjA/
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2623:49
cBxWy995SrS9LAET660t9w/
drwxr-xr-x 6 elasticsearch elasticsearch 4096 Jan 2623:19
TPUrqHNdRT2lCNVPMPF2eg/

范例: 插入数据

#_id 自动生成
#index1是索引数据库,book是type
[root@node1 ~]#curl -XPOST http://10.0.0.101:9200/index1/book/ -H 'Content-Type:
application/json' -d '{"name":"linux", "author": "wangxiaochun", "version":
"1.0"}'
{"_index":"index1","_type":"book","_id":"isQ3TXsB1gLtFVg76of5","_version":1,"res
ult":"created","_shards":
{"total":2,"successful":2,"failed":0},"_seq_no":0,"_primary_term":1}
[root@node1 ~]#curl -XPOST 'http://10.0.0.101:9200/index1/book?pretty' -H
'Content-Type: application/json' -d '{"name":"python", "author": "xuwei",
"version": "1.0"}'
{
"_index" : "index1",
"_type" : "book",
"_id" : "i8Q5TXsB1gLtFVg7vodl",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
  },
"_seq_no" : 1,
"_primary_term" : 1
}
#_id 指定为3
#index1是索引数据库,book是type,3是document记录
[root@node1 ~]#curl -XPOST 'http://10.0.0.101:9200/index1/book/3?pretty' -H
'Content-Type: application/json' -d '{"name":"golang", "author": "zhang",
"version": "1.0"}'
{
"_index" : "index1",
"_type" : "book",
"_id" : "3",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
  },
"_seq_no" : 2,
"_primary_term" : 1
}
#数据存放的磁盘位置
[root@node1 ~]#tree /data/es-data/ -d
/data/es-data/
└── nodes
    └── 0
        ├── indices
        │   ├── KnAuNXCPQS6CqzqXY3Plgw
        │   │   ├── 0
        │   │   │   ├── index
        │   │   │   ├── _state
        │   │   │   └── translog
        │   │   └── _state
        │   └── t-t7GOq0RSOig6a1Fjv5Ug
        │       ├── 0
        │       │   ├── index
        │       │   ├── _state
        │       │   └── translog
        │       └── _state
        ├── snapshot_cache
        └── _state
17 directories

范例: 查询指定ID的索引

#指定ID查询
#curl -XGET ‘http://localhost:9200/{index}/{type}/{id}’
[root@node1 ~]#curl  'http://localhost:9200/index1/book/3?pretty'
{
"_index" : "index1",
"_type" : "book",
"_id" : "3",
"_version" : 1,
"_seq_no" : 2,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "golang",
"author" : "zhang",
"version" : "1.0"
  }
}
#查询所有
[root@node1 ~]#curl  'http://10.0.0.101:9200/index1/_search?pretty'
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
  },
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
    },
"max_score" : 1.0,
"hits" : [
      {
"_index" : "index1",
"_type" : "book",
"_id" : "isQ3TXsB1gLtFVg76of5",
"_score" : 1.0,
"_source" : {
"name" : "linux",
"author" : "wangxiaocohun",
"version" : "1.0"
        }
      },
      {
"_index" : "index1",
"_type" : "book",
"_id" : "i8Q5TXsB1gLtFVg7vodl",
"_score" : 1.0,
"_source" : {
"name" : "python",
"author" : "wuwei",
"version" : "1.0"
        }
      },
      {
"_index" : "index1",
"_type" : "book",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"name" : "golang",
"author" : "zhang",
"version" : "1.0"
        }
      }
    ]
  }
}
#按条件进行查询
[root@node1 ~]#curl  'http://localhost:9200/index1/book/_search?
q=name:linux&pretty'
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
  },
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
    },
"max_score" : 0.9808291,
"hits" : [
      {
"_index" : "index1",
"_type" : "book",
"_id" : "isQ3TXsB1gLtFVg76of5",
"_score" : 0.9808291,
"_source" : {
"name" : "linux",
"author" : "wangxiaocohun",
"version" : "1.0"
        }
      }
    ]
  }
}

范例: 更新

[root@node1 ~]#curl -XPOST 'http://localhost:9200/index1/book/3' -H 'Content-
Type: application/json' -d '{"version": "2.0","name":"golang","author": "zhang"}'
{"_index":"index1","_type":"book","_id":"3","_version":3,"result":"updated","_sh
ards":{"total":2,"successful":2,"failed":0},"_seq_no":5,"_primary_term":1}
[root@node1 ~]#curl  'http://localhost:9200/index1/book/3?pretty'
{
"_index" : "index1",
"_type" : "book",
"_id" : "3",
"_version" : 3,
"_seq_no" : 5,
"_primary_term" : 1,
"found" : true,
"_source" : {
"version" : "2.0",
"name" : "golang",
"author" : "zhang"
  }
}

删除格式

curl -XDELETE http://kibana服务器:9200/<索引名称>

范例: 删除

[root@node1 ~]#curl -XDELETE
'http://localhost:9200/index1/book/i8Q5TXsB1gLtFVg7vodl'
{"_index":"index1","_type":"book","_id":"i8Q5TXsB1gLtFVg7vodl","_version":2,"res
ult":"deleted","_shards":
{"total":2,"successful":2,"failed":0},"_seq_no":3,"_primary_term":1

范例: 删除指定索引

[root@es-node1 ~]#curl -XDELETE http://10.0.0.101:9200/tomcat-accesslog-0.107-
2021.02.02
{"acknowledged":true}

范例: 删除所有索引

[root@es-node1 ~]#for i in `curl 'http://10.0.0.101:9200/_cat/indices?v'|awk
'{print $3}'`;do curl -XDELETE http://10.0.0.101:9200/$i;done

2.4.2 Python脚本

[root@es-node1~]# apt -y install python3
[root@es-node1~]# cat els-cluster-monitor.py
#!/usr/bin/python3
#coding:utf-8
importsmtplib
fromemail.mime.textimportMIMEText
fromemail.utilsimportformataddr
importsubprocess
importjson
body = ""
false="false"
#用另外一个进程运行curl返回结果从stdout中读取
obj = subprocess.Popen(("curl -sXGET http://10.0.0.101:9200/_cluster/health?
pretty=true"),shell=True, stdout=subprocess.PIPE) #
data = obj.stdout.read()
#print(type(data)) # 应该是字符串类型或bytes类型
#print(data) # 看看是不是返回的json形式的
es_dict = json.loads(data) ifdataelse {}  # 把json字符串解析为字典
status = es_dict.get("status") # 通过字典查找status
ifstatus == "green":
print("OK")
else:
print("Not OK")
[root@es-node1~]# chmod +x els-cluster-monitor.py
[root@es-node1~]#./els-cluster-monitor.py
OK
#将第二个节点停止服务
[root@es-node2~]# systemctl stop elasticsearch
#再次查看状态
[root@es-node1~]# python els-cluster-monitor.py
NotOK

2.5 Elasticsearch 插件

2.5.1 Head 插件

通过使用插件可以实现对 ES 集群的状态监控, 数据访问, 管理配置等功能。

2.5.1.1 Head 介绍

Head 是一个 ES 在生产较为常用的插件

git地址:https://github.com/mobz/elasticsearch-head

三种安装方法

编译安装 Docker 浏览器插件

2.5.1.2 编译安装
2.5.1.2.1 安装 Head 插件前准备

注意: 如果使用浏览器插件,则无需此步

修改elasticsearch节点的服务配置文件,开启跨域访问支持,然后重启elasticsearch服务

官方文档:

https://www.elastic.co/guide/en/elasticsearch/reference/6.8/modules-http.html

范例:

[root@es-node1 ~]# vim /etc/elasticsearch/elasticsearch.yml
#在文件最后添加下面两行
http.cors.enabled: true#开启支持跨域访问
http.cors.allow-origin: "*"#指定允许访问范围
[root@es-node1 ~]# systemctl restart elasticsearch
2.5.1.2.2 服务方式启动

在elasticsearch 5.x版本以后不再支持直接安装head插件,而是通过服务启动

此安装方式通过 npm 工具实现

npm(Node Package Manager)是和NodeJS一起安装的包管理和分发工具,使用npm 可以很方便让 JavaScript开发者下载、安装、上传以及管理已经安装的相关包。

范例: CentOS 7 安装 Head 插件

[root@es-node1 ~]# yum install -y npm git
#因为使用了nodejs,建议用下面方式加速
[root@es-node1 ~]#apt install npm
[root@es-node1 ~]#npm config get registry
https://registry.npmjs.org/
[root@es-node1 ~]#npm config set registry  https://registry.npm.taobao.org
[root@es-node1 ~]#npm config get registry
https://registry.npm.taobao.org/
[root@es-node1 ~]# cd /usr/local/src/
[root@es-node1 src]#git clone git://github.com/mobz/elasticsearch-head.git
[root@es-node1 src]# cd elasticsearch-head/
[root@es-node1 elasticsearch-head]# npm install grunt -save
[root@es-node2 elasticsearch-head]# ll node_modules/grunt #确认生成文件
[root@es-node1 elasticsearch-head]# npm install #执行安装
[root@es-node1 elasticsearch-head]# npm run start  & #后台启动服务

范例: Ubuntu 安装 Head 插件

[root@es-node1 ~]# apt -y install npm
#因为使用了nodejs,建议用下面方式加速
[root@es-node1 ~]#npm config get registry
https://registry.npmjs.org/
[root@es-node1 ~]#npm config set registry  https://registry.npm.taobao.org
[root@es-node1 ~]#npm config get registry
https://registry.npm.taobao.org/
[root@es-node1 ~]# git clone git://github.com/mobz/elasticsearch-head.git
[root@es-node1 ~]# cd elasticsearch-head/
[root@es-node1 elasticsearch-head]# npm install #执行安装
[root@es-node1 elasticsearch-head]# npm run start  & #后台启动服务
2.5.1.3 Docker 方式启动 Head 插件
[root@es-node1 ~]#docker run -d -p 9100:9100 --name head  mobz/elasticsearch-
head:5
#安装完毕后,访问:http://localhost:9100

2.5.1.4 浏览器安装插件

2.5.1.4.1 在线安装

从谷歌应用商店下载安装插件,支持chrome和edge浏览器

注意: 需要科学上网

https://chrome.google.com/webstore/detail/elasticsearch-
head/ffmkiejjmecolpfloofpjologoblkegm/related

安装完插件,点击图标就可以打开插件

2.5.1.4.2 离线安装

先下载Head插件文件,再离线安装

2.5.1.5 利用 Head 插件观察状态

head 插件中集群状态说明

状态颜色说明:

绿色:索引数据完整,副本满足,所有条件都满足

黄色:索引数据完整,副本不满足,即数据没有丢失,但副本丢失,可能会影响容错功能红色:有索引数据不完整的情况,即数据丢失

紫色:有数据分片正在同步过程中

  • 0 表示分片的片shard编号

粗体线框为主分片,细体线框为副本分片

星表示主master节点,圆点表示slave工作节点

添加索引后,可以观察到下面显示

[root@node3 ~]#systemctl stop  elasticsearch.service

[root@node3 ~]#systemctl start  elasticsearch.service

有时出现紫色的同步状态

index2数据库是2分片3副本

2.4.2 Cerebro 插件

2.5.2.1 Cerebro 介绍

Cerebro 是开源的 elasticsearch 集群 Web 管理程序,需要 java1.8 或者更高版本,此工具应用也很广泛 Cerebro v0.9.4 需要 Java11

github链接: https://github.com/lmenezes/cerebro

2.5.2.2 包安装

注意:内存建议大于3G以上

#依赖JDK
[root@ubuntu2004 ~]#apt -y install openjdk-11-jdk
#Java8实际也支持
[root@ubuntu2004 ~]#apt -y install openjdk-8-jdk
#下载包,官方提供了DEB和RPM包
[root@ubuntu2004 ~]#wget
https://github.com/lmenezes/cerebro/releases/download/v0.9.4/cerebro_0.9.4_all.d
eb
#安装
[root@ubuntu2004 ~]#dpkg -i cerebro_0.9.4_all.deb
#启动
[root@ubuntu2004 ~]#systemctl start cerebro.service
#默认无法启动,查看日志,可以看到以下提示,原因是默认cerebro.db文件所有目录没有权限导致
[root@ubuntu2004 ~]#journalctl  -u cerebro
 Caused by: java.sql.SQLException: opening db: './cerebro.db': 权限不够

# 修改配置文件

[root@ubuntu2004 ~]#vim /etc/cerebro/application.conf
data.path: "/var/lib/cerebro/cerebro.db"#取消此行注释
#data.path = "./cerebro.db"  #注释此行
[root@ubuntu2004 ~]#systemctl restart  cerebro.service
active
[root@ubuntu2004 ~]#ss -ntlp|grep 9000
LISTEN   0100   *:9000         *:*        users:(("java",pid=26333,fd=155))

# 访问下面链接地址

http://cerebro.wang.org:9000
#在Node address输入框中输入ES的地址http://127.0.0.1:9200

三节点集群显示如下

显示特殊索引

2.5.2.3 二进制安装

注意:内存建议大于3G以上

#先安装jdk
[root@es-node1 ~]#apt -y install  openjdk-8-jdk
#下载文件
[root@es-node1 ~]#wget
https://github.com/lmenezes/cerebro/releases/download/v0.9.3/cerebro-0.9.3.tgz
[root@es-node1 ~]#tar xvf cerebro-0.9.3.tgz -C /usr/local/
[root@es-node1 ~]#ln -s /usr/local/cerebro-0.9.3/ /usr/local/cerebro
#修改配置
[root@es-node1 ~]#vim /usr/local/cerebro/conf/application.conf
hosts = [
  {
    host ="http://10.0.0.101:9200"#修改此行,指向ES的地址
    name ="es-cluster"#修改此行
#  headers-whitelist = [ "x-proxy-user", "x-proxy-roles", "X-Forwarded-For" ]
#}
# Example of host with authentication
#{
#  host = "http://some-authenticated-host:9200"
#  name = "Secured Cluster"
#  auth = {
#    username = "username"
#    password = "secret-password"
#  }
  }
]
#启动插件
[root@es-node1 ~]#/usr/local/cerebro/bin/cerebro &
[info] play.api.Play - Application started (Prod) (no global state)
[info] p.c.s.AkkaHttpServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
......
#打开浏览器访问http://10.0.0.101:9000 可看到下面提示

点击集群名es-cluster 就可以进入下面界面

2.5.2.4 Docker 运行
docker run -p 9000:9000 --env-file env-ldap  lmenezes/cerebro

2.5.3 利用插件管理索引

2.5.3.1 利用 cerebro 插件创建索引

建议shard分片数配置为ELK服务器的数量,副本为1表示对数据有一个备份

再创建一个索引,不指定分片信息

2.5.3.2 利用 cerebro 插件验证分片

ES7.0版本默认分片为1个,并且只有1个副本

ES6.X版本前默认分片为5个副本1个

2.5.3.3 利用 head 插件验证

观察下面2外面的框比较粗,即为primary分片

2.5.3.4 利用 head 插件删除索引

2.5.3.5 在各个节点主机自动生成下面目录
[root@es-node1 ~]#ll /data/es-data/nodes/0/indices/
total 16
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2613:39 ./
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2613:31 ../
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2613:39
32A1_WR4QEKmTfKFe61JjA/
drwxr-xr-x 6 elasticsearch elasticsearch 4096 Jan 2613:31
TPUrqHNdRT2lCNVPMPF2eg/
[root@es-node2 ~]#ll /data/es-data/nodes/0/indices/
total 12
drwxr-xr-x 3 elasticsearch elasticsearch 4096 Jan 2613:31 ./
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2613:31 ../
drwxr-xr-x 7 elasticsearch elasticsearch 4096 Jan 2613:32
TPUrqHNdRT2lCNVPMPF2eg/
[root@es-node3 ~]#ll /data/es-data/nodes/0/indices/
total 16
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2613:39 ./
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2613:31 ../
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 2613:39
32A1_WR4QEKmTfKFe61JjA/
drwxr-xr-x 6 elasticsearch elasticsearch 4096 Jan 2613:31
TPUrqHNdRT2lCNVPMPF2eg/

2.5.4 其它插件

Edge 浏览器应用中还有其它ES插件,可以使用

2.6 Elasticsearch 集群工作原理

官方说明

https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

2.6.1 节点分类

单机节点 ES 存在单点问题,可以实现多机的集群,每个节点的角色有所不同

ES的节点有三种

Master 节点

ES集群中只有一个 Master 节点,用于控制整个集群的操作

Master 节点负责增删索引,增删节点,shard分片的重新分配

Master 主要维护Cluster State,包括节点名称,节点连接地址,索引名称和配置认息等

Master 接受集群状态的变化并推送给所有节点,集群中各节点都有一份完整的集群状态信息,都由 master node负责维护

Master 节点不需要涉及到文档级别的变更和搜索等操作协调创建索引请求或查询请求,将请求分发到相关的node上。

当Cluster State有新数据产生后, Master 会将数据同步给其他 Node 节点

Master节点通过超过一半的节点投票选举产生的

可以设置node.master: true 指定为是否参与Master节点选举, 默认true

Data 节点

存储数据的节点即为 data 节点

当创建索引后,索引创建的数据会存储至某个数据节点

Data 节点消耗内存和磁盘IO的性能比较大

配置node.data: true, 默认为 true,即默认节点都是 data类型

Coordinating 节点(协调)

处理请求的节点即为 coordinating 节点,该节点为所有节点的默认角色,不能取消

coordinating 节点主要将请求路由到正确的节点处理。比如创建索引的请求会由 coordinating 路由到 master 节点处理

当配置 node.master:false、node.data:false 则只充当 coordinating节点

2.6.2 集群选举

ES集群的选举是由master-eligble(有资格的master节点)发起,当该节点发现当前节点不是master, 并且该节点通过ZenDiscovery模块ping其他节点,得到超过mininum_master_nodes个节点无法连接 master时,就会发起选举

选举时,优先选举ClusterStateVersion最大的Node节点,如果ClusterStateVersion相同,则选举ID最小的Node

ClusterStateVersion是集群的状态版本号,每一次集群选举ClusterStateVersion都会更新,因此最大的 ClusterStateVersion是与原有集群数据最接近或者是相同的,这样就尽可能的避免数据丢失。

Node的ID是在第一次服务启动时随机生成的,直接选用最小ID的Node,主要是为了选举的稳定性,尽量少的出现选举不出来的问题。

每个集群中只有一个Master节点

每个集群中损坏的节点不能超过集群一半以上,否则集群将无法提供服务

2.6.3 ES 集群分片和副本

2.6.3.1 分片 Shard

ES 中存储的数据可能会很大,有时会达到PB级别

基于性能和容量等原因,可以将一个索引数据分割成多个小的分片,再将每个分片分布至不同的节点,从而实现数据的分布存储,实现性能和容量的水平扩展

在读取时,可以实现多节点的并行读取,提升性能

除此之外,如果一个分片的主机宕机,也不影响其它节点分片的读取

横向扩展即增加服务器,当有新的Node节点加入到集群中时,集群会动态的重新进行分配和负载

例如原来有两个Node节点,每个节点上有3个分片,即共6个分片,如果再添加一个node节点到集群中, 集群会动态的将此6个分片分配到这三个节点上,最终每个节点上有两个分片。

7,X 默认每个索引只有一个分片

2.6.3.2 副本 Replication

将一个索引分成多个分片,仍然存在数据的单点问题,可以对每一个分片进行复制生成副本,即备份,实现数据的高可用

ES的分片分为主分片(primary shard)和副本分片(复制replica shard),而且通常分布在不同节点主分片实现数据读写,副本分片只支持读

每个数据分片只有一个主分片,而副本分片可以有多个,比如;一个副本,即有一个备份

7,X 默认每个索引只有一个副本分片

2.6.4 ES集群故障转移

故障转移指的是,当集群中有节点发生故障时,ES集群会进行自动修复

假设由3个节点的ES集群组成,其中一个节点宕机

ES集群的故障转移流程如下

重新选举

node3 节点宕机,导致 node3 的原有的P0和R2分片丢失

node1 和 node2 发现 node1 无法响应

一段时间后会发起 master 选举,比如这里选择 node1 为 master 节点;此时集群状态变为 Red 状态

主分片调整

新的Master节点 node1 发现在原来在node3上的主分片 P0 未分配,将 node2 上的 R0 提升为主分片

此时所有的主分片都正常分配,但0和2分片没有副本分片,集群状态变为 Yellow状态

副本分片调整

node1 将 P0 和 P2 主分片重新生成新的副本分片 R0、R1,此时集群状态变为 Green

修复好node3节点后,自动将各个分片均匀分配

2.6.5 ES 文档路由

2.6.5.1 ES 文档路由原理

ES文档是分布式存储,当一个文档存储至 ES集群时,如何决定存储的节点位置,以及读取时从哪里获取数据?

在ES 中,通过如下的公式计算文档对应的分片存储到哪个节点

shard = hash(routing) % number_of_primary_shards
# hash 算法保证将数据均匀分散在分片中
# routing 是一个可变参数,默认是文档id,也可以自定义。
# number_of_primary_shards 主分片数
#注意:该算法与主分片数相关,一但确定后便不能更改主分片

可以发送请求到集群中的任一节点。每个节点都知道集群中任一文档位置, 每个节点都有能力接收请求, 再接将请求转发到真正存储数据的节点上

2.6.5.2 ES 文档创建流程

  • 客户端向协调节点 Node1 发送新建索引文档或者删除索引文档请求。

  • Node1节点使用文档的 _id 确定文档属于分片 0 。

  • 因为分片 0 的主分片目前被分配在 Node 3 上,请求会被转发到 Node 3

  • Node3 在主分片上面执行创建或删除请求

  • Node3 执行如果成功,它将请求并行转发到 Node1 和 Node2 的副本分片上。

  • 一旦所有的副本分片都报告成功, Node3 将向协调节点Node1 报告成功

  • 协调节点Node1 客户端报告成功。在客户端收到响应时,文档变更已经在主分片和所有副本分片执行完成

2.6.5.3 ES 文档读取流程

可以从主分片或者从其它任意副本分片读取文档 ,读取流程如下图所示 :

  • 客户端向 Node1 发送读取请求。

  • 节点使用文档的 _id 来确定文档属于分片 0 。分片 0 的副本分片存在于所有的三个节点上。

  • 在处理读取请求时,协调结点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡。

  • 在这种情况下,它将请求转发到 Node2 。

  • Node2 将文档返回给 Node1 ,然后将文档返回给客户端。

3 Beats 收集数据

Beats 是一个免费且开放的平台,集合了多种单一用途数据采集器。它们从成百上千或成千上万台机器和系统向 Logstash 或 Elasticsearch 发送数据。

虽然利用 logstash 就可以收集日志,功能强大,但由于 Logtash 是基于Java实现,需要在采集日志的主机上安装JAVA环境,会消耗比较多的内存和磁盘空间,logstash运行时最少也会需要额外的500M的以上的内存,资源消耗很大,有些得不偿失。

可以采有基于Go开发的 Beat 工具代替 Logstash 收集日志,部署更为方便,而且只占用10M左右的内存空间及更小的磁盘空间。

官方链接

https://www.elastic.co/cn/beats/

Github 链接

https://github.com/elastic/beats

下载链接

https://www.elastic.co/cn/downloads/beats

Beats 是一些工具集,包括以下,其中 filebeat 应用最为广泛

Beat Description
Auditbeat Collect your Linux audit framework data and monitor the integrity of your
files.
Filebeat Tails and ships log files
Functionbeat Read and ships events from serverless infrastructure.
Heartbeat Ping remote services for availability
Metricbeat Fetches sets of metrics from the operating system and services
Packetbeat Monitors the network and applications by sniffing packets
Winlogbeat Fetches and ships Windows Event logs
Osquerybeat Runs Osquery and manages interraction with it.
filebeat:收集日志文件数据。最常用的工具
packetbeat:用于收集网络数据。一般用zabbix实现此功能
metricbeat:从OS和服务收集指标数据,比如系统运行状态、CPU 内存利用率等。
winlogbeat:从Windows平台日志收集工具。
heartbeat:定时探测服务是否可用。支持ICMP、TCP 和 HTTP,也支持TLS、身份验证和代理
auditbeat:收集审计日志
Functionbeat:使用无服务器基础架构提供云数据。面向云端数据的无服务器采集器,处理云数据

注意: Beats 版本要和 Elasticsearch 相同的版本,否则可能会出错

3.1 利用 Metricbeat 监控性能相关指标

metricbeat 可以收集指标数据,比如系统运行状态、CPU、内存利用率等。 生产中一般用 zabbix等专门的监控系统实现此功能

官方配置说明

https://www.elastic.co/guide/en/beats/metricbeat/current/configuring-howto-
metricbeat.html

3.1.1 下载 metricbeat 并安装

下载链接

https://www.elastic.co/cn/downloads/beats/metricbeat
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/apt/pool/main/m/metricbeat
/
[root@elk-web2 ~]#wget
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/apt/pool/main/m/metricbeat
/metricbeat-7.6.2-amd64.deb
[root@elk-web2 ~]#dpkg -i metricbeat-7.6.2-amd64.deb

3.1.2 修改配置

[root@elk-web2 ~]#vim /etc/metricbeat/metricbeat.yml
setup.kibana:
   host: "10.0.0.101:5601"#指向kabana服务器地址和端口,非必须项,当使用dashboard时才需
要指定
#-------------------------- Elasticsearch output ------------------------------
output.elasticsearch:
# Array of hosts to connect to.
hosts: ["10.0.0.102:9200"]   #指向任意一个ELK集群节点即可
[root@elk-web2 ~]#grep -Ev "#|^$" /etc/metricbeat/metricbeat.yml
metricbeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: false
setup.template.settings:
  index.number_of_shards: 1
  index.codec: best_compression
setup.kibana:
  host: "10.0.0.101:5601"
output.elasticsearch:
  hosts: ["10.0.0.102:9200"]
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~
- add_docker_metadata: ~
- add_kubernetes_metadata: ~

3.1.3 启动服务

[root@elk-web2 ~]#systemctl enable --now  metricbeat.service
Synchronizing state of metricbeat.service with SysV service script with
/lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable metricbeat
[root@elk-web2 ~]#systemctl status metricbeat.service
● metricbeat.service - Metricbeat is a lightweight shipper for metrics.
   Loaded: loaded (/lib/systemd/system/metricbeat.service; enabled; vendor
preset: enabled)
   Active: active (running) since Sun 2021-02-0712:11:13 CST; 1s ago
     Docs: https://www.elastic.co/products/beats/metricbeat
 Main PID: 1741 (metricbeat)
    Tasks: 10 (limit: 2290)
   CGroup: /system.slice/metricbeat.service
           └─1741 /usr/share/metricbeat/bin/metricbeat -e-c
/etc/metricbeat/metricbeat.yml -path.home /usr/share/metricbeat -path.config
/etc/metricbeat -pa
Feb 0712:11:14 elk-web2.wang.org metricbeat[1741]: 2021-02-07T12:11:14.440+0800
       INFO        pipeline/output.go:95        Connecting to backoff(elas
Feb 0712:11:14 elk-web2.wang.org metricbeat[1741]: 2021-02-07T12:11:14.453+0800
       INFO        elasticsearch/client.go:757        Attempting to connec
Feb 0712:11:14 elk-web2.wang.org metricbeat[1741]: 2021-02-07T12:11:14.503+0800
       INFO        [license]        licenser/es_callback.go:50        Elas
Feb 0712:11:14 elk-web2.wang.org metricbeat[1741]: 2021-02-07T12:11:14.528+0800
       INFO        [index-management]        idxmgmt/std.go:258        Aut
Feb 0712:11:14 elk-web2.wang.org metricbeat[1741]: 2021-02-07T12:11:14.621+0800
       INFO        [index-management]        idxmgmt/std.go:271        ILM
Feb 0712:11:14 elk-web2.wang.org metricbeat[1741]: 2021-02-07T12:11:14.622+0800
       INFO        [index-management]        idxmgmt/std.go:410        Set
Feb 0712:11:14 elk-web2.wang.org metricbeat[1741]: 2021-02-07T12:11:14.622+0800
       INFO        [index-management]        idxmgmt/std.go:415        Set
Feb 0712:11:14 elk-web2.wang.org metricbeat[1741]: 2021-02-07T12:11:14.622+0800
       INFO        [index-management]        idxmgmt/std.go:449        Set
Feb 0712:11:14 elk-web2.wang.org metricbeat[1741]: 2021-02-07T12:11:14.622+0800
       INFO        [index-management]        idxmgmt/std.go:453        Set
Feb 0712:11:14 elk-web2.wang.org metricbeat[1741]: 2021-02-07T12:11:14.628+0800
       INFO        template/load.go:169        Existing template will be o
lines 1-19/19 (END)

3.1.4 Head 插件查看索引

3.1.5 通过 Kibana 查看收集的性能指标

3.2 利用 Heartbeat 监控

heartbeat 用来定时探测服务是否正常运行。支持ICMP、TCP 和 HTTP,也支持TLS、身份验证和代理

官方heartbeat配置文档

https://www.elastic.co/guide/en/beats/heartbeat/current/configuring-howto-
heartbeat.html

3.2.1 下载并安装

下载链接

https://www.elastic.co/cn/downloads/beats/heartbeat
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/apt/pool/main/f/filebeat/
[root@elk-web2 ~]#wget
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/apt/pool/main/h/heartbeat-
elastic/heartbeat-7.6.2-amd64.deb
[root@elk-web2 ~]#dpkg -i heartbeat-7.6.2-amd64.deb
#准备需要监控的服务httpd
[root@elk-web2 ~]#apt -y install apache2

3.2.2 修改配置

官方参考

https://www.elastic.co/guide/en/beats/heartbeat/current/configuration-heartbeat-
options.html
# heartbeat.yml
heartbeat.monitors:
- type: icmp
  id: ping-myhost
  name: My Host Ping
  hosts: ["myhost"]
  schedule: '*/5 * * * * * *'
- type: tcp
  id: myhost-tcp-echo
  name: My Host TCP Echo
  hosts: ["myhost:777"]  # default TCP Echo Protocol
  check.send: "Check"
  check.receive: "Check"
  schedule: '@every 5s'
- type: http
  id: service-status
  name: Service Status
  service.name: my-apm-service-name
  hosts: ["http://localhost:80/service/status"]
  check.response.status: [200]
  schedule: '@every 5s'
heartbeat.scheduler:
  limit: 10

时间格式

https://github.com/gorhill/cronexpr#implementation
Field name     Mandatory?   Allowed values    Allowed special characters
----------     ----------   --------------    --------------------------
Seconds        No           0-59              * / , -
Minutes        Yes          0-59              * / , -
Hours          Yes          0-23              * / , -
Day of month   Yes          1-31              * / , - L W
Month          Yes          1-12 or JAN-DEC   * / , -
Day of week    Yes          0-6 or SUN-SAT    * / , - L #
Year           No           1970–2099         * / , -

范例

[root@elk-web2 ~]#vim /etc/heartbeat/heartbeat.yml
22# Configure monitors inline
23 heartbeat.monitors:
24- type: http
25
26# List or urls to query
27   urls: ["http://localhost:80"]  #指向需要监控的服务器的地址和端口
28
29# Configure task schedule
30   schedule: '@every 10s'
31
32# Total test connection and data exchange timeout
33   timeout: 6s
35- type: icmp                   #监控ICMP
36   id: ping-myhost
37   name: My Host Ping
38   hosts: ["10.0.0.100"]
39   schedule: '*/5 * * * * * *'
62 setup.kibana:
63
64# Kibana Host
65# Scheme and port can be left out and will be set to the default (http and
5601)
  • 66 # In case you specify and additional path, the scheme is required:

  • http://localhost:5601/path

  • 67 # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 68 host: "10.0.0.101:5601 # 指向 kibana 服务器地址和端口

  • 92 #-------------------------- Elasticsearch output ---------------------------

  • 93 output.elasticsearch:

  • 94 # Array of hosts to connect to.

  • 95 hosts: ["10.0.0.101:"] # 指向 ELK 集群服务器地址和端口

3.2.3 启动服务

[root@elk-web2 ~]#systemctl enable --now  heartbeat-elastic.service

3.2.4 head 插件查看索引

3.2.5 通过 Kibana 查看收集的性能指标

3.2.6 停止监控的服务再观察 Kibana

[root@elk-web2 ~]#systemctl stop apache2

3.2.7 利用 Kibana 将 Heartbeat 的数据进行可视化

3.3 利用 Filebeat 收集日志

Filebeat 是用于转发和集中日志数据的轻量级传送程序。作为服务器上的代理安装,Filebeat监视您指定的日志文件或位置,收集日志事件,并将它们转发到Elasticsearch或Logstash进行索引。

Logstash 直接收集日志,需要安装JDK,并且会占用至少500M 以上的内存

生产一般使用filebeat代替logstash, 基于go开发,部署方便,重要的是只需要10M多内存,比较节约资源.

filebeat 支持从日志,Syslog,Redis,Docker,TCP,UDP,标准输入等读取数据,再输入至 Elasticsearch,logstash,Redis,Kafka等

Filebeat的工作方式如下:

启动Filebeat时,它将启动一个或多个输入,这些输入将在为日志数据指定的位置中查找。对于Filebeat 所找到的每个日志,Filebeat都会启动收集器。每个收集器都读取一个日志以获取新内容,并将新日志数据发送到libbeat,libbeat会汇总事件并将汇总的数据发送到为Filebeat配置的输出。

Filebeat 官方说明

https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html
https://www.elastic.co/guide/en/beats/filebeat/current/configuring-howto-
filebeat.html

输入和输入官方说明

https://www.elastic.co/guide/en/beats/filebeat/current/configuration-filebeat-
options.html
https://www.elastic.co/guide/en/beats/filebeat/current/configuring-output.html

注意: Filebeat 支持多个输入,但不支持同时有多个输出

3.3.1 安装 Filebeat

[root@elk-web1 ~]#wget
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/apt/pool/main/f/filebeat/f
ilebeat-7.6.2-amd64.deb
[root@elk-web1 ~]#dpkg -i filebeat-7.6.2-amd64.deb

官方说明

https://www.elastic.co/guide/en/beats/filebeat/8.3/configuration-general-
options.html

添加新字段的配置说明

#添加新字段
vim /etc/filebeat/filebeat.yml
- type : log
  enabled: true
  paths:
- /var/log/syslog
  fields:
    project: test-syslog  #添加fields.project和fields.env字段,可用于区分不同的日志
    env: test
  tags: ["syslog","test"]        #添加标签,也可以用于区分不同的日志

3.3.2 案例: 从标准输入读取再输出至标准输出

3.3.2.1 创建配置
[root@elk-web1 ~]#vim /etc/filebeat/stdin.yml
filebeat.inputs:
- type: stdin
  enabled: true
output.console:
  pretty: true
  enable: true
3.3.2.2 执行读取
[root@elk-web1 ~]#filebeat -e -c /etc/filebeat/stdin.yml
.....
hello,es  #输入,回车后,输出如下
{
"@timestamp": "2022-07-09T14:48:22.446Z",
"@metadata": {
"beat": "filebeat",
"type": "_doc",
"version": "7.17.5"
  },
"agent": {
"name": "es-web01",
"type": "filebeat",
"version": "7.17.5",
"hostname": "es-web01",
"ephemeral_id": "8918da58-f04c-4b74-9dfe-4e53952c2530",
"id": "fffb2178-8110-400c-b3f9-ce8920aeb61a"
  },
"message": "hello,es",
"log": {
"offset": 0,
"file": {
"path": ""
    }
  },
"input": {
"type": "stdin"
  },
"ecs": {
"version": "1.12.0"
  },
"host": {
"name": "es-web01"
  }
}

3.3.3 案例: 从标准输入读取再输出至 Json 格式的文件

3.3.3.1 创建配置
[root@elk-web1 ~]#vim /etc/filebeat/stdout_file.yml
filebeat.inputs:
- type: stdin
  enabled: true
  json.keys_under_root: true#默认False会将json数据存储至message,改为true则会独立
message外存储
output.file:
  path: "/tmp"
  filename: "filebeat.log"
3.3.2.2 执行读取
[root@elk-web1 ~]#filebeat -e -c /etc/filebeat/stdout_file.yml
.....
#输入,回车后,输出如下
{"name" : "wangxiaochun", "age" : "18", "phone" : "0123456789" }
[root@elk-web1 ~]#cat /tmp/filebeat.log
{"@timestamp":"2022-08-01T13:53:48.259Z","@metadata":
{"beat":"filebeat","type":"_doc","version":"7.17.5"},"host":
{"name":"ubuntu2004.wang.org"},"agent":
{"hostname":"ubuntu2004.wang.org","ephemeral_id":"e17c1494-889d-49fb-b3d7-
5cb573b1f152","id":"d1fdb707-5e4f-47b3-944b-
8f6d1477190a","name":"ubuntu2004.wang.org","type":"filebeat","version":"7.17.5"}
,"ecs":{"version":"1.12.0"},"log":{"offset":0,"file":{"path":""}},"json":
{},"message":"","input":{"type":"stdin"}}
#Json格式整理
[root@elk-web1 ~]#apt -y install jq
[root@elk-web1 ~]#cat /tmp/filebeat.log  | jq
{
"@timestamp": "2022-08-01T13:42:23.524Z",
"@metadata": {
"beat": "filebeat",
"type": "_doc",
"version": "7.17.5"
  },
"input": {
"type": "stdin"
  },
"ecs": {
"version": "1.12.0"
  },
"host": {
"name": "ubuntu2004.wang.org"
  },
"agent": {
"name": "ubuntu2004.wang.org",
"type": "filebeat",
"version": "7.17.5",
"hostname": "ubuntu2004.wang.org",
"ephemeral_id": "4465f007-7cce-4a0d-981a-d34ecd8b3fc0",
"id": "d1fdb707-5e4f-47b3-944b-8f6d1477190a"
  },
"log": {
"offset": 0,
"file": {
"path": ""
    }
  },
"name": "wangxiaochun",
"age": "18",
"phone": "0123456789"
}

3.3.4 案例: 从文件读取再输出至标准输出

https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-log.html

filebeat 会将每个文件的读取数据的相关信息记录在/var/lib/filebeat/registry/filebeat/log.json文件中, 可以实现日志采集的持续性,而不会重复采集

3.3.4.1 创建配置
[root@elk-web1 ~]#vim /etc/filebeat/file.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
  - /var/log/syslog
output.console:
  pretty: true
  enable: true
3.3.4.2 执行读取
[root@elk-web1 ~]#filebeat -e -c /etc/filebeat/file.yml
......
#执行生成文件内容后echo hello,wang > /var/log/filebeat.log,可以看到下面的输出信息
{
"@timestamp": "2022-07-09T14:55:14.839Z",
"@metadata": {
"beat": "filebeat",
"type": "_doc",
"version": "7.17.5"
  },
"log": {
"offset": 0,
"file": {
"path": "/var/log/filebeat.log"
    }
  },
"message": "hello,wang",
"input": {
"type": "log"
  },
"ecs": {
"version": "1.12.0"
  },
"host": {
"name": "elk-web1"
  },
"agent": {
"name": "elk-web1",
"type": "filebeat",
"version": "7.17.5",
"hostname": "elk-web1",
"ephemeral_id": "c9b4cd1d-1a9d-4531-83ec-0a53fd532dfc",
"id": "fffb2178-8110-400c-b3f9-ce8920aeb61a"
  }
}

3.3.5 案例: 利用 Filebeat 收集系统日志到 ELasticsearch

默认生成的索引名称为 filebeat-<版本>-<时间>*

3.3.5.1 修改配置
[root@elk-web1 ~]#vim /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true           #开启日志
  paths:
  - /var/log/*            #指定收集的日志文件
#-------------------------- Elasticsearch output ------------------------------
output.elasticsearch:
  hosts: ["10.0.0.101:9200"]#指定ELK集群服务器地址和端口
3.3.5.2 启动服务
[root@elk-web1 ~]#systemctl enable --now filebeat.service
3.3.5.3 head 插件查看索引

3.3.5.4 通过 Kibana 查看收集的日志信息

3.3.6 案例: 自定义索引名称收集所有系统日志到 ELasticsearch

3.3.6.1 修改配置

范例:收集系统日志

[root@elk-web1 ~]#vi /etc/rsyslog.conf
.....
*.*  /var/log/system.log
[root@elk-web1 ~]#systemctl restart rsyslog
[root@elk-web1 ~]#vim /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true                       #开启日志
  paths:
  - /var/log/syslog.log               #指定收集的日志文件
  include_lines: ['failed','nginx']#只过滤指定包含关健字的日志
#exclude_lines: ['Debug']           #排除包含关健字的日志
#paths: /var/log/*
#exclude_files: ['.gz$']            #排除文件名包含关健字的日志文件
output.elasticsearch:
  hosts: ["10.0.0.101:9200"]#指定ES集群服务器地址和端口
  index: "wang-%{[agent.version]}-%{+yyyy.MM.dd}"#自定义索引名称
setup.ilm.enabled: false #关闭索引生命周期ilm功能,默认开启时索引名称只能为filebeat-*
setup.template.name: "wang"#定义模板名称,要自定义索引名称,必须指定此项,否则无法启动
setup.template.pattern: "wang-*"#定义模板的匹配索引名称,要自定义索引名称,必须指定此项,否
则无法启动
#默认情况下 Filebeat 写入到 ES 的索引分片为1,如果需要修订分片,可以通过如下实现
#注意:如果模板已经存在,需要利用插件先删除模板和索引才能生效
setup.template.settings:
  index.number_of_shards: 3
  index.number_of_replicas: 0

范例: 收集Nginx的访问日志

[root@elk-web1 ~]#vim /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true#开启日志
  paths:
- /var/log/nginx/access.log               #指定收集的日志文件
output.elasticsearch:
  hosts: ["10.0.0.101:9200"]        #指定ES集群服务器地址和端口
  index: "nginx-access-%{[agent.version]}-%{+yyyy.MM.dd}"#自定义索引名称
setup.ilm.enabled: false
setup.template.name: "nginx"#定义模板名称,要自定义索引名称,必须指定此项,否则无法启动
setup.template.pattern: "nginx-*"#定义模板的匹配索引名称,要自定义索引名称,必须指定此项,
否则无法启动
3.3.6.2 启动服务
[root@elk-web1 ~]#systemctl enable --now filebeat.service
3.3.6.3 插件查看索引

3.3.6.4 通过kibana查看收集的日志信息

3.3.7 案例: 利用 Filebeat 收集 Nginx Json 格式日志到 Elasticsearch

官方文档

https://www.elastic.co/guide/en/beats/filebeat/7.6/filebeat-input-log.html
https://www.elastic.co/guide/en/beats/filebeat/7.6/redis-output.html

生产环境中我们经常需要获取Web访问用户的信息,比如:来源的IP是哪个地域,网站的PV、UV、状态码、访问时间等等;所以需要收集的Nginx访问日志

3.3.7.1 安装 nginx 配置访问日志使用 Json格式
#修改nginx访问日志为Json格式
[root@elk-web1 ~]#vim /etc/nginx/nginx.conf
    log_format access_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"uri":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"tcp_xff":"$proxy_protocol_addr",'
'"http_user_agent":"$http_user_agent",'
'"status":"$status"}';
    access_log  /var/log/nginx/access_json.log access_json ;
......
#默认开启nginx的错误日志,但如果是ubuntu,还需要修改下面行才能记录错误日志
[root@elk-web1 ~]#vim /etc/nginx/sites-available/default
    location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
#try_files $uri $uri/ =404; #将此行注释
[root@elk-web1 ~]#systemctl restart nginx
[root@elk-web1 ~]#ll /var/log/nginx/
total 1012
-rw-r--r--1 root root 1029780 Aug 2515:34 access_json.log
-rw-r--r--1 root root     196 Aug 2515:34 error.log
#用浏览器访问几次,包括404等错误访问,查看日志是否记录
[root@elk-web1 ~]#tail  /var/log/nginx/access_json.log
{"@timestamp":"2022-07-
10T14:07:47+00:00","host":"10.0.0.104","clientip":"10.0.0.1","size":3543,"respon
setime":0.000,"upstreamtime":"-","upstreamhost":"-
","http_host":"10.0.0.104","uri":"/index.html","domain":"10.0.0.104","xff":"-
","referer":"-","tcp_xff":"-","http_user_agent":"Mozilla/5.0 (Windows NT 10.0;
Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114
Safari/537.36 Edg/103.0.1264.49","status":"200"}
{"@timestamp":"2022-07-
10T14:07:47+00:00","host":"10.0.0.104","clientip":"10.0.0.1","size":197,"respons
etime":0.000,"upstreamtime":"-","upstreamhost":"-
","http_host":"10.0.0.104","uri":"/icons/ubuntu-
logo.png","domain":"10.0.0.104","xff":"-
","referer":"http://10.0.0.104/","tcp_xff":"-","http_user_agent":"Mozilla/5.0
(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.49","status":"404"}
[root@elk-web1 ~]#tail  /var/log/nginx/error.log
2022/07/10 14:07:47 [error] 63684#63684: *1 open() "/var/www/html/icons/ubuntu-
logo.png" failed (2: No such file or directory), client: 10.0.0.1, server: _,
request: "GET /icons/ubuntu-logo.png HTTP/1.1", host: "10.0.0.104", referrer:
"http://10.0.0.104/"
2022/07/10 14:07:47 [error] 63684#63684: *1 open() "/var/www/html/favicon.ico"
failed (2: No such file or directory), client: 10.0.0.1, server: _, request: "GET
/favicon.ico HTTP/1.1", host: "10.0.0.104", referrer: "http://10.0.0.104/"
2022/07/10 14:07:47 [error] 63684#63684: *1 open() "/var/www/html/icons/ubuntu-
logo.png" failed (2: No such file or directory), client: 10.0.0.1, server: _,
request: "GET /icons/ubuntu-logo.png HTTP/1.1", host: "10.0.0.104", referrer:
"http://10.0.0.104/"
2022/07/10 14:07:47 [error] 63684#63684: *1 open() "/var/www/html/favicon.ico"
failed (2: No such file or directory), client: 10.0.0.1, server: _, request: "GET
/favicon.ico HTTP/1.1", host: "10.0.0.104", referrer: "http://10.0.0.104/"
3.3.7.2 修改 Filebeat 配置文件
[root@elk-web1 ~]#cat  /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
- /var/log/nginx/access_json.log
  json.keys_under_root: true#默认false会将全部数据存储至message字段,改为true则会以
Json格式存储
  json.overwrite_keys: true#设为true,覆盖默认的message字段,使用自定义json格式中的key
  tags: ["nginx-access"]           #指定tag,用于分类
- type: log
  enabled: true
  paths:
- /var/log/nginx/error.log
  tags: ["nginx-error"]
output.elasticsearch:
  hosts: ["10.0.0.101:9200","10.0.0.102:9200","10.0.0.103:9200"]
  indices:
- index: "nginx-access-%{[agent.version]}-%{+yyy.MM.dd}"
      when.contains:
        tags: "nginx-access"#如果记志中有access的tag,就记录到nginx-access的索引中
- index: "nginx-error-%{[agent.version]}-%{+yyy.MM.dd}"
      when.contains:
        tags: "nginx-error"#如果记志中有error的tag,就记录到nginx-error的索引中
setup.ilm.enabled: false#关闭索引生命周期ilm功能,默认开启时索引名称只能为filebeat-*
setup.template.name: "nginx"#定义模板名称,要自定义索引名称,必须指定此项,否则无法启动
setup.template.pattern: "nginx-*"#定义模板的匹配索引名称,要自定义索引名称,必须指定此项,
否则无法启动
[root@elk-web1 ~]#systemctl restart filebeat.service
3.3.7.3 插件查看索引

3.3.7.4 在 Kibana 验证日志数据

创建索引模式

查看索引

3.3.8 案例: 利用 Filebeat 收集 Tomat 的 Json 格式的访问日志到 Elasticsearch

3.3.8.1 安装 Tomcat 并配置使用 Json 格式的访问日志
#安装Tomcat,包安装或二进制安装
[root@ubuntu2004 ~]#apt -y install tomcat9 tomcat9-admin
[root@ubuntu2004 ~]#ll /var/lib/tomcat9/
total 20
drwxr-xr-x  5 root   root   4096 Aug  310:55 ./
drwxr-xr-x 44 root   root   4096 Aug  310:55 ../
lrwxrwxrwx  1 root   root     12 Jul 2102:09 conf -> /etc/tomcat9/
drwxr-xr-x  2 tomcat tomcat 4096 Jul 2102:09 lib/
lrwxrwxrwx  1 root   root     17 Jul 2102:09 logs -> ../../log/tomcat9/
drwxr-xr-x  2 root   root   4096 Aug  310:55 policy/
drwxrwxr-x  3 tomcat tomcat 4096 Aug  310:55 webapps/
lrwxrwxrwx  1 root   root     19 Jul 2102:09 work -> ../../cache/tomcat9/
[root@ubuntu2004 ~]#ll /var/lib/tomcat9/webapps/
total 12
drwxrwxr-x 3 tomcat tomcat 4096 Aug  310:55 ./
drwxr-xr-x 5 root   root   4096 Aug  310:55 ../
drwxr-xr-x 3 root   root   4096 Aug  310:55 ROOT/
[root@ubuntu2004 ~]#ls /etc/tomcat9/
Catalina  catalina.properties  context.xml  jaspic-providers.xml
logging.properties  policy.d  server.xml  tomcat-users.xml  web.xml
#修改 Tomcat 的访问日志为Json格式
[root@elk-web1 ~]#vim /usr/local/tomcat/conf/server.xml
[root@ubuntu2004 ~]#vim /etc/tomcat9/server.xml
.......
<Valve className="org.apache.catalina.valves.AccessLogValve"directory="logs"
prefix="localhost_access_log"suffix=".txt"
########################添加下面行,注意是一行,不要换行
#####################################
pattern="
{&quot;clientip&quot;:&quot;%h&quot;,&quot;ClientUser&quot;:&quot;%l&quot;,&quot
;authenticated&quot;:&quot;%u&quot;,&quot;AccessTime&quot;:&quot;%t&quot;,&quot;
method&quot;:&quot;%r&quot;,&quot;status&quot;:&quot;%s&quot;,&quot;SendBytes&qu
ot;:&quot;%b&quot;,&quot;Query?
string&quot;:&quot;%q&quot;,&quot;partner&quot;:&quot;%
{Referer}i&quot;,&quot;AgentVersion&quot;:&quot;%{User-Agent}i&quot;}"/>
######################################################################
      </Host>
    </Engine>
  </Service>
</Server>
[root@elk-web1 ~]#systemctl restart tomcat
#访问几次tomcat的页面,可以看到如下的Json格式日志
[root@elk-web1 ~]#tail -n1 /usr/local/tomcat/logs/localhost_access_log.2022-07-
11.txt
{"clientip":"10.0.0.1","ClientUser":"-","authenticated":"-","AccessTime":"
[11/Jul/2022:14:33:22 +0000]","method":"GET /
HTTP/1.1","status":"200","SendBytes":"11230","Query?string":"","partner":"-
","AgentVersion":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.49"}
3.3.8.2 修改 Filebeat 配置文件
[root@elk-web1 ~]#cat /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
- /usr/local/tomcat/logs/localhost_access_log.*
  json.keys_under_root: true#默认False会将json数据存储至message,改为true则会独立
message外存储
  json.overwrite_keys: false#设为true,覆盖默认的message字段,使用自定义json格式中的
key
  tags: ["tomcat-access"]
- type: log
  enabled: true
  paths:
- /usr/local/tomcat/logs/catalina.*
  tags: ["tomcat-error"]
output.elasticsearch:
  hosts: ["10.0.0.101:9200"]        #指定ELK集群服务器地址和端口
  indices:
- index: "tomcat-access-%{[agent.version]}-%{+yyy.MM.dd}"
      when.contains:
        tags: "tomcat-access"
- index: "tomcat-error-%{[agent.version]}-%{+yyy.MM.dd}"
      when.contains:
        tags: "tomcat-error"
setup.ilm.enabled: false
setup.template.name: "tomcat"
setup.template.pattern: "tomcat-*"

3.38.3 插件查看索引

3.3.8.4 通过 Kibana 查看收集的日志信息

创建访问日志的索引模式

创建错误日志的索引模式

查看访问日志索引

选中agent.name字段

只显示指定字段,所以可以将多个tomcat主机的日志合并成一个索引,利用,再利用此字段区别不同的主机

查看错误日志索引

3.3.9 案例: 利用 Filebeat 收集 Tomat 的多行错误日志到 Elasticsearch

3.3.9.1 Tomcat 错误日志解析

Tomcat 是 Java 应用,当只出现一个错误时,会显示很多行的错误日志,如下所示

[root@ubuntu2004 ~]#tail  /usr/local/tomcat/logs/catalina.out
12-Jul-202114:05:58.190 WARNING [main]
org.apache.catalina.startup.Catalina.parseServerXml Unable to load server
configuration from [/usr/local/apache-tomcat-9.0.64/conf/server.xml]
    org.xml.sax.SAXParseException; systemId: file:/usr/local/apache-tomcat-
8.5.61/conf/server.xml; lineNumber: 22; columnNumber: 1; Content is not allowed
in prolog.
        at
com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXPa
rser.java:1243)
        at
com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXPar
serImpl.java:644)
        at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1535)
        at
org.apache.catalina.startup.Catalina.parseServerXml(Catalina.java:617)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:709)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:746)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav
a:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:305)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:475)
12-Jul-202114:05:58.191 SEVERE [main]
org.apache.catalina.startup.Catalina.start Cannot start server, server instance
is not configured

多个行其实是同一个事件的日志的内容,而ES是根据每一行来区别不同的日志

可以将多个行合并成一个日志来解决此问题

官方文档

https://www.elastic.co/guide/en/beats/filebeat/7.0/multiline-examples.html

3.3.9.2 安装 Tomcat 并配置
#安装Tomcat
略
#修改 Tomcat 的访问日志格式为 Json
[root@elk-web1 ~]#vim /usr/local/tomcat/conf/server.xml
.......
<Valve className="org.apache.catalina.valves.AccessLogValve"directory="logs"
prefix="localhost_access_log"suffix=".txt"
########################添加下面行,注意是一行,不要换行
#####################################
pattern="
{&quot;clientip&quot;:&quot;%h&quot;,&quot;ClientUser&quot;:&quot;%l&quot;,&quot
;authenticated&quot;:&quot;%u&quot;,&quot;AccessTime&quot;:&quot;%t&quot;,&quot;
method&quot;:&quot;%r&quot;,&quot;status&quot;:&quot;%s&quot;,&quot;SendBytes&qu
ot;:&quot;%b&quot;,&quot;Query?
string&quot;:&quot;%q&quot;,&quot;partner&quot;:&quot;%
{Referer}i&quot;,&quot;AgentVersion&quot;:&quot;%{User-Agent}i&quot;}"/>
######################################################################
      </Host>
    </Engine>
  </Service>
</Server>
[root@elk-web1 ~]#systemctl restart tomcat
3.3.9.3 修改 Filebeat 配置文件
[root@elk-web1 ~]#cat /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
- /usr/local/tomcat/logs/localhost_access_log.*
  json.keys_under_root: true
  json.overwrite_keys: false
  tags: ["tomcat-access"]
- type: log
  enabled: true
  paths:
- /usr/local/tomcat/logs/catalina.*.log
  tags: ["tomcat-error"]
  multiline.type: pattern           #此为默认值,可省略
  multiline.pattern: '^[0-3][0-9]-'#正则表达式匹配以两位,或者为'^\d{2}'
  multiline.negate: true
  multiline.match: after
  multiline.maxlines: 10000#默认只合并500行,指定最大合并1万行
output.elasticsearch:
  hosts: ["10.0.0.101:9200"]
  indices:
- index: "tomcat-access-%{[agent.version]}-%{+yyy.MM.dd}"
      when.contains:
        tags: "tomcat-access"
  • index: "tomcat-error-%{[agent.version]}-%{+yyy.MM.dd}"

  • when.contains:

        tags: "tomcat-error"
setup.ilm.enabled: false
setup.template.name: "tomcat"
setup.template.pattern: "tomcat-*"
3.3.9.4 插件查看索引

3.3.9.5 通过 Kibana 查看收集的日志信息

创建访问日志的索引模式

创建错误日志的索引模式

查看错误索引,可以看到多行合并为一个日志

3.3.10 案例: 从标准输入读取再输出至 Logstash

[root@elk-web1 ~]#vim /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: stdin
  enabled: true
output.logstash:
  hosts: ["10.0.0.104:5044","10.0.0.105:5044"]
  index: filebeat
  loadbalance: true#默认为false,只随机输出至一个可用的logstash,设为true,则输出至全部
logstash
  worker: 1#线程数量
  compression_level: 3#压缩比

3.3.11 案例: 利用 Filebeat 收集 Nginx 日志到 Redis

官方文档

https://www.elastic.co/guide/en/beats/filebeat/7.6/filebeat-input-log.html
https://www.elastic.co/guide/en/beats/filebeat/7.6/redis-output.html

生产环境中我们经常需要获取Web访问用户的信息,比如:来源的IP是哪个地域,网站的PV、UV、状态码、访问时间等等;所以需要收集的Nginx访问日志

将 filebeat收集的日志,发送至Redis 格式如下

output.redis:
  hosts: ["localhost:6379"]
  password: "my_password"
  key: "filebeat"
  db: 0
  timeout: 5
output.redis:
  hosts: ["10.0.0.105:6379"]
  password: "123456"
  db: "0"
  key: "filebeat"#所有日志都存放在key名称为filebeat的列表中,llen filebeat可查看长度,
即日志记录数
#keys: #也可以用下面的不同日志存放在不同的key的形式
#  - key: "nginx_access"
#    when.contains:
#    tags: "access"
#  - key: "nginx_error"
#    when.contains:
#    tags: "error"
3.3.11.1 安装 Nginx 配置访问日志使用 Json格式
[root@centos8 ~]#vim /etc/nginx/nginx.conf
.....
    log_format access_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"uri":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"tcp_xff":"$proxy_protocol_addr",'
'"http_user_agent":"$http_user_agent",'
'"status":"$status"}';
    access_log  /var/log/nginx/access_json.log access_json ;
......
[root@centos8 ~]#ll /var/log/nginx/
total 1012
-rw-r--r--1 root root 1029780 Aug 2515:34 access_json.log
-rw-r--r--1 root root     196 Aug 2515:34 error.log
[root@centos8 ~]#tail -n1  /var/log/nginx/access_json.log
{"@timestamp":"2021-04-
21T03:05:14+08:00","host":"172.17.180.135","clientip":"103.229.183.40","size":47
89,"responsetime":0.047,"upstreamtime":"0.046","upstreamhost":"127.0.0.1:9000","
http_host":"www.wangxiaochun.com","uri":"/index.php","domain":"www.wangxiaochun.
com","xff":"-","referer":"-","tcp_xff":"","http_user_agent":"python-
requests/2.25.1","status":"200"}
3.3.11.2 安装和配置 Redis
[root@ubuntu1804 ~]#apt -y install redis
[root@ubuntu1804 ~]#sed -i.bak '/^bind.*/c bind 0.0.0.0'  /etc/redis/redis.conf
[root@ubuntu1804 ~]#systemctl restart  redis
3.3.11.3 修改 Filebeat 配置文件
[root@centos8 ~]#cat  /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
- /var/log/nginx/access_json.log
  json.keys_under_root: true#默认False会将json数据存储至message,改为true则会独立
message外存储
  json.overwrite_keys: true#设为true,覆盖默认的message字段,使用自定义json格式中的key
  tags: ["nginx-access"]
- type: log
  enabled: true
  paths:
- /var/log/nginx/error.log
  tags: ["nginx-error"]
output.redis:
  hosts: ["10.0.0.104:6379"]
  key: "filebeat"
#password: "123456"
#db: 0
[root@centos8 ~]#systemctl restart filebeat.service
3.3.11.4 在 Redis 验证日志数据
[root@ubuntu1804 ~]#redis-cli
127.0.0.1:6379> keys *
1) "filebeat"
127.0.0.1:6379> type filebeat
list
127.0.0.1:6379> llen filebeat
(integer) 2097
127.0.0.1:6379> LINDEX filebeat 2096
"{\"@timestamp\":\"2021-08-25T07:57:46.000Z\",\"@metadata\":
{\"beat\":\"filebeat\",\"type\":\"_doc\",\"version\":\"7.6.2\"},\"http_user_agen
t\":\"curl/7.58.0\",\"upstreamhost\":\"-\",\"input\":
{\"type\":\"log\"},\"agent\":{\"type\":\"filebeat\",\"ephemeral_id\":\"04ea5e3e-
e79f-47c0-8947-
d9c84057d4f6\",\"hostname\":\"centos8.wang.org\",\"id\":\"308f47e9-779a-4f44-
8dfc-
a3fe2d12b844\",\"version\":\"7.6.2\"},\"size\":3971,\"uri\":\"/404.html\",\"doma
in\":\"10.0.0.8\",\"referer\":\"-\",\"upstreamtime\":\"-\",\"xff\":\"-
\",\"http_host\":\"10.0.0.8\",\"tags\":[\"nginx-access\"],\"log\":
{\"offset\":1030081,\"file\":
{\"path\":\"/var/log/nginx/access_json.log\"}},\"host\":
{\"name\":\"centos8.wang.org\"},\"status\":\"404\",\"responsetime\":0,\"ecs\":
{\"version\":\"1.4.0\"},\"clientip\":\"10.0.0.101\",\"tcp_xff\":\"\"}"
127.0.0.1:6379> LINDEX filebeat 2095
"{\"@timestamp\":\"2021-08-25T07:57:55.179Z\",\"@metadata\":
{\"beat\":\"filebeat\",\"type\":\"_doc\",\"version\":\"7.6.2\"},\"log\":
{\"file\":
{\"path\":\"/var/log/nginx/error.log\"},\"offset\":402},\"message\":\"2021/08/25
15:57:46 [error] 24983#0: *3 open() \\\"/usr/share/nginx/html/error2.html\\\"
failed (2: No such file or directory), client: 10.0.0.101, server: _, request:
\\\"GET /error2.html HTTP/1.1\\\", host: \\\"10.0.0.8\\\"\",\"tags\":[\"nginx-
error\"],\"input\":{\"type\":\"log\"},\"ecs\":{\"version\":\"1.4.0\"},\"host\":
{\"name\":\"centos8.wang.org\"},\"agent\":{\"id\":\"308f47e9-779a-4f44-8dfc-
a3fe2d12b844\",\"version\":\"7.6.2\",\"type\":\"filebeat\",\"ephemeral_id\":\"04
ea5e3e-e79f-47c0-8947-d9c84057d4f6\",\"hostname\":\"centos8.wang.org\"}}"
127.0.0.1:6379>

3.3.12 案例: 从标准输入读取再输出至 Kafka

[root@elk-web1 ~]#vim /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: stdin
  enabled: true
output.kafka:
  hosts: ["10.0.0.201:9092", "10.0.0.202:9092", "10.0.0.203:9092"]
  topic: filebeat-log   #指定kafka的topic
  partition.round_robin:
    reachable_only: true#true表示只发布到可用的分区,false时表示所有分区,如果一个节点
down,会block
  required_acks: 1#如果为0,错误消息可能会丢失,1等待写入主分区(默认),-1等待写入副本分
区
  compression: gzip
  max_message_bytes: 1000000#每条消息最大长度,以字节为单位,如果超过将丢弃

4 Logstash 过滤

4.1 Logstash 介绍

Logstash 是免费且开放的服务器端数据处理管道,能够从多个来源采集数据,转换数据,然后将数据发送到您最喜欢的“存储库”中

Logstash 可以水平伸缩,而且logstash是整个ELK中拥有最多插件的一个组件

Losgtash 基于 Ruby 语言开发

Logstash 主要功能:

输入 Input:用于日志收集,常见插件: Stdin、File、Kafka、Redis、Filebeat、Http 过滤 Filter:日志过滤和转换,常用插件: grok、date、geoip、mutate、useragent 输出 Output:将过滤转换过的日志输出, 常见插件: File,Stdout,Elasticsearch,MySQL,Redis,Kafka

Logstash 官网:

https://www.elastic.co/cn/logstash/

Logstash 官方下载链接:

https://www.elastic.co/cn/downloads/logstash
https://www.elastic.co/cn/downloads/past-releases#logstash

Logstash 官方说明

https://www.elastic.co/guide/en/logstash/7.6/index.html

4.2 Logstash 安装

4.2.1 环境准备安装 Java 环境

4.2.1.1 Ubuntu 环境准备

[root@logstash ~]#apt -y install openjdk-11-jdk
[root@logstash ~]#apt -y install openjdk-8-jdk
4.2.1.2 CentOS 环境准备

关闭防火墙和 SELinux

[root@logstash ~]# systemctl disable --now firewalld
[root@logstash ~]# sed -i '/SELINUX/s/enforcing/disabled/' /etc/selinux/config

安装 Java 环境

#安装oracle 的JDK
[root@logstash ~]# yum install jdk-8u121-linux-x64.rpm
[root@logstash ~]# java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
#或者安装OpenJDK
[root@logstash ~]# yum -y install java-1.8.0-openjdk
[root@logstash ~]# java -version
openjdk version "1.8.0_302"
OpenJDK Runtime Environment (build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM (build 25.302-b08, mixed mode)

4.2.2 安装 Logstash

注意: Logstash 版本要和 Elasticsearch 相同的版本,否则可能会出错

镜像网站下载链接

https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x
4.2.2.1 Ubuntu 安装 Logstash
[root@logstash ~]#wget
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/apt/pool/main/l/logstash/l
ogstash-7.6.2-amd64.deb
[root@logstash ~]#dpkg -i logstash-7.6.2-amd64.deb
Selecting previously unselected package logstash.
(Reading database ... 74411 files and directories currently installed.)
Preparing to unpack logstash-7.6.2.deb ...
Unpacking logstash (1:7.6.2-1) ...
Setting up logstash (1:7.6.2-1) ...
Using provided startup.options file: /etc/logstash/startup.options
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in
version 9.0 and will likely be removed in a future release.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.headius.backport9.modules.Modules to
method sun.nio.ch.NativeThread.signal(long)
WARNING: Please consider reporting this to the maintainers of
com.headius.backport9.modules.Modules
WARNING: Use --illegal-access=warn to enable warnings of further illegal
reflective access operations
WARNING: All illegal access operations will be denied in a future release
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/pleaserun-
0.0.30/lib/pleaserun/platform/base.rb:112: warning: constant ::Fixnum is
deprecated
Successfully created system startup script for Logstash
4.2.2.2 RHEL系列安装 Logstash
[root@logstash ~]#wget
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/yum/7.6.2/logstash-
7.6.2.rpm
[root@logstash ~]#yum install logstash-7.6.2.rpm
[root@logstash ~]#chown logstash.logstash /usr/share/logstash/data/queue –R #权限
更改为logstash用户和组,否则启动的时候日志报错
4.2.2.3 修改 Logstash 配置
[root@logstash ~]#vim /etc/logstash/logstash.yml
[root@logstash ~]#grep -Ev '#|^$' /etc/logstash/logstash.yml
node.name: logstash-node01
pipeline.workers: 2
pipeline.batch.size: 1000#批量写入的消息个数,可以根据ES的性能做性能优化
pipeline.batch.delay: 5#批量写入的延时,可以根据ES的性能做性能优化
path.data: /var/lib/logstash #默认值
path.logs: /var/log/logstash #默认值
#内存优化
[root@logstash ~]#vim /etc/logstash/jvm.options
-Xms1g
-Xmx1g
#Logstash默认以logstash用户运行,如果logstash需要收集本机的日志,可能会有权限问题,可以修改为
root
[root@logstash ~]#vim /etc/systemd/system/logstash.service
[Service]
User=root
Group=root
[root@logstash ~]#systemctl daemon-reload;systemctl restart logstash

4.3 Logstash 使用

4.3.1 Logstash 命令

官方文档

https://www.elastic.co/guide/en/logstash/current/first-event.html
#各种插件
https://www.elastic.co/guide/en/logstash/7.6/input-plugins.html
https://www.elastic.co/guide/en/logstash/7.6/filter-plugins.html
https://www.elastic.co/guide/en/logstash/7.6/output-plugins.html

范例: 查看帮助

[root@logstash ~]#/usr/share/logstash/bin/logstash --help
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in
version 9.0 and will likely be removed in a future release.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.headius.backport9.modules.Modules
(file:/usr/share/logstash/logstash-core/lib/jars/jruby-complete-9.2.9.0.jar) to
method sun.nio.ch.NativeThread.signal(long)
WARNING: Please consider reporting this to the maintainers of
com.headius.backport9.modules.Modules
WARNING: Use --illegal-access=warn to enable warnings of further illegal
reflective access operations
WARNING: All illegal access operations will be denied in a future release
WARNING: Could not find logstash.yml which is typically located in
$LS_HOME/config or /etc/logstash. You can specify the path using --
path.settings. Continuing using the defaults
Usage:
    bin/logstash [OPTIONS]
Options:
-n, --node.name NAME          Specify the name of this logstash instance, if
no value is given
                                  it will default to the current hostname.
                                   (default: "logstash.wang.org")
-f, --path.config CONFIG_PATH Load the logstash config from a specific file
                                  or directory.  If a directory is given, all
                                  files in that directory will be concatenated
in lexicographical order and then parsed as a
                                  single config file. You can also specify
                                  wildcards (globs) and any matched files will
                                  be loaded in the order described above.
-e, --config.string CONFIG_STRING Use the given string as the configuration
                                  data. Same syntax as the config file. If no
                                  input is specified, then the following is
                                  used as the default input:
"input { stdin { type => stdin } }"
                                  and if no output is specified, then the
                                  following is used as the default output:
"output { stdout { codec => rubydebug } }"
                                  If you wish to use both defaults, please use
                                  the empty string for the '-e' flag.
                                   (default: nil)
--field-reference-parser MODE (DEPRECATED) This option is no longer
                                  configurable.
                                  Use the given MODE when parsing field
                                  references.
                                  The field reference parser is used to expand
                                  field references in your pipeline configs,
                                  and has become more strict to better handle
                                  ambiguous- and illegal-syntax inputs.
                                  The only available MODE is:
-`STRICT`: parse in a strict manner; when
                                     given ambiguous- or illegal-syntax input,
                                     raises a runtime exception that should
                                     be handled by the calling plugin.
                                   (default: "STRICT")
--modules MODULES             Load Logstash modules.
                                  Modules can be defined using multiple
instances
'--modules module1 --modules module2',
                                     or comma-separated syntax
'--modules=module1,module2'
                                  Cannot be used in conjunction with '-e' or '-
f'
                                  Use of '--modules' will override modules
declared
in the 'logstash.yml' file.
-M, --modules.variable MODULES_VARIABLE Load variables for module template.
                                  Multiple instances of '-M' or
'--modules.variable' are supported.
                                  Ignored if'--modules' flag is not used.
                                  Should be in the format of
'-M
"MODULE_NAME.var.PLUGIN_TYPE.PLUGIN_NAME.VARIABLE_NAME=VALUE"'
                                  as in
'-M
"example.var.filter.mutate.fieldname=fieldvalue"'
--setup                       Load index template into Elasticsearch, and
saved searches,
                                  index-pattern, visualizations, and dashboards
into Kibana when
                                  running modules.
                                   (default: false)
--cloud.id CLOUD_ID           Sets the elasticsearch and kibana host
settings for
                                  module connections in Elastic Cloud.
                                  Your Elastic Cloud User interface or the Cloud
support
                                  team should provide this.
                                  Add an optional label prefix '<label>:' to
help you
                                  identify multiple cloud.ids.
e.g.
'staging:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRub3RhcmVhbCRpZGVudGlmaWVy'
--cloud.auth CLOUD_AUTH Sets the elasticsearch and kibana username and
password
for module connectionsin Elastic Cloud
e.g.'username:<password>'
--pipeline.id ID Sets the ID of the pipeline.
(default:"main")
-w, --pipeline.workers COUNT Sets the number of pipeline workers to run.
(default:2)
--java-execution Use Java execution engine.
(default:true)
--plugin-classloaders (Beta) Load Java pluginsin independent
classloaders to isolate their dependencies.
(default:false)
-b, --pipeline.batch.size SIZE Size of batches the pipeline is to workin.
(default:125)
-u, --pipeline.batch.delay DELAY_IN_MS When creating pipeline batches, how
long to waitwhile polling
for the next event.
(default:50)
--pipeline.unsafe_shutdown Force logstash toexit during shutdown even
if there are still inflight eventsin memory.
By default, logstash will refuse to quituntil
all
received events have been pushed to the
outputs.
(default:false)
--path.data PATH This should point to a writable directory.
Logstash
will use this directory whenever it needs to
store
data. Plugins will also have access to this
path.
(default:"/usr/share/logstash/data")
-p, --path.plugins PATH A path of where tofind plugins. This flag
can be given multiple times to include
multiple paths. Plugins are expected to be
in a specific directory hierarchy:
'PATH/logstash/TYPE/NAME.rb' where TYPE is
'inputs' 'filters', 'outputs' or'codecs'
and NAME is the name of the plugin.
(default: [])
-l, --path.logs PATH Write logstash internal logs to the given
file. Without this flag, logstash will emit
logs to standard output.
(default:"/usr/share/logstash/logs")
--log.level LEVEL Set the log levelfor logstash. Possible
values are:
- fatal
- error
- warn
- info
- debug
- trace
(default:"info")
--config.debug Print the compiled config ruby code out as a
debug log (you must also have--log.level=debug enabled).
                                  WARNING: This will include any 'password'
options passed to plugin configs as plaintext, and may result
in plaintext passwords appearing in your logs!
                                   (default: false)
-i, --interactive SHELL       Drop to shell instead of running as normal.
                                  Valid shells are "irb" and "pry"
-V, --version                 Emit the version of logstash and its friends,
thenexit.
-t, --config.test_and_exit    Check configuration for valid syntax and then
exit.
                                   (default: false)
-r, --config.reload.automatic Monitor configuration changes and reload
                                  whenever it is changed.
                                  NOTE: use SIGHUP to manually reload the config
                                   (default: false)
--config.reload.interval RELOAD_INTERVAL How frequently to poll the
configuration location
for changes, in seconds.
                                   (default: 3000000000)
--http.host HTTP_HOST         Web API binding host (default: "127.0.0.1")
--http.port HTTP_PORT         Web API http port (default: 9600..9700)
--log.format FORMAT           Specify if Logstash should write its own logs
in JSON form (one
                                  event per line) or in plain text (using Ruby's
Object#inspect)
                                   (default: "plain")
--path.settings SETTINGS_DIR  Directory containing logstash.yml file. This
can also be
set through the LS_SETTINGS_DIR environment
variable.
                                   (default: "/usr/share/logstash/config")
--verbose                     Set the log level to info.
                                  DEPRECATED: use --log.level=info instead.
--debug                       Set the log level to debug.
                                  DEPRECATED: use --log.level=debug instead.
--quiet                       Set the log level to info.
                                  DEPRECATED: use --log.level=info instead.
-h, --help                    print help
#常用选项
-e指定配置内容
-f指定配置文件
-t语法检查
-r修改配置文件,自动加载生效
#服务方式启动,由于默认没有配置文件,所以无法启动
[root@logstash ~]#systemctl start logstash

各种插件帮助

https://www.elastic.co/guide/en/logstash/current/index.html

范例: 列出所有插件

[root@logstash ~]#/usr/share/logstash/bin/logstash-plugin list

Github logstash插件链接

https://github.com/logstash-plugins

4.3.2 Logstash 输入 Input 插件

官方链接

https://www.elastic.co/guide/en/logstash/7.6/input-plugins.html
4.3.2.1 标准输入

范例: 交互式实现

#标准输入和输出,codec => rubydebug指输出格式,是默认值,可以省略
[root@logstash ~]#/usr/share/logstash/bin/logstash  -e 'input { stdin{} } output
{ stdout{ codec => rubydebug }}'
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in
version 9.0 and will likely be removed in a future release.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.headius.backport9.modules.Modules
(file:/usr/share/logstash/logstash-core/lib/jars/jruby-complete-9.2.9.0.jar) to
method sun.nio.ch.NativeThread.signal(long)
WARNING: Please consider reporting this to the maintainers of
com.headius.backport9.modules.Modules
WARNING: Use --illegal-access=warn to enable warnings of further illegal
reflective access operations
WARNING: All illegal access operations will be denied in a future release
WARNING: Could not find logstash.yml which is typically located in
$LS_HOME/config or /etc/logstash. You can specify the path using --
path.settings. Continuing using the defaults
Could not find log4j2 configuration at path
/usr/share/logstash/config/log4j2.properties. Using default config which logs
errors to the console
[WARN ] 2021-01-2618:46:17.658 [LogStash::Runner] multilocal - Ignoring the
'pipelines.yml' file because modules or command line options are specified
[INFO ] 2021-01-2618:46:17.670 [LogStash::Runner] runner - Starting Logstash
{"logstash.version"=>"7.6.2"}
[INFO ] 2021-01-2618:46:19.248 [Converge PipelineAction::Create<main>]
Reflections - Reflections took 25 ms to scan 1 urls, producing 20 keys and 40
values
[WARN ] 2021-01-2618:46:19.837 [[main]-pipeline-manager] LazyDelegatingGauge -
A gauge metric of an unknown type (org.jruby.RubyArray) has been created for
key: cluster_uuids. This may result in invalid serialization.  It is recommended
to log an issue to the responsible developer/development team.
[INFO ] 2021-01-2618:46:19.844 [[main]-pipeline-manager] javapipeline -
Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>2,
"pipeline.batch.size"=>125, "pipeline.batch.delay"=>50,
"pipeline.max_inflight"=>250, "pipeline.sources"=>["config string"], :thread=>"#
<Thread:0x36c2d619 run>"}
[INFO ] 2021-01-2618:46:20.724 [[main]-pipeline-manager] javapipeline -
Pipeline started {"pipeline.id"=>"main"}
The stdin plugin is now waiting for input:
[INFO ] 2021-01-2618:46:20.799 [Agent thread] agent - Pipelines running
{:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[INFO ] 2021-01-2618:46:21.010 [Api Webserver] agent - Successfully started
Logstash API endpoint {:port=>9600}
hello world  #标准输入此字符串
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/awesome_print-
1.7.0/lib/awesome_print/formatters/base_formatter.rb:31: warning: constant
::Fixnum is deprecated
{
"@version"=> "1",                       #事件版本号,一个事件就是一个ruby对象
"@timestamp"=> 2021-01-26T10:47:49.594Z,  #当前事件的发生时间
"host"=> "logstash.wang.org",       #标记事件发生在哪里
"message"=> "hello world"#消息的具体内容
}
#后续还可继续输入其它信息,按ctrl+c退出
#指定输入信息为Json格式
[root@logstash ~]#logstash -e 'input { stdin{ codec => json } } output { stdout{
codec => rubydebug }}'
.......
 { "name":"wang","age": "18"} #输入Json格式信息
#自动解析
{
"age"=> "18",
"name"=> "wang",
"host"=> "logstash-node1.wang.org",
"@version"=> "1",
"@timestamp"=> 2022-08-03T07:04:12.194Z
}
#输入非Json格式信息,告警提示无法自动解析,存放message字段
hello,world
[WARN ] 2022-08-0315:08:06.911 [[main]<stdin] jsonlines - JSON parse error,
original data now in message field {:message=>"Unrecognized token 'hello': was
expecting ('true', 'false' or 'null')\n at [Source: (String)\"hello,world\";
line: 1, column: 6]", :exception=>LogStash::Json::ParserError,
:data=>"hello,world"}
{
"@version"=> "1",
"message"=> "hello,world",
"@timestamp"=> 2022-08-03T07:08:06.915Z,
"host"=> "logstash-node1.wang.org",
"tags"=> [
        [0] "_jsonparsefailure"
    ]
}

范例: 以配置文件实现

#配置文件
[root@logstash ~]#cat /etc/logstash/conf.d/stdin_to_stdout.conf
input {
    stdin {
        type => "stdin_type"#自定义事件类型,可用于后续判断
        tags => "stdin_tag"#自定义事件tag,可用于后续判断
        codec => "json"#指定Json 格式
    }
}
output {
    stdout {
        codec => "rubydebug"#输出格式,此为默认值,可省略
    }
}
#语法检查
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/stdin_to_stdout.conf -t
.....
Configuration OK
[INFO ] 2021-07-1218:16:23.225 [LogStash::Runner] runner - Using
config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash
#执行logstash
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/stdin_to_stdout.conf
.....
[INFO ] 2021-07-1218:19:11.069 [[main]-pipeline-manager] javapipeline -
Pipeline Java execution initialization time {"seconds"=>1.58}
[INFO ] 2021-07-1218:19:11.317 [[main]-pipeline-manager] javapipeline -
Pipeline started {"pipeline.id"=>"main"}
The stdin plugin is now waiting for input:
[INFO ] 2021-07-1218:19:11.547 [Agent thread] agent - Pipelines running
{:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
hello,wangxiaochun    #输入信息
{
"@version"=> "1",
"@timestamp"=> 2021-07-12T10:22:12.076Z,
"host"=> "logstash",
"tags"=> [
        [0] "stdin_tag"
    ],
"type"=> "stdin_type",
"message"=> "hello,wangxiaochun"
}
hello,logstash     #输入信息
{
"@version"=> "1",
"@timestamp"=> 2021-07-12T10:22:22.991Z,
"host"=> "logstash",
"tags"=> [
        [0] "stdin_tag"
    ],
"type"=> "stdin_type",
"message"=> "hello,logstash"
}
4.3.2.2 从文件输入

Logstash 会记录每个文件的读取位置,下次自动从此位置继续向后读取每个文件的读取位置记录在 /var/lib/logsstash/plugins/inputs/files/.sincedb_xxxx对应的文件中此文件包括文件的 inode号, 大小等信息

范例:

[root@logstash ~]#cat /etc/logstash/conf.d/file_to_stdout.conf
input {
    file {
        path => "/tmp/wang.*"
        type => "wanglog"#添加自定义的type字段,可以用于条件判断
        exclude => "*.txt"#排除不想采集数据的文件,基于通配符glob匹配语法
        start_position => "beginning"#第一次丛头开始读取文件,可以取值为:beginning和
end
        stat_interval => "3"#定时检查文件是否更新,默认1s
        codec => json                 #如果文件是Json格式,需要指定此项才能解析,如果不是
Json格式,却添加此行也不会影响结果
    }
    file {
        path => "/var/log/syslog"
        type => "syslog"
        start_position => "beginning"
        stat_interval => "3"
    }
}
output {
    stdout {
        codec => rubydebug
    }
}
#语法检查
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/file_to_stdout.conf -t
[root@logstash ~]#echo line1 >> /tmp/wang.log
#执行
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/file_to_stdout.conf
{
"message"=> "line1",
"@timestamp"=> 2021-07-12T10:31:42.390Z,
"host"=> "logstash",
"type"=> "syslog",
"@version"=> "1",
"path"=> "/tmp/wang.log"
}
#再追加内容到文件
[root@logstash ~]#echo line1 >> /tmp/wang.log
#可以看到logstash会输出下面内容
{
"message"=> "line2",
"@timestamp"=> 2021-07-12T10:32:51.570Z,
"host"=> "logstash",
"type"=> "syslog",
"@version"=> "1",
"path"=> "/tmp/wang.log"
}

logstash利用 sincedb 文件记录了logstash收集的记录文件的信息,比如位置,以方便下次接着从此位置继续收集日志

[root@es-node1~]# cat
/var/lib/logstash/plugins/inputs/file/.sincedb_1ced15cfacdbb0380466be84d620085a
1342198680206429465#记录了收集文件的inode和大小等信息
[root@es-node1 ~]# ll -li /elk/logs/ELK-Cluster.log
134219868-rw-r--r--1 elasticsearch elasticsearch 29465 Apr 2114:33
/elk/logs/ELK-Cluster.log
4.3.2.3 从 Http 请求买取数据
[root@logstash ~]# cat /etc/logstash/conf.d/http_to_stdout.conf
input {
    http {
        port =>6666
        codec => json
    }
}
output {
    stdout {
        codec => rubydebug
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/http_to_stdout.conf -r
.....
{
"message"=> "test log message",
"headers"=> {
"content_length"=> "0",
"http_user_agent"=> "curl/7.68.0",
"http_host"=> "logstash.wang.org:6666",
"http_version"=> "HTTP/1.1",
"request_method"=> "GET",
"http_accept"=> "*/*",
"request_path"=> "/"
    },
"@version"=> "1",
"@timestamp"=> 2022-07-14T06:38:20.626Z,
"host"=> "10.0.0.100"
}
#执行下面访问可以看到上面信息
[root@ubuntu2004 ~]#curl http://logstash.wang.org:6666
ok
[root@ubuntu2004 ~]#curl  -XPOST -d'test log message'
http://logstash.wang.org:6666
4.3.2.4 从 Filebeat 读取数据
[root@elk-web1 ~]#vim /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true#开启日志
  paths:
- /var/log/*            #指定收集的日志文件
output.logstash:
  hosts: ["10.0.0.104:5044"]
[root@logstash ~]#cat /etc/logstash/conf.d/filebeat_to_stdout.conf
input {
    beats {
       port => 5044
    }
}
output {
    stdout {
        codec => rubydebug
    }
}
4.3.2.5 从 Redis 中读取数据

支持由多个 Logstash 从 Redis 读取日志,提高性能

Logstash 从 Redis 收集完数据后,将删除对应的列表Key

官方链接:

https://www.elastic.co/guide/en/logstash/7.6/plugins-inputs-redis.html

范例:

[root@logstash ~]#cat /etc/logstash/conf.d/redis_to_stdout.conf
input {
    redis {
        host => 'Redis_IP'
        port => "6379"
        password => "123456"
        db => "0"
        data_type => 'list'
        key => "nginx-accesslog"
    }
}
output {
    stdout {
        codec => rubydebug
    }
}
4.3.2.6 从 Kafka 中读取数据

官方链接:

https://www.elastic.co/guide/en/logstash/7.6/plugins-inputs-kafka.html

范例:

[root@logstash ~]#cat /etc/logstash/conf.d/kakfa_to_stdout.conf
input {
    kafka {
        bootstrap_servers => "10.0.0.201:9092,10.0.0.202:9092,10.0.0.203:9092"
        group_id => "logstash"
        topics => ["nginx-accesslog","nginx-errorlog"]
        codec => "json"
        consumer_threads => 8
    }
}
output {
    stdout {
        codec => rubydebug
    }
}

4.3.3 Logstash 过滤 Filter 插件

数据从源传输到存储库的过程中,Logstash 过滤器能够解析各个事件,识别已命名的字段以构建结构, 并将它们转换成通用格式,以便进行更强大的分析和实现商业价值。

Logstash 能够动态地转换和解析数据,不受格式或复杂度的影响

常见的 Filter 插件:

利用 Grok 从非结构化数据中派生出结构

从 IP 地址破译出地理坐标

利用 useragent 从请求中分析操作系统、设备类型

简化整体处理,不受数据源、格式或架构的影响

官方链接

https://www.elastic.co/guide/en/logstash/7.6/filter-plugins.html
4.3.3.1 Grok 插件

4.3.3.1.1 Grok 介绍

Grok 是一个过滤器插件,可帮助您描述日志格式的结构。有超过200种 grok模式抽象概念,如IPv6地址,UNIX路径和月份名称。为了将行与格式匹配

生产环境常需要将如下非结构化的数据解析成 json 结构化数据格式

2016-09-19T18:19:00 [8.8.8.8:prd] DEBUG this is an example log message

使用 Grok 插件可以基于正则表达式技术用内置的正则表达式的别名来表示和匹配上面的日志

%{TIMESTAMP_ISO8601:timestamp} \[%{IPV4:ip};%{WORD:environment}\] %
{LOGLEVEL:log_level} %{GREEDYDATA:message}

最终转换为以下格式

{
"timestamp": "2016-09-19T18:19:00",
"ip": "8.8.8.8",
"environment": "prd",
"log_level": "DEBUG",
"message": "this is an example log message"
}

参考网站

https://www.elastic.co/cn/blog/do-you-grok-grok
http://grokdebug.herokuapp.com/
http://grokdebug.herokuapp.com/discover?#

范例: 利用grokedebug 网站将nginx日志自动生成grok的内置格式代码

58.250.250.21 -- [14/Jul/2020:15:07:27 +0800] "GET /wp-
content/plugins/akismet/_inc/form.js?ver=4.1.3 HTTP/1.1"200330
"http://www.wangxiaochun.com/?p=117""Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36""-"
#cat /var/log/nginx/access.log
10.0.0.100 -- [03/Aug/2022:16:34:17 +0800] "GET / HTTP/1.1"200612"-"
"curl/7.68.0"
%{COMBINEDAPACHELOG}

基于上面生成的代码转化为 Json 格式

或者使作Kibana 实现上面功能

、4.3.3.1.2 范例:使用 grok pattern 将 Nginx 日志格式化为 json 格式

[root@logstash ~]# cat /etc/logstash/conf.d/http_grok_stdout.conf
input {
    http {
        port =>6666
    }
}
filter {
#将nginx日志格式化为json格式
    grok {
        match => {
"message"=> "%{COMBINEDAPACHELOG}"#将message字段转化为指定的Json格式
        }
    }
}
output {
    stdout {
    codec => rubydebug
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/http_grok_stdout.conf -r
.....
{
"ident"=> "-",
"verb"=> "GET",
"@version"=> "1",
"httpversion"=> "1.1",
"message"=> "10.0.0.100 - - [14/Jul/2020:14:45:02 +0800] \"GET /
HTTP/1.1\" 200 612 \"-\" \"curl/7.68.0\"",
"host"=> "10.0.0.1",
"request"=> "/",
"auth"=> "-",
"timestamp"=> "14/Jul/2020:14:45:02 +0800",
"response"=> "200",
"referrer"=> "\"-\"",
"@timestamp"=> 2022-07-14T07:38:52.606Z,
"headers"=> {
"http_accept"=> "*/*",
"request_path"=> "/",
"http_version"=> "HTTP/1.1",
"http_host"=> "logstash.wang.org:6666",
"content_length"=> "86",
"request_method"=> "POST",
"http_user_agent"=> "insomnia/6.3.2"
    },
"agent"=> "\"curl/7.68.0\"",
"clientip"=> "10.0.0.100",
"bytes"=> "612"
}
#使用curl 或 insomnia 等工具将nginx日志发送http请求至logstash,可以看到上面的输出信息
[root@ubuntu2004 ~]#curl -XPOST -d '58.250.250.21 - - [14/Jul/2020:15:07:27
+0800] "GET /wp-content/plugins/akismet/_inc/form.js?ver=4.1.3 HTTP/1.1" 200 330
"http://www.wangxiaochun.com/?p=117" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-"'
http://logstash.wang.org:6666/
ok

范例: 直接将nginx的访问日志转化为Json格式

[root@ubuntu2004 ~]#cat /etc/logstash/conf.d/nginx_grok_stdout.conf
input {
    file {
        path => "/var/log/nginx/access.log"
        type => "nginx-accesslog"
        start_position => "beginning"
        stat_interval => "3"
    }
}
filter {
#将nginx日志格式化为json格式
    grok {
        match => {
"message"=> "%{COMBINEDAPACHELOG}"#将message字段转化为指定的Json格式
        }
    }
}
output {
    stdout {
    codec => rubydebug
    }
}
4.3.3.2 Geoip 插件

geoip 根据 ip 地址提供的对应地域信息,比如:经纬度,国家,城市名等,以方便进行地理数据分析范例:

[root@logstash ~]#cat /etc/logstash/conf.d/http_geoip_stdout.conf
input {
    http {
        port =>6666
    }
}
filter {
#将nginx日志格式化为json格式
    grok {
        match => {
"message"=> "%{COMBINEDAPACHELOG}"
        }
    }
#以上面提取clientip字段为源,获取地域信息
    geoip {
source=> "clientip"#指定源IP的所在字段
    }
}
output {
    stdout {
        codec => rubydebug
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/http_geoip_stdout.conf -r
{
"response"=> "200",
"clientip"=> "58.250.250.21",
"host"=> "10.0.0.100",
"@version"=> "1",
"auth"=> "-",
"request"=> "/wp-content/plugins/akismet/_inc/form.js?ver=4.1.3",
"@timestamp"=> 2020-07-14T07:51:38.653Z,
"agent"=> "\"Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36\"",
"headers"=> {
"http_user_agent"=> "curl/7.68.0",
"http_host"=> "logstash.wang.org:6666",
"content_type"=> "application/x-www-form-urlencoded",
"request_path"=> "/",
"request_method"=> "POST",
"content_length"=> "275",
"http_version"=> "HTTP/1.1",
"http_accept"=> "*/*"
    },
"bytes"=> "330",
"message"=> "58.250.250.21 - - [14/Jul/2020:15:07:27 +0800] \"GET /wp-
content/plugins/akismet/_inc/form.js?ver=4.1.3 HTTP/1.1\" 200 330
\"http://www.wangxiaochun.com/?p=117\" \"Mozilla/5.0 (Windows NT 10.0; Win64;
x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36\" \"-
\"",
"referrer"=> "\"http://www.wangxiaochun.com/?p=117\"",
"timestamp"=> "14/Jul/2020:15:07:27 +0800",
"verb"=> "GET",
"geoip"=> {
"country_name"=> "China",
"continent_code"=> "AS",
"latitude"=> 34.7732,
"ip"=> "58.250.250.21",
"country_code2"=> "CN",
"timezone"=> "Asia/Shanghai",
"longitude"=> 113.722,
"country_code3"=> "CN",
"location"=> {
"lat"=> 34.7732,
"lon"=> 113.722
        }
    },
"ident"=> "-",
"httpversion"=> "1.1"
}
#使用curl命令或insomnia等发送nginx日志给logstash可以看到上面信息
[root@ubuntu2004 ~]#curl -XPOST -d '58.250.250.21 - - [14/Jul/2020:15:07:27
+0800] "GET /wp-content/plugins/akismet/_inc/form.js?ver=4.1.3 HTTP/1.1" 200 330
"http://www.wangxiaochun.com/?p=117" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-"'
http://logstash.wang.org:6666/
ok

范例: 只显示指定的geoip的字段信息

[root@logstash ~]#cat  /etc/logstash/conf.d/http_geoip_field_stdout.conf
input {
    http {
        port =>6666
    }
}
filter {
#将nginx日志格式化为json格式
    grok {
        match => {
"message"=> "%{COMBINEDAPACHELOG}"
        }
    }
#以上面提取clientip字段为源,获取地域信息,并指定显示的字段
    geoip {
source=> "clientip"
        fields => ["continent_code","country_name","country_code2","timezone",
"longitude","latitude"]
    }
}
output {
    stdout {
        codec => rubydebug
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/http_geoip_field_stdout.conf -r
......
{
"httpversion"=> "1.1",
"clientip"=> "58.250.250.21",
"agent"=> "\"Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36\"",
"verb"=> "GET",
"timestamp"=> "14/Jul/2020:15:07:27 +0800",
"@version"=> "1",
"geoip"=> {
"latitude"=> 34.7732,
"country_name"=> "China",
"continent_code"=> "AS",
"country_code2"=> "CN",
"longitude"=> 113.722,
"timezone"=> "Asia/Shanghai"
    },
"bytes"=> "330",
"ident"=> "-",
"auth"=> "-",
"referrer"=> "\"http://www.wangxiaochun.com/?p=117\"",
"@timestamp"=> 2020-07-14T08:02:49.744Z,
"host"=> "10.0.0.100",
"response"=> "200",
"message"=> "58.250.250.21 - - [14/Jul/2020:15:07:27 +0800] \"GET /wp-
content/plugins/akismet/_inc/form.js?ver=4.1.3 HTTP/1.1\" 200 330
\"http://www.wangxiaochun.com/?p=117\" \"Mozilla/5.0 (Windows NT 10.0; Win64;
x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36\" \"-
\"",
"headers"=> {
"request_method"=> "POST",
"content_type"=> "application/x-www-form-urlencoded",
"http_host"=> "logstash.wang.org:6666",
"http_accept"=> "*/*",
"content_length"=> "275",
"http_user_agent"=> "curl/7.68.0",
"request_path"=> "/",
"http_version"=> "HTTP/1.1"
    },
"request"=> "/wp-content/plugins/akismet/_inc/form.js?ver=4.1.3"
}
......
#使用curl命令或insomnia等发送nginx日志给logstash可以看到上面信息
[root@ubuntu2004 ~]#curl -XPOST -d '58.250.250.21 - - [14/Jul/2020:15:07:27
+0800] "GET /wp-content/plugins/akismet/_inc/form.js?ver=4.1.3 HTTP/1.1" 200 330
"http://www.wangxiaochun.com/?p=117" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-"'
http://logstash.wang.org:6666/
ok
4.3.3.3 Date 插件

date插件可以将日志中的日期字符串解析为日志类型。然后替换@timestamp 字段(此字段默认为当前写放logstash的时间而非日志本身的时间)或指定的其他字段

match 类型为数组,用于指定日期匹配的格式,可以以此指定多种日期格式
target 类型为字符串,用于指定赋值的字段名,默认是 @timestamp
timezone 类型为字符串,用于指定时区域

官方说明

https://www.elastic.co/guide/en/logstash/current/plugins-filters-date.html

时区格式参考

http://joda-time.sourceforge.net/timezones.html

范例:

[root@logstash ~]#cat /etc/logstash/conf.d/http_grok_date_stdout.conf
input {
    http {
        port =>6666
    }
}
filter {
#将nginx日志格式化为json格式
    grok {
        match => {
"message"=> "%{COMBINEDAPACHELOG}"
        }
    }
#解析date日期格式为: 14/Jul/2020:15:07:27 +0800,
    date {
        match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
        target => "access_time"#将时间写入新生成的access_time字段
#target => "@timestamp"        #将时间覆盖原有的@timestamp字段
        timezone => "Asia/Shanghai"
   }
}
output {
    stdout {
        codec => rubydebug
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/http_grok_date_stdout.conf -r
......
{
"@version"=> "1",
"headers"=> {
"http_host"=> "logstash.wang.org:6666",
"request_method"=> "POST",
"content_length"=> "275",
"request_path"=> "/",
"http_accept"=> "*/*",
"http_user_agent"=> "curl/7.68.0",
"content_type"=> "application/x-www-form-urlencoded",
"http_version"=> "HTTP/1.1"
    },
"@timestamp"=> 2020-07-14T08:14:23.063Z,
"verb"=> "GET",
"ident"=> "-",
"clientip"=> "58.250.250.21",
"auth"=> "-",
"timestamp"=> "14/Jul/2020:15:07:27 +0800",
"referrer"=> "\"http://www.wangxiaochun.com/?p=117\"",
"bytes"=> "330",
"request"=> "/wp-content/plugins/akismet/_inc/form.js?ver=4.1.3",
"httpversion"=> "1.1",
"response"=> "200",
"message"=> "58.250.250.21 - - [14/Jul/2020:15:07:27 +0800] \"GET /wp-
content/plugins/akismet/_inc/form.js?ver=4.1.3 HTTP/1.1\" 200 330
\"http://www.wangxiaochun.com/?p=117\" \"Mozilla/5.0 (Windows NT 10.0; Win64;
x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36\" \"-
\"",
"access_time"=> 2020-07-14T07:07:27.000Z,  #生成新的字段
"agent"=> "\"Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36\"",
"host"=> "10.0.0.100"
}
......
#用curl提交日志,可以看到上面输出信息
[root@ubuntu2004 ~]#curl -XPOST -d '58.250.250.21 - - [14/Jul/2020:15:07:27
+0800] "GET /wp-content/plugins/akismet/_inc/form.js?ver=4.1.3 HTTP/1.1" 200 330
"http://www.wangxiaochun.com/?p=117" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-"'
http://logstash.wang.org:6666/
ok

范例: 将UNIX时间转换

date {
    match => ["timestamp","UNIX","YYYY-MM-dd HH:mm:ss"]
    target =>"@timestamp"
    timezone => "Asia/shanghai"
}
4.3.3.4 Useragent 插件

useragent 插件可以根据请求中的 user-agent 字段,解析出浏览器设备、操作系统等信息

范例:

[root@logstash ~]#cat /etc/logstash/conf.d/http_grok_useragent_stdout.conf
input {
    http {
        port =>6666
    }
}
filter {
#将nginx日志格式化为json格式
    grok {
        match => {
"message"=> "%{COMBINEDAPACHELOG}"
        }
    }
#解析date日期如: 10/Dec/2020:10:40:10 +0800
    date {
        match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
        target => "@timestamp"
#target => "access_time"
        timezone => "Asia/Shanghai"
    }
#提取agent字段,进行解析
    useragent {
source=> "agent"#指定从哪个字段获取数据
        target => "useragent"#转换后的新字段
    }
}
output {
    stdout {
        codec => rubydebug
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/http_grok_useragent_stdout.conf -r
......
{
"bytes"=> "330",
"ident"=> "-",
"host"=> "10.0.0.100",
"@version"=> "1",
"auth"=> "-",
"httpversion"=> "1.1",
"message"=> "58.250.250.21 - - [14/Jul/2020:15:07:27 +0800] \"GET /wp-
content/plugins/akismet/_inc/form.js?ver=4.1.3 HTTP/1.1\" 200 330
\"http://www.wangxiaochun.com/?p=117\" \"Mozilla/5.0 (Windows NT 10.0; Win64;
x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36\" \"-
\"",
"referrer"=> "\"http://www.wangxiaochun.com/?p=117\"",
"request"=> "/wp-content/plugins/akismet/_inc/form.js?ver=4.1.3",
"headers"=> {
"content_type"=> "application/x-www-form-urlencoded",
"request_path"=> "/",
"http_user_agent"=> "curl/7.68.0",
"http_accept"=> "*/*",
"http_host"=> "logstash.wang.org:6666",
"http_version"=> "HTTP/1.1",
"request_method"=> "POST",
"content_length"=> "275"
    },
"agent"=> "\"Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36\"",
"@timestamp"=> 2020-07-14T07:07:27.000Z,
"timestamp"=> "14/Jul/2020:15:07:27 +0800",
"verb"=> "GET",
"useragent"=> {            #生成的新字段
"name"=> "Chrome",
"major"=> "103",
"os_version"=> "10",
"patch"=> "0",
"os_major"=> "10",
"os_full"=> "Windows 10",
"os"=> "Windows",
"minor"=> "0",
"version"=> "103.0.0.0",
"os_name"=> "Windows",
"device"=> "Other"
    },
"clientip"=> "58.250.250.21",
"response"=> "200"
}
,,,,,,
#用curl提交日志,可以看到上面输出信息
[root@ubuntu2004 ~]#curl -XPOST -d '58.250.250.21 - - [14/Jul/2020:15:07:27
+0800] "GET /wp-content/plugins/akismet/_inc/form.js?ver=4.1.3 HTTP/1.1" 200 330
"http://www.wangxiaochun.com/?p=117" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-"'
http://logstash.wang.org:6666/
ok
4.3.3.5 Mutate 插件

Mutate 插件主要是对字段进行、类型转换、删除、替换、更新等操作,可以使用以下函数

remove_field 删除字段
split 字符串切割,相当于awk取列
add_field 添加字段
convert 类型转换
gsub 字符串替换

官方链接:

https://www.elastic.co/guide/en/logstash/7.6/plugins-filters-mutate.html
4.3.3.5.1 remove_field 删除字段

范例:

[root@logstash ~]#cat
/etc/logstash/conf.d/http_grok_mutate_remove_field_stdout.conf
input {
    http {
        port =>6666
    }
}
filter {
#将nginx日志格式化为json格式
    grok {
        match => {
"message"=> "%{COMBINEDAPACHELOG}"
        }
    }
#解析date日期如: 10/Dec/2020:10:40:10 +0800
    date {
        match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
        target => "@timestamp"
#target => "access_time"
        timezone => "Asia/Shanghai"
    }
#mutate 删除操作
    mutate {
        remove_field => ["headers","message", "agent"]
    }
}
output {
    stdout {
        codec => rubydebug
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/http_grok_mutate_remove_field_stdout.conf -r
......
{
"@version"=> "1",
"request"=> "/wp-content/plugins/akismet/_inc/form.js?ver=4.1.3",
"referrer"=> "\"http://www.wangxiaochun.com/?p=117\"",
"response"=> "200",
"timestamp"=> "14/Jul/2020:15:07:27 +0800",
"ident"=> "-",
"host"=> "10.0.0.100",
"httpversion"=> "1.1",
"verb"=> "GET",
"bytes"=> "330",
"@timestamp"=> 2020-07-14T07:07:27.000Z,
"clientip"=> "58.250.250.21",
"auth"=> "-"
}
,,,,,,
#用curl提交日志,可以看到上面输出信息
[root@ubuntu2004 ~]#curl -XPOST -d '58.250.250.21 - - [14/Jul/2020:15:07:27
+0800] "GET /wp-content/plugins/akismet/_inc/form.js?ver=4.1.3 HTTP/1.1" 200 330
"http://www.wangxiaochun.com/?p=117" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-"'
http://logstash.wang.org:6666/
ok
4.3.3.5.2 Split 切割

mutate 中的 split 字符切割, 指定字段做为分隔符,生成新的字段名

示例: 1000|提交订单|2020-01-08 09:10:21

范例: split 切割字符串取列

[root@logstash ~]#cat
/etc/logstash/conf.d/http_grok_mutate_remove_field_stdout.conf
input {
    http {
        port =>6666
    }
}
filter {
#mutate 切割操作
    mutate {
#字段分隔符
        split => { "message"=> "|" } #将message字段按 | 分割成多个列表元素
    }
}
output {
    stdout {
        codec => rubydebug
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/http_grok_mutate_split_stdout.conf
......
{
"message"=> [
        [0] "1000",
        [1] "提交订单",
        [2] "2020-01-08 09:10:21"
    ],
"@timestamp"=> 2021-07-14T09:23:40.392Z,
"host"=> "10.0.0.100",
"@version"=> "1",
"headers"=> {
"http_accept"=> "*/*",
"request_path"=> "/",
"content_length"=> "37",
"request_method"=> "POST",
"content_type"=> "application/x-www-form-urlencoded",
"http_version"=> "HTTP/1.1",
"http_user_agent"=> "curl/7.68.0",
"http_host"=> "logstash.wang.org:6666"
    }
}
,,,,,,
#用curl提交日志,可以看到上面输出信息
[root@ubuntu2004 ~]#curl -XPOST -d '1000|提交订单|2020-01-08 09:10:21'
http://logstash.wang.org:6666/
ok

4.3.3.5.3 add_field 添加字段

范例:

[root@logstash ~]#cat
/etc/logstash/conf.d/http_grok_mutate_add_field_stdout.conf
input {
    http {
        port =>6666
    }
}
filter {
#mutate 切割操作
    mutate {
#字段分隔符
        split => { "message"=> "|" }
#添加字段,将message的列表的第0个元素添加字段名user_id
        add_field => {
"user_id"=> "%{[message][0]}"
"action"=> "%{[message][1]}"
"time"=> "%{[message][2]}"
        }
#add_field => {"[@metadata][target_index]" => "app-%{+YYY.MM.dd}"}#添加字
段做索引名
#删除无用字段
        remove_field => ["headers","message"]
    }
}
output {
    stdout {
        codec => rubydebug
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/http_grok_mutate_add_field_stdout.conf
......
{
"user_id"=> "1000",                    #生成字段名
"@timestamp"=> 2021-07-14T09:34:11.144Z,
"time"=> "2020-01-08 09:10:21",     #生成字段名
"action"=> "提交订单",                  #生成字段名
"@version"=> "1",
"host"=> "10.0.0.100"
}
,,,,,,
#用curl提交日志,可以看到上面输出信息
[root@ubuntu2004 ~]#curl -XPOST -d '1000|提交订单|2020-01-08 09:10:21'
http://logstash.wang.org:6666/
ok
5.5.3.5.4 convert 转换

mutate 中的 convert 可以实现数据类型的转换。 支持转换integer、float、string等类型

范例:

[root@logstash ~]#cat /etc/logstash/conf.d/http_grok_mutate_convert_stdout.conf
input {
    http {
        port =>6666
    }
}
filter {
#mutate 切割操作
    mutate {
#字段分隔符
        split => { "message"=> "|" }
#添加字段
        add_field => {
"user_id"=> "%{[message][0]}"
"action"=> "%{[message][1]}"
"time"=> "%{[message][2]}"
        }
#删除无用字段
        remove_field => ["headers","message"]
#对新添加字段进行格式转换
        convert => {
"user_id"=> "integer"
"action"=> "string"
"time"=> "string"
        }
#convert => ["excute_time","float] #此格式也可以支持
#convert => ["time","string" ]
    }
}
output {
    stdout {
        codec => rubydebug
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/http_grok_mutate_convert_stdout.conf -r
......
{
"user_id"=> "1000",
"@timestamp"=> 2021-07-14T09:39:41.401Z,
"time"=> "2020-01-08 09:10:21",
"action"=> "提交订单",
"@version"=> "1",
"host"=> "10.0.0.100"
}
......
#用curl提交日志,可以看到上面输出信息
[root@ubuntu2004 ~]#curl -XPOST -d '1000|提交订单|2020-01-08 09:10:21'
http://logstash.wang.org:6666/
ok
5.5.3.5.5 gsub 替换

gsub 实现字符串的替换

filter {
    mutate {
gsub=>["message","\n", " "] #将message字段中的换行替换为空格
    }
}
4.3.3.6 条件判断

范例:

#vim /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
- /var/log/nginx/access.log
  tags: ["access"]
- type: log
  enabled: true
  paths:
- /var/log/nginx/error.log
  tags: ["error"]
output.logstash:
  hosts: ["10.0.0.104:5044","10.0.0.105:5044",]
#loadbalance: true        #负载均衡
#worker: 2 #number of hosts * workers #开启多进程
#vim /etc/logstash/conf.d/filebeat_logstash_es.conf
input {
    beats {
        port => 5044
    }
}
filter {
if"access"in [tags][0] {
        mutate {
            add_field => { "target_index"=> "access-%{+YYYY.MM.dd}"}
        }
    }
elseif"error"in [tags][0] {
        mutate {
            add_field => { "target_index"=> "error-%{+YYYY.MM.dd}"}
        }
    }
elseif"system"in [tags][0] {
        mutate {
            add_field => { "target_index"=> "system-%{+YYYY.MM.dd}"}
        }
    }
}
output {
    elasticsearch {
        hosts =>["10.0.0.101:9200","10.0.0.102:9200","10.0.0.103:9200"]  #一般写
data地址
        index => "%{[target_index]}"#使用字段target_index值做为索引名
        template_overwrite => true#覆盖索引模板
    }
}

范例:

#vim /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
- /var/log/nginx/access.log
  fields:
    project: test-access
    env: test
output.logstash:
  hosts: ["10.0.0.104:5044","10.0.0.105:5044",]
#vim /etc/logstash/conf.d/filebeat_logstash_es.conf
input {
    beats {
        port => 5044
    }
    file {
        path => "/tmp/wang.log"
        type => wanglog     #自定义的类型,可以用于条件判断
        start_position => "beginning"
        stat_interval => "3"
    }
}
output {
if [fields][env] =="test" {
        elasticsearch {
            hosts =>["10.0.0.101:9200","10.0.0.102:9200","10.0.0.103:9200"]
            index => "test-nginx-%{+YYYY.MM.dd}"
        }
    }
if [type] =="wanglog" {
        stdout {
            codec => rubydebug
        }
    }
}

4.3.4 Logstash 输出 Output 插件

官方链接

https://www.elastic.co/guide/en/logstash/7.6/output-plugins.html
4.3.4.1 Stdout 插件

stdout 插件将数据输出到屏幕终端,主要用于调试

output {
    stdout {
        codec => rubydebug
    }
}
4.3.4.2 File 插件

输出到文件,可以将将分散在多个文件的数据统一存放到一个文件

示例: 将所有 web 机器的日志收集到一个文件中,从而方便统一管理

output {
    stdout {
        codec => rubydebug
    }
    file {
        path => "/var/log/test.log"
    }
}

范例:

[root@logstash ~]#/usr/share/logstash/bin/logstash  -e 'input { stdin{} } output
{ file{ path => "/tmp/logstash.log" }}'
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in
version 9.0 and will likely be removed in a future release.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.headius.backport9.modules.Modules
(file:/usr/share/logstash/logstash-core/lib/jars/jruby-complete-9.2.9.0.jar) to
method sun.nio.ch.NativeThread.signal(long)
WARNING: Please consider reporting this to the maintainers of
com.headius.backport9.modules.Modules
WARNING: Use --illegal-access=warn to enable warnings of further illegal
reflective access operations
WARNING: All illegal access operations will be denied in a future release
WARNING: Could not find logstash.yml which is typically located in
$LS_HOME/config or /etc/logstash. You can specify the path using --
path.settings. Continuing using the defaults
Could not find log4j2 configuration at path
/usr/share/logstash/config/log4j2.properties. Using default config which logs
errors to the console
[WARN ] 2021-01-2618:58:24.105 [LogStash::Runner] multilocal - Ignoring the
'pipelines.yml' file because modules or command line options are specified
[INFO ] 2021-01-2618:58:24.116 [LogStash::Runner] runner - Starting Logstash
{"logstash.version"=>"7.6.2"}
[INFO ] 2021-01-2618:58:26.179 [Converge PipelineAction::Create<main>]
Reflections - Reflections took 35 ms to scan 1 urls, producing 20 keys and 40
values
[WARN ] 2021-01-2618:58:26.619 [[main]-pipeline-manager] LazyDelegatingGauge -
A gauge metric of an unknown type (org.jruby.RubyArray) has been created for
key: cluster_uuids. This may result in invalid serialization.  It is recommended
to log an issue to the responsible developer/development team.
[INFO ] 2021-01-2618:58:26.622 [[main]-pipeline-manager] javapipeline -
Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>2,
"pipeline.batch.size"=>125, "pipeline.batch.delay"=>50,
"pipeline.max_inflight"=>250, "pipeline.sources"=>["config string"], :thread=>"#
<Thread:0x4187ef25 run>"}
[INFO ] 2021-01-2618:58:27.294 [[main]-pipeline-manager] javapipeline -
Pipeline started {"pipeline.id"=>"main"}
The stdin plugin is now waiting for input:
[INFO ] 2021-01-2618:58:27.414 [Agent thread] agent - Pipelines running
{:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[INFO ] 2021-01-2618:58:27.600 [Api Webserver] agent - Successfully started
Logstash API endpoint {:port=>9600}
test  #输入内容
[INFO ] 2021-01-2618:59:30.242 [[main]>worker0] file - Opening file
{:path=>"/tmp/logstash.log"}
[INFO ] 2021-01-2618:59:46.667 [[main]>worker0] file - Closing file
/tmp/logstash.log
[root@logstash ~]#cat /tmp/logstash.log
{"@version":"1","@timestamp":"2021-01-
26T10:59:29.943Z","host":"logstash.wang.org","message":"test"}
4.3.4.3 Elasticsearch 插件

官方说明

https://www.elastic.co/guide/en/logstash/7.6/plugins-outputs-elasticsearch.html

索引的时间格式说明

https://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html

当日志量较小时,可以按月或周生成索引,当日志量比较大时,会按天生成索引,以方便后续按天删除

output {
    elasticsearch {
      hosts =>["10.0.0.101:9200","10.0.0.102:9200","10.0.0.103:9200"]#一般写ES中
data节点地址
      index => "app-%{+YYYY.MM.dd}"#指定索引名称,建议加时间,按天建立索引
#index => "%{[@metadata][target_index]}"#使用字段[@metadata][target_index]值
做为索引名
      template_overwrite => true#覆盖索引模板,此项可选,默认值为false
    }
}

注意: 索引名必须为小写

范例: 将标准输入输出到 elasticsearch

[root@logstash ~]#/usr/share/logstash/bin/logstash  -e 'input { stdin{} } output
{ elasticsearch {hosts => ["10.0.0.101:9200"] index => "mytest-%{+YYYY.MM.dd}"
}}'
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in
version 9.0 and will likely be removed in a future release.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.headius.backport9.modules.Modules
(file:/usr/share/logstash/logstash-core/lib/jars/jruby-complete-9.2.9.0.jar) to
method sun.nio.ch.NativeThread.signal(long)
WARNING: Please consider reporting this to the maintainers of
com.headius.backport9.modules.Modules
WARNING: Use --illegal-access=warn to enable warnings of further illegal
reflective access operations
WARNING: All illegal access operations will be denied in a future release
WARNING: Could not find logstash.yml which is typically located in
$LS_HOME/config or /etc/logstash. You can specify the path using --
path.settings. Continuing using the defaults
Could not find log4j2 configuration at path
/usr/share/logstash/config/log4j2.properties. Using default config which logs
errors to the console
[WARN ] 2021-01-2619:05:02.417 [LogStash::Runner] multilocal - Ignoring the
'pipelines.yml' file because modules or command line options are specified
[INFO ] 2021-01-2619:05:02.431 [LogStash::Runner] runner - Starting Logstash
{"logstash.version"=>"7.6.2"}
[INFO ] 2021-01-2619:05:04.002 [Converge PipelineAction::Create<main>]
Reflections - Reflections took 37 ms to scan 1 urls, producing 20 keys and 40
values
[INFO ] 2021-01-2619:05:04.763 [[main]-pipeline-manager] elasticsearch -
Elasticsearch pool URLs updated {:changes=>{:removed=>[], :added=>
[http://10.0.0.101:9200/]}}
[WARN ] 2021-01-2619:05:04.935 [[main]-pipeline-manager] elasticsearch -
Restored connection to ES instance {:url=>"http://10.0.0.101:9200/"}
[INFO ] 2021-01-2619:05:05.126 [[main]-pipeline-manager] elasticsearch - ES
Output version determined {:es_version=>7}
[WARN ] 2021-01-2619:05:05.129 [[main]-pipeline-manager] elasticsearch -
Detected a 6.x and above cluster: the `type` event field won't be used to
determine the document _type {:es_version=>7}
[INFO ] 2021-01-2619:05:05.196 [[main]-pipeline-manager] elasticsearch - New
Elasticsearch output {:class=>"LogStash::Outputs::ElasticSearch", :hosts=>
["//10.0.0.101:9200"]}
[INFO ] 2021-01-2619:05:05.275 [Ruby-0-Thread-6: :1] elasticsearch - Using
default mapping template
[WARN ] 2021-01-2619:05:05.329 [[main]-pipeline-manager] LazyDelegatingGauge -
A gauge metric of an unknown type (org.jruby.specialized.RubyArrayOneObject) has
been created for key: cluster_uuids. This may result in invalid serialization.
It is recommended to log an issue to the responsible developer/development team.
[INFO ] 2021-01-2619:05:05.334 [[main]-pipeline-manager] javapipeline -
Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>2,
"pipeline.batch.size"=>125, "pipeline.batch.delay"=>50,
"pipeline.max_inflight"=>250, "pipeline.sources"=>["config string"], :thread=>"#
<Thread:0x26fa8247 run>"}
[INFO ] 2021-01-2619:05:05.381 [Ruby-0-Thread-6: :1] elasticsearch - Attempting
to install template {:manage_template=>{"index_patterns"=>"logstash-*",
"version"=>60001, "settings"=>{"index.refresh_interval"=>"5s",
"number_of_shards"=>1}, "mappings"=>{"dynamic_templates"=>[{"message_field"=>
{"path_match"=>"message", "match_mapping_type"=>"string", "mapping"=>
{"type"=>"text", "norms"=>false}}}, {"string_fields"=>{"match"=>"*",
"match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false,
"fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}}}}],
"properties"=>{"@timestamp"=>{"type"=>"date"}, "@version"=>{"type"=>"keyword"},
"geoip"=>{"dynamic"=>true, "properties"=>{"ip"=>{"type"=>"ip"}, "location"=>
{"type"=>"geo_point"}, "latitude"=>{"type"=>"half_float"}, "longitude"=>
{"type"=>"half_float"}}}}}}}
[INFO ] 2021-01-2619:05:05.463 [Ruby-0-Thread-6: :1] elasticsearch - Installing
elasticsearch template to _template/logstash
[INFO ] 2021-01-2619:05:06.262 [[main]-pipeline-manager] javapipeline -
Pipeline started {"pipeline.id"=>"main"}
The stdin plugin is now waiting for input:
[INFO ] 2021-01-2619:05:06.322 [Agent thread] agent - Pipelines running
{:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[INFO ] 2021-01-2619:05:06.519 [Api Webserver] agent - Successfully started
Logstash API endpoint {:port=>9600}
Elasticsearch test #输入信息

范例:将文件输出至 Elasticsearch

[root@logstash ~]#/usr/share/logstash/bin/logstash -e  'input { file { path =>
"/var/log/bootstrap.log" start_position => "beginning" stat_interval => "3" } }
output { elasticsearch {hosts => ["10.0.0.101:9200"] index => "logfile-%
{+YYYY.MM.dd}" }}'
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in
version 9.0 and will likely be removed in a future release.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.headius.backport9.modules.Modules
(file:/usr/share/logstash/logstash-core/lib/jars/jruby-complete-9.2.9.0.jar) to
method sun.nio.ch.NativeThread.signal(long)
WARNING: Please consider reporting this to the maintainers of
com.headius.backport9.modules.Modules
WARNING: Use --illegal-access=warn to enable warnings of further illegal
reflective access operations
WARNING: All illegal access operations will be denied in a future release
WARNING: Could not find logstash.yml which is typically located in
$LS_HOME/config or /etc/logstash. You can specify the path using --
path.settings. Continuing using the defaults
Could not find log4j2 configuration at path
/usr/share/logstash/config/log4j2.properties. Using default config which logs
errors to the console
[WARN ] 2021-01-2623:49:26.545 [LogStash::Runner] multilocal - Ignoring the
'pipelines.yml' file because modules or command line options are specified
[INFO ] 2021-01-2623:49:26.555 [LogStash::Runner] runner - Starting Logstash
{"logstash.version"=>"7.6.2"}
[INFO ] 2021-01-2623:49:28.556 [Converge PipelineAction::Create<main>]
Reflections - Reflections took 67 ms to scan 1 urls, producing 20 keys and 40
values
[INFO ] 2021-01-2623:49:29.685 [[main]-pipeline-manager] elasticsearch -
Elasticsearch pool URLs updated {:changes=>{:removed=>[], :added=>
[http://10.0.0.101:9200/]}}
[WARN ] 2021-01-2623:49:29.959 [[main]-pipeline-manager] elasticsearch -
Restored connection to ES instance {:url=>"http://10.0.0.101:9200/"}
[INFO ] 2021-01-2623:49:30.239 [[main]-pipeline-manager] elasticsearch - ES
Output version determined {:es_version=>7}
[WARN ] 2021-01-2623:49:30.246 [[main]-pipeline-manager] elasticsearch -
Detected a 6.x and above cluster: the `type` event field won't be used to
determine the document _type {:es_version=>7}
[INFO ] 2021-01-2623:49:30.330 [[main]-pipeline-manager] elasticsearch - New
Elasticsearch output {:class=>"LogStash::Outputs::ElasticSearch", :hosts=>
["//10.0.0.101:9200"]}
[INFO ] 2021-01-2623:49:30.448 [Ruby-0-Thread-6: :1] elasticsearch - Using
default mapping template
[WARN ] 2021-01-2623:49:30.469 [[main]-pipeline-manager] LazyDelegatingGauge -
A gauge metric of an unknown type (org.jruby.specialized.RubyArrayOneObject) has
been created for key: cluster_uuids. This may result in invalid serialization.
It is recommended to log an issue to the responsible developer/development team.
[INFO ] 2021-01-2623:49:30.489 [[main]-pipeline-manager] javapipeline -
Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>2,
"pipeline.batch.size"=>125, "pipeline.batch.delay"=>50,
"pipeline.max_inflight"=>250, "pipeline.sources"=>["config string"], :thread=>"#
<Thread:0x30ea9ca1 run>"}
[INFO ] 2021-01-2623:49:30.577 [Ruby-0-Thread-6: :1] elasticsearch - Attempting
to install template {:manage_template=>{"index_patterns"=>"logstash-*",
"version"=>60001, "settings"=>{"index.refresh_interval"=>"5s",
"number_of_shards"=>1}, "mappings"=>{"dynamic_templates"=>[{"message_field"=>
{"path_match"=>"message", "match_mapping_type"=>"string", "mapping"=>
{"type"=>"text", "norms"=>false}}}, {"string_fields"=>{"match"=>"*",
"match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false,
"fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}}}}],
"properties"=>{"@timestamp"=>{"type"=>"date"}, "@version"=>{"type"=>"keyword"},
"geoip"=>{"dynamic"=>true, "properties"=>{"ip"=>{"type"=>"ip"}, "location"=>
{"type"=>"geo_point"}, "latitude"=>{"type"=>"half_float"}, "longitude"=>
{"type"=>"half_float"}}}}}}}
[INFO ] 2021-01-2623:49:31.773 [[main]-pipeline-manager] file - No sincedb_path
set, generating one based on the "path" setting
{:sincedb_path=>"/usr/share/logstash/data/plugins/inputs/file/.sincedb_d775630e2
3677feb080794eae41c5417", :path=>["/var/log/bootstrap.log"]}
[INFO ] 2021-01-2623:49:31.803 [[main]-pipeline-manager] javapipeline -
Pipeline started {"pipeline.id"=>"main"}
[INFO ] 2021-01-2623:49:31.913 [Agent thread] agent - Pipelines running
{:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[INFO ] 2021-01-2623:49:31.948 [[main]<file] observingtail - START, creating
Discoverer, Watch with file and sincedb collections
[INFO ] 2021-01-2623:49:32.417 [Api Webserver] agent - Successfully started
Logstash API endpoint {:port=>9600}

范例: 配置文件实现

#将配置写入配置文件中
[root@ubuntu1804 ~]#cat /etc/logstash/conf.d/logstash-test.conf
input {
    file {
        path => "/var/log/syslog"
        start_position => "beginning"
        stat_interval => 3
    }
}
output {
    elasticsearch {
        hosts => ["10.0.0.101:9200"]
        index => "syslog-%{+YYYY.MM.dd}"
    }
}
#检查语法
[root@ubuntu1804 ~]#/usr/share/logstash/bin/logstash  -f
/etc/logstash/conf.d/logstash-test.conf -t
#前台执行
[root@ubuntu1804 ~]#/usr/share/logstash/bin/logstash  -f
/etc/logstash/conf.d/logstash-test.conf

Elasticsearch服务器验证收到数据

通过head插件观察到下面信息

通过cerebro插件可以看到下面信息

4.3.4.4 Redis 插件

Logstash 支持将日志转发至 Redis

官方链接:

https://www.elastic.co/guide/en/logstash/7.6/plugins-outputs-redis.html

范例

[root@logstash ~]#cat /etc/logstash/conf.d/file_to_redis.conf
input {
    file {
        path => "/var/log/nginx/access.log"
        type => 'nginx-accesslog'
        start_position => "beginning"
        stat_interval => "3"
        codec ==> json
    }
}
output {
if [type] =='nginx-accesslog' {
        redis {
            host => 'Redis_IP'
            port => "6379"
            password => "123456"
            db => "0"
            data_type => 'list'
            key => "nginx-accesslog"
        }
    }
}
4.3.4.5 Kafka 插件

Logstash 支持将日志转发至 Kafka

官方链接:

https://www.elastic.co/guide/en/logstash/7.6/plugins-outputs-kafka.html

范例:

[root@logstash ~]#cat /etc/logstash/conf.d/file_to_kafka.conf
input {
    file {
        path => "/var/log/nginx/access.log"
        type => 'nginx-accesslog'
        start_position => "beginning"
        stat_interval => "3"
        codec ==> json
    }
    file {
        path => "/var/log/nginx/error.log"
        type => 'nginx-errorlog'
        start_position => "beginning"
        stat_interval => "3"
    }
}
output {
#stdout {}
if [type] =='nginx-accesslog' {
        kafka {
            bootstrap_servers =>
'10.0.0.201:9092,10.0.0.202:9092,10.0.0.203:9092'
            topic_id => 'nginx-accesslog'
            codec => 'json'#如果是Json格式,需要标识的字段
        }
    }
if [type] =='nginx-errorlog' {
        kafka {
            bootstrap_servers => 'Kafka_IP1:9092,Kafka_IP2:9092,Kafka_IP3:9092'
            topic_id => 'nginx-errorlog'
            codec => 'json'#为了保留logstash添加的字段,比如:type字段,也需要指定json格
式,否则会丢失logstash添加的字段
        }
    }
}

4.4 Logstash 实战案例

4.4.1 收集单个系统日志并输出至 Elasticsearch

前提需要logstash用户对被收集的日志文件有读的权限并对写入的文件有写权限

4.4.1.1 Logstash配置文件

[root@logstash ~]#vim /etc/logstash/conf.d/dpkg-to-es.conf
input {
  file {
    path => "/var/log/dpkg.log"
    start_position => "beginning"
    stat_interval => "3"
  }
}
output {
  elasticsearch {
    hosts => ["10.0.0.101:9200"]
    index => "linux-%{+YYYY.MM.dd}"
  }
}
4.4.1.2 检测配置文件语法是否正确
[root@logstash ~]#/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/dpkg-
to-es.conf  -t
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in
version 9.0 and will likely be removed in a future release.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.headius.backport9.modules.Modules
(file:/usr/share/logstash/logstash-core/lib/jars/jruby-complete-9.2.9.0.jar) to
method sun.nio.ch.NativeThread.signal(long)
WARNING: Please consider reporting this to the maintainers of
com.headius.backport9.modules.Modules
WARNING: Use --illegal-access=warn to enable warnings of further illegal
reflective access operations
WARNING: All illegal access operations will be denied in a future release
WARNING: Could not find logstash.yml which is typically located in
$LS_HOME/config or /etc/logstash. You can specify the path using --
path.settings. Continuing using the defaults
Could not find log4j2 configuration at path
/usr/share/logstash/config/log4j2.properties. Using default config which logs
errors to the console
[WARN ] 2021-01-3115:58:00.880 [LogStash::Runner] multilocal - Ignoring the
'pipelines.yml' file because modules or command line options are specified
[INFO ] 2021-01-3115:58:02.007 [LogStash::Runner] Reflections - Reflections
took 37 ms to scan 1 urls, producing 20 keys and 40 values
Configuration OK
[INFO ] 2021-01-3115:58:02.447 [LogStash::Runner] runner - Using
config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash
4.4.1.3 启动 Logstash 服务
[root@logstash ~]#systemctl enable --now logstash.service
Created symlink /etc/systemd/system/multi-user.target.wants/logstash.service â••
/etc/systemd/system/logstash.service.
[root@logstash ~]#systemctl status  logstash.service
â•• logstash.service - logstash
   Loaded: loaded (/etc/systemd/system/logstash.service; enabled; vendor preset:
enabled)
   Active: active (running) since Sun 2021-01-3115:55:49 CST; 6s ago
 Main PID: 3053 (java)
    Tasks: 14 (limit: 2290)
   CGroup: /system.slice/logstash.service
           â••â••3053 /usr/bin/java -Xms1g-Xmx1g-XX:+UseConcMarkSweepGC -
XX:CMSInitiatingOccupancyFraction=75-XX:+UseCMSInitiatingOccupancyOnly -
Djava.awt.hea
Jan 3115:55:49 logstash.wang.org systemd[1]: Started logstash.
Jan 3115:55:49 logstash.wang.org logstash[3053]: OpenJDK 64-Bit Server VM
warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely
Jan 3115:55:55 logstash.wang.org logstash[3053]: WARNING: An illegal reflective
access operation has occurred
Jan 3115:55:55 logstash.wang.org logstash[3053]: WARNING: Illegal reflective
access by com.headius.backport9.modules.Modules (file:/usr/share/logstash/log
Jan 3115:55:55 logstash.wang.org logstash[3053]: WARNING: Please consider
reporting this to the maintainers of com.headius.backport9.modules.Modules
Jan 3115:55:55 logstash.wang.org logstash[3053]: WARNING: Use --illegal-
access=warn to enable warnings of further illegal reflective access operations
Jan 3115:55:55 logstash.wang.org logstash[3053]: WARNING: All illegal access
operations will be denied in a future release
4.4.1.4 生成数据并验证
[root@logstash ~]#apt purge  apache2 -y
4.4.1.5 在 Kibana 中验证结果

4.4.2 通过 Logstash 收集多个日志文件并输出至 Elasticsearch

4.4.2.1 服务器部署 Tomcat 服务

安装 Java 环境并且通过一个 Web 界面进行访问测试。

4.4.2.1.1 配置 Java 环境并部署 Tomcat
#先安装JDK,因为logstash已经安装JDK,此步不用执行
[root@logstash ~]#mkdir /apps
[root@logstash ~]#ll apache-tomcat-8.5.61.tar.gz
-rw-r--r--1 root root 10492067 Jan  317:47 apache-tomcat-8.5.61.tar.gz
[root@logstash ~]#tar xf apache-tomcat-8.5.61.tar.gz  -C /apps/
[root@logstash ~]#cd /apps
[root@logstash apps]#ln -s apache-tomcat-8.5.61/ tomcat
[root@logstash ~]#/apps/tomcat/bin/startup.sh
4.4.2.1.2 确认 Web 可以访问

用浏览器访问tomcat

生成访问日志

[root@logstash ~]#ll /apps/tomcat/logs/
total 32
drwxr-x--- 2 root root 4096 Jan 3116:25 ./
drwxr-xr-x 9 root root 4096 Jan 3116:25 ../
-rw-r-----1 root root 6615 Jan 3116:25 catalina.2021-01-31.log
-rw-r-----1 root root 6787 Jan 3116:25 catalina.out
-rw-r-----1 root root    0 Jan 3116:25 host-manager.2021-01-31.log
-rw-r-----1 root root  459 Jan 3116:25 localhost.2021-01-31.log
-rw-r-----1 root root  711 Jan 3116:30 localhost_access_log.2021-01-31.txt
-rw-r-----1 root root    0 Jan 3116:25 manager.2021-01-31.log
4.4.2.2 Logstash配置
[root@logstash ~]#cat /etc/logstash/conf.d/syslog-tomcat-to-es.conf
input {
  file {
    path => "/var/log/syslog"#日志路径
    start_position => "beginning"#第一次收集日志的位置
    stat_interval => "3"#日志收集的间隔时间
    type => "syslog"#事件的唯一类型,可用于区分不同日志,分别存于不同
index
  }
 file {
    path => "/apps/tomcat/logs/localhost_access_log.*.txt"#日志路径
    start_position => "beginning"#第一次收集日志的位置
    stat_interval => "3"#日志收集的间隔时间
    type => "tomcat-access"#事件的唯一类型
 }
}
output {
  elasticsearch {
    hosts => ["10.0.0.101:9200"]
    index => "linux-syslog-tomcat-%{+YYYY.MM.dd}"
  }
}
4.4.2.3 设置权限并重启logstash并查看日志是否有报错
#修改权限让logstash可以访问日志
[root@logstash ~]#setfacl  -m u:logstash:r /var/log/syslog  /apps/tomcat/logs/*
[root@logstash ~]#setfacl  -Rm u:logstash:rx   /apps/tomcat/logs/
#或者修改Logstash启用用户为root
[root@logstash ~]#vim /etc/systemd/system/logstash.service
User=logstash
Group=logstash
[root@logstash ~]#systemctl restart logstash
#确认没有错误提示
[root@logstash ~]#cat /var/log/logstash/*
[2021-01-31T17:14:25,950][INFO ][logstash.javapipeline    ][main] Starting
pipeline {:pipeline_id=>"main", "pipeline.workers"=>2,
"pipeline.batch.size"=>125, "pipeline.batch.delay"=>50,
"pipeline.max_inflight"=>250, "pipeline.sources"=>["/etc/logstash/conf.d/dpkg-
to-es.conf", "/etc/logstash/conf.d/syslog-tomcat-to-es.conf"], :thread=>"#
<Thread:0x100e8e59 run>"}
[2021-01-31T17:14:26,977][INFO ][logstash.inputs.file     ][main] No sincedb_path
set, generating one based on the "path" setting
{:sincedb_path=>"/var/lib/logstash/plugins/inputs/file/.sincedb_32f0f350939e5021
672b2ae32dbe8707", :path=>["/apps/tomcat/logs/localhost_access_log.*.txt"]}
[2021-01-31T17:14:27,011][INFO ][logstash.inputs.file     ][main] No sincedb_path
set, generating one based on the "path" setting
{:sincedb_path=>"/var/lib/logstash/plugins/inputs/file/.sincedb_97162ef95ddfd5ec
14e860c916f9ca74", :path=>["/var/log/syslog.log"]}
[2021-01-31T17:14:27,022][INFO ][logstash.inputs.file     ][main] No sincedb_path
set, generating one based on the "path" setting
{:sincedb_path=>"/var/lib/logstash/plugins/inputs/file/.sincedb_53ee1dc7b0052cf4
3da0cab60435e2c0", :path=>["/var/log/dpkg.log"]}
[2021-01-31T17:14:27,071][INFO ][logstash.javapipeline    ][main] Pipeline
started {"pipeline.id"=>"main"}
[2021-01-31T17:14:27,111][INFO ][filewatch.observingtail  ][main] START, creating
Discoverer, Watch with file and sincedb collections
[2021-01-31T17:14:27,146][INFO ][filewatch.observingtail  ][main] START, creating
Discoverer, Watch with file and sincedb collections
[2021-01-31T17:14:27,138][INFO ][filewatch.observingtail  ][main] START, creating
Discoverer, Watch with file and sincedb collections
[2021-01-31T17:14:27,217][INFO ][logstash.agent           ] Pipelines running
{:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[2021-01-31T17:14:27,599][INFO ][logstash.agent           ] Successfully started
Logstash API endpoint {:port=>9600}
4.4.2.4 向被收集的文件生成新日志信息
[root@centos8 ~]#while true;do curl 10.0.0.104:8080;sleep 1;done
[root@logstash ~]#logger  "test log"
4.4.2.5 查看索引是否生成

4.4.2.6 配置将不同类型日志写入不同索引
[root@logstash ~]#cat /etc/logstash/conf.d/syslog-tomcat-to-es.conf
input {
  file {
    path => "/var/log/syslog"
    start_position => "beginning"
    stat_interval => "3"
    type => "syslog"
  }
  file {
    path => "/apps/tomcat/logs/localhost_access_log.*.txt"
    start_position => "beginning"
    stat_interval => "3"
    type => "tomcat-access"
  }
}
output {
if [type] =="syslog" {                 #指定类型不同,写入不同索引
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "syslog-0.104-%{+YYYY.MM.dd}"
    }
    file {                                #可以同时写入文件
      path => "/tmp/syslog-0.104.log"
    }
  }
if [type] =="tomcat-access" {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "tomcat-accesslog-0.104-%{+YYYY.MM.dd}"
    }
    file {
      path => "/tmp/tomcat-accesslog-0.104.log"
    }
  }
}
[root@logstash ~]#systemctl restart logstash.service

4.4.2.7 Kibana 界面添加索引

4.4.2.7.1 添加syslog索引

4.4.2.7.2 添加tomcat索引

4.4.2.8 Kibana 展示索引

4.4.2.8.1 Kibana 展示 syslog 索引

4.4.2.8.2 Kibana 展示 tomcat 日志索引

4.4.2.9 输出索引文件
[root@logstash ~]#ll /tmp/*.log
-rw-r--r--1 logstash logstash  57005 Jan 3119:02 /tmp/syslog-0.104.log
-rw-r--r--1 logstash logstash 141780 Jan 3119:02 /tmp/tomcat-accesslog-
0.104.log
[root@logstash ~]#tail  /tmp/syslog-0.104.log
{"@timestamp":"2021-01-
31T10:46:35.318Z","path":"/var/log/syslog","type":"syslog","message":"Jan 31
18:46:32 logstash logstash[4863]: [2021-01-31T18:46:32,488][INFO ]
[logstash.outputs.file    ][main] Closing file
/tmp/syslog.log","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:46:38.321Z","path":"/var/log/syslog","type":"syslog","message":"Jan 31
18:46:35 logstash logstash[4863]: [2021-01-31T18:46:35,451][INFO ]
[logstash.outputs.file    ][main] Opening file
{:path=>\"/tmp/syslog.log\"}","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:46:53.331Z","path":"/var/log/syslog","type":"syslog","message":"Jan 31
18:46:52 logstash logstash[4863]: [2021-01-31T18:46:52,511][INFO ]
[logstash.outputs.file    ][main] Closing file
/tmp/syslog.log","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:46:56.335Z","path":"/var/log/syslog","type":"syslog","message":"Jan 31
18:46:53 logstash logstash[4863]: [2021-01-31T18:46:53,472][INFO ]
[logstash.outputs.file    ][main] Opening file
{:path=>\"/tmp/syslog.log\"}","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:47:14.348Z","path":"/var/log/syslog","type":"syslog","message":"Jan 31
18:47:12 logstash logstash[4863]: [2021-01-31T18:47:12,537][INFO ]
[logstash.outputs.file    ][main] Closing file
/tmp/syslog.log","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:47:17.352Z","path":"/var/log/syslog","type":"syslog","message":"Jan 31
18:47:14 logstash logstash[4863]: [2021-01-31T18:47:14,481][INFO ]
[logstash.outputs.file    ][main] Opening file
{:path=>\"/tmp/syslog.log\"}","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:47:35.363Z","path":"/var/log/syslog","type":"syslog","message":"Jan 31
18:47:32 logstash logstash[4863]: [2021-01-31T18:47:32,575][INFO ]
[logstash.outputs.file    ][main] Closing file
/tmp/syslog.log","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:47:38.366Z","path":"/var/log/syslog","type":"syslog","message":"Jan 31
18:47:35 logstash logstash[4863]: [2021-01-31T18:47:35,493][INFO ]
[logstash.outputs.file    ][main] Opening file
{:path=>\"/tmp/syslog.log\"}","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:47:53.376Z","path":"/var/log/syslog","type":"syslog","message":"Jan 31
18:47:52 logstash logstash[4863]: [2021-01-31T18:47:52,623][INFO ]
[logstash.outputs.file    ][main] Closing file
/tmp/syslog.log","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:47:56.378Z","path":"/var/log/syslog","type":"syslog","message":"Jan 31
18:47:53 logstash logstash[4863]: [2021-01-31T18:47:53,510][INFO ]
[logstash.outputs.file    ][main] Opening file
{:path=>\"/tmp/syslog.log\"}","@version":"1","host":"logstash.wang.org"}
[root@logstash ~]#tail /tmp/tomcat-accesslog-0.104.log
{"@timestamp":"2021-01-
31T10:38:55.090Z","path":"/apps/tomcat/logs/localhost_access_log.2021-01-
31.txt","type":"tomcat-access","message":"10.0.0.8 - - [31/Jan/2021:18:38:46
+0800] \"GET / HTTP/1.1\" 200 11156","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:39:04.106Z","path":"/apps/tomcat/logs/localhost_access_log.2021-01-
31.txt","type":"tomcat-access","message":"10.0.0.8 - - [31/Jan/2021:18:38:52
+0800] \"GET / HTTP/1.1\" 200 11156","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:39:04.106Z","path":"/apps/tomcat/logs/localhost_access_log.2021-01-
31.txt","type":"tomcat-access","message":"10.0.0.8 - - [31/Jan/2021:18:38:53
+0800] \"GET / HTTP/1.1\" 200 11156","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:39:04.107Z","path":"/apps/tomcat/logs/localhost_access_log.2021-01-
31.txt","type":"tomcat-access","message":"10.0.0.8 - - [31/Jan/2021:18:38:54
+0800] \"GET / HTTP/1.1\" 200 11156","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:39:04.107Z","path":"/apps/tomcat/logs/localhost_access_log.2021-01-
31.txt","type":"tomcat-access","message":"10.0.0.8 - - [31/Jan/2021:18:38:55
+0800] \"GET / HTTP/1.1\" 200 11156","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:39:04.108Z","path":"/apps/tomcat/logs/localhost_access_log.2021-01-
31.txt","type":"tomcat-access","message":"10.0.0.8 - - [31/Jan/2021:18:38:57
+0800] \"GET / HTTP/1.1\" 200 11156","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:39:04.108Z","path":"/apps/tomcat/logs/localhost_access_log.2021-01-
31.txt","type":"tomcat-access","message":"10.0.0.8 - - [31/Jan/2021:18:38:58
+0800] \"GET / HTTP/1.1\" 200 11156","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:39:04.108Z","path":"/apps/tomcat/logs/localhost_access_log.2021-01-
31.txt","type":"tomcat-access","message":"10.0.0.8 - - [31/Jan/2021:18:38:59
+0800] \"GET / HTTP/1.1\" 200 11156","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:39:04.108Z","path":"/apps/tomcat/logs/localhost_access_log.2021-01-
31.txt","type":"tomcat-access","message":"10.0.0.8 - - [31/Jan/2021:18:39:00
+0800] \"GET / HTTP/1.1\" 200 11156","@version":"1","host":"logstash.wang.org"}
{"@timestamp":"2021-01-
31T10:39:04.109Z","path":"/apps/tomcat/logs/localhost_access_log.2021-01-
31.txt","type":"tomcat-access","message":"10.0.0.8 - - [31/Jan/2021:18:39:01
+0800] \"GET / HTTP/1.1\" 200 11156","@version":"1","host":"logstash.wang.org"}

4.4.3 通过 Logstash 收集 Tomcat 和 Java 日志并输出至 Elasticsearch

每台Tomcat服务器要安装logstash负责收集Tomcat服务器的访问日志和错误日志进行实时统计,然后将日志转发给Elasticsearch进行分析,最终利用 Kibana 在前端展现

4.4.3.1 服务器部署 Tomcat 服务

需要安装 Java 环境,并自定义一个 Web 界面进行测试。

4.4.3.1.1 配置 Java 环境并部署 Tomcat
#先安装JDK,因为logstash已经安装JDK,此步不用执行
[root@elk-web1 ~]#apt -y  install openjdk-8-jdk
[root@logstash ~]#mkdir /apps
[root@logstash ~]#ll apache-tomcat-8.5.61.tar.gz
-rw-r--r--1 root root 10492067 Jan  317:47 apache-tomcat-8.5.61.tar.gz
[root@logstash ~]#tar xf apache-tomcat-8.5.61.tar.gz  -C /apps/
[root@logstash ~]#cd /apps
[root@logstash apps]#ln -s apache-tomcat-8.5.61/ tomcat
[root@logstash ~]#/apps/tomcat/bin/startup.sh
4.4.3.1.2 确认 Web 可以访问

用浏览器访问 tomcat

生成访问日志

[root@elk-web1 ~]#ll /apps/tomcat/logs/
total 32
drwxr-x--- 2 root root 4096 Feb  210:27 ./
drwxr-xr-x 9 root root 4096 Feb  210:25 ../
-rw-r-----1 root root 6158 Feb  210:27 catalina.2021-02-02.log
-rw-r-----1 root root 6158 Feb  210:27 catalina.out
-rw-r-----1 root root    0 Feb  210:27 host-manager.2021-02-02.log
-rw-r-----1 root root  458 Feb  210:27 localhost.2021-02-02.log
-rw-r-----1 root root 1605 Feb  210:27 localhost_access_log.2021-02-02.txt
-rw-r-----1 root root    0 Feb  210:27 manager.2021-02-02.log
4.4.3.1.3 Tomcat 日志转为 Json 格式

参考文档:

http://tomcat.apache.org/tomcat-9.0-doc/config/valve.html#Access_Logging

调整日志格式为 json,方便后期 Elasticsearch 分析使用

[root@elk-web1 ~]# vim /apps/tomcat/conf/server.xml
    <Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"suffix=".txt"
#pattern="%h %l %u %t &quot;%r&quot; %s %b" /> 删除此行,加下面内容实现自定义的json日志
格式
pattern="
{&quot;clientip&quot;:&quot;%h&quot;,&quot;ClientUser&quot;:&quot;%l&quot;,&quot
;authenticated&quot;:&quot;%u&quot;,&quot;AccessTime&quot;:&quot;%t&quot;,&quot;
method&quot;:&quot;%r&quot;,&quot;status&quot;:&quot;%s&quot;,&quot;SendBytes&qu
ot;:&quot;%b&quot;,&quot;Query?
string&quot;:&quot;%q&quot;,&quot;partner&quot;:&quot;%
{Referer}i&quot;,&quot;AgentVersion&quot;:&quot;%{User-Agent}i&quot;}"/>
[root@elk-web1 ~]#/apps/tomcat/bin/shutdown.sh
[root@elk-web1 ~]#/apps/tomcat/bin/startup.sh

# 查看日志格式发生变化

[root@elk-web1 ~]#tail -f /apps/tomcat/logs/localhost_access_log.2021-02-02.txt
10.0.0.1 -- [02/Feb/2021:10:36:13 +0800] "GET / HTTP/1.1"20011156
10.0.0.1 -- [02/Feb/2021:10:36:13 +0800] "GET /favicon.ico HTTP/1.1"20021630
10.0.0.1 -- [02/Feb/2021:10:36:13 +0800] "GET / HTTP/1.1"20011156
10.0.0.1 -- [02/Feb/2021:10:36:13 +0800] "GET /favicon.ico HTTP/1.1"20021630
10.0.0.1 -- [02/Feb/2021:10:36:13 +0800] "GET / HTTP/1.1"20011156
10.0.0.1 -- [02/Feb/2021:10:36:13 +0800] "GET /favicon.ico HTTP/1.1"20021630
10.0.0.1 -- [02/Feb/2021:10:36:13 +0800] "GET / HTTP/1.1"20011156
10.0.0.1 -- [02/Feb/2021:10:36:13 +0800] "GET /favicon.ico HTTP/1.1"20021630
10.0.0.1 -- [02/Feb/2021:10:36:13 +0800] "GET / HTTP/1.1"20011156
10.0.0.1 -- [02/Feb/2021:10:36:13 +0800] "GET /favicon.ico HTTP/1.1"20021630
{"clientip":"10.0.0.1","ClientUser":"-","authenticated":"-","AccessTime":"
[02/Feb/2021:10:37:10 +0800]","method":"GET /
HTTP/1.1","status":"200","SendBytes":"11156","Query?string":"","partner":"-
","AgentVersion":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36 FS"}
{"clientip":"10.0.0.1","ClientUser":"-","authenticated":"-","AccessTime":"
[02/Feb/2021:10:37:10 +0800]","method":"GET /favicon.ico
HTTP/1.1","status":"200","SendBytes":"21630","Query?
string":"","partner":"http://10.0.0.107:8080/","AgentVersion":"Mozilla/5.0
(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/88.0.4324.104 Safari/537.36 FS"}
{"clientip":"10.0.0.1","ClientUser":"-","authenticated":"-","AccessTime":"
[02/Feb/2021:10:37:11 +0800]","method":"GET /
HTTP/1.1","status":"200","SendBytes":"11156","Query?string":"","partner":"-
","AgentVersion":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36 FS"}
{"clientip":"10.0.0.1","ClientUser":"-","authenticated":"-","AccessTime":"
[02/Feb/2021:10:37:11 +0800]","method":"GET /favicon.ico
HTTP/1.1","status":"200","SendBytes":"21630","Query?
string":"","partner":"http://10.0.0.107:8080/","AgentVersion":"Mozilla/5.0
(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/88.0.4324.104 Safari/537.36 FS"}
{"clientip":"10.0.0.1","ClientUser":"-","authenticated":"-","AccessTime":"
[02/Feb/2021:10:37:11 +0800]","method":"GET /
HTTP/1.1","status":"200","SendBytes":"11156","Query?string":"","partner":"-
","AgentVersion":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36 FS"}
{"clientip":"10.0.0.1","ClientUser":"-","authenticated":"-","AccessTime":"
[02/Feb/2021:10:37:11 +0800]","method":"GET /favicon.ico
HTTP/1.1","status":"200","SendBytes":"21630","Query?
string":"","partner":"http://10.0.0.107:8080/","AgentVersion":"Mozilla/5.0
(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/88.0.4324.104 Safari/537.36 FS"}

4.4.3.1.4 验证日志是否 Json 格式

利用json网站工具验证 json 格式

https://www.sojson.com/
http://www.kjson.com/

4.4.3.1.5 利用 Python 脚本获取日志行中的 IP
[root@elk-web1 ~]#cat get_status.py
#!/usr/bin/python3
#coding:utf-8
status_200= []
status_404= []
with open("access_json.log") as f:
for line in f.readlines():
      line = eval(line)
      print(line.get("clientip"))
if line.get("status") =="200":
          status_200.append(line.get)
elif line.get("status") =="404":
          status_404.append(line.get)
else:
          print("状态码 ERROR")
f.close()
print("状态码200的有--:",len(status_200))
print("状态码404的有--:",len(status_404))
[root@elk-web1 ~]#
[root@elk-web1 ~]#./get_status.py
10.0.0.1
10.0.0.1
10.0.0.1
10.0.0.1
10.0.0.1
状态码200的有--: 5
状态码404的有--: 0
4.4.3.2 在 Tomcat 服务器安装 Logstash 收集 Tomcat和系统日志

需要部署tomcat并安装配置 logstash

4.4.3.2.1 安装配置 Logstash

[root@elk-web1 ~]#dpkg -i logstash-7.6.2.deb
[root@elk-web1 ~]#vim /etc/systemd/system/logstash.service
[Service]
Type=simple
User=root   #修改用户和组为root,让logstash访问日志文件
Group=root
[root@elk-web1 ~]#cat /etc/logstash/conf.d/tomcat-to-es.conf
input {
  file {
    path => "/var/log/syslog"
    start_position => "beginning"
    stat_interval => "3"
    type => "syslog"
  }
  file {
    path => "/apps/tomcat/logs/localhost_access_log.*.txt"
    start_position => "end"
    stat_interval => "3"
    type => "tomcat-accesslog"
    codec => json
  }
}
output {
if [type] =="syslog" {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "syslog-0.107-%{+YYYY.MM.dd}"
    }
  }
if [type] =="tomcat-accesslog" {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "tomcat-accesslog-0.107-%{+YYYY.MM.dd}"
    }
    file {
      path => "/tmp/tomcat-accesslog-0.107.log"
    }
  }
}
4.4.3.2.2 重启 Logstash 并确认
[root@elk-web1 ~]#systemctl restart logstash  #更改完配置文件重启logstash
[root@elk-web1 ~]#tail -f /var/log/logstash/logstash-plain.log #确保日志无错误
4.4.3.2.3 访问 Tomcat 并生成日志
[root@elk-web1 ~]#tail -1 /apps/tomcat/logs/localhost_access_log.2021-02-02.txt
{"clientip":"10.0.0.1","ClientUser":"-","authenticated":"-","AccessTime":"
[02/Feb/2021:12:34:46 +0800]","method":"GET /favicon.ico
HTTP/1.1","status":"200","SendBytes":"21630","Query?
string":"","partner":"http://10.0.0.107:8080/","AgentVersion":"Mozilla/5.0
(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/88.0.4324.104 Safari/537.36 FS"}
[root@elk-web1 ~]#tail -n 1 /tmp/tomcat-accesslog-0.107.log
{"status":"200","host":"elk-
web1.wang.org","SendBytes":"11156","authenticated":"-
","@version":"1","@timestamp":"2021-02-
02T04:34:56.067Z","path":"/apps/tomcat/logs/localhost_access_log.2021-02-
02.txt","type":"tomcat-accesslog","ClientUser":"-","Query?
string":"","clientip":"10.0.0.1","AccessTime":"[02/Feb/2021:12:34:45
+0800]","AgentVersion":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36
FS","partner":"-","method":"GET / HTTP/1.1"}
4.4.3.2.4 访问 Head 插件验证索引

4.4.3.2.5 在 Kibana 添加索引

4.4.3.2.5.1 在kibana添加 Tomcat 索引

4.4.3.2.5.2 在Kibana 添加 syslog 索引

4.4.3.2.7 验证数据

4.4.3.3 利用 multiline 插件收集 Java 错误日志

Java应用日志有时因为某一个错误会出现很多行错误的日志信息,但这些行都属于同一个日志的信息

为了Elasticsearch 分析方便,需要将多行日志合并成一行日志

使用codec的multiline插件实现多行匹配,而且支持使用what指令灵活的将匹配到的行与前面的行合并或者和后面的行合并

插件链接:

https://www.elastic.co/guide/en/logstash/current/plugins-codecs-multiline.html

多行匹配规则

https://www.elastic.co/guide/en/beats/filebeat/8.3/multiline-examples.html

4.4.3.3.1 实现测试 multiline 插件的配置文件
#测试multiline插件
[root@elk-web1 ~]#cat  /etc/logstash/conf.d/java-log-to-es.conf
input {
  stdin {
    codec => multiline {
      pattern => "^\["#用正则表达式表示以[开头的行
      negate => "true"#匹配正则表达式的行才进行合并,true为匹配不成功进行操作,false为成功
进行操作
      what => "previous"#将正则表达式前面的行进行合并,previous表示与以前的行合并,如果是
下面的行合并就是next
    }
  }
}
output {
  stdout {
    codec => "rubydebug"
  }
}

4.4.3.3.2 测试语法是否正确

# 语法检查

[root@elk-web1 ~]#/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/java-
log-to-es.conf -t
WARNING: Could not find logstash.yml which is typically located in
$LS_HOME/config or /etc/logstash. You can specify the path using --
path.settings. Continuing using the defaults
Could not find log4j2 configuration at path
/usr/share/logstash/config/log4j2.properties. Using default config which logs
errors to the console
[INFO ] 2021-02-0409:52:36.951 [main] writabledirectory - Creating directory
{:setting=>"path.queue", :path=>"/usr/share/logstash/data/queue"}
[INFO ] 2021-02-0409:52:36.974 [main] writabledirectory - Creating directory
{:setting=>"path.dead_letter_queue",
:path=>"/usr/share/logstash/data/dead_letter_queue"}
[WARN ] 2021-02-0409:52:37.345 [LogStash::Runner] multilocal - Ignoring the
'pipelines.yml' file because modules or command line options are specified
[INFO ] 2021-02-0409:52:38.684 [LogStash::Runner] Reflections - Reflections
took 78 ms to scan 1 urls, producing 20 keys and 40 values
Configuration OK
[INFO ] 2021-02-0409:52:40.235 [LogStash::Runner] runner - Using
config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash
4.4.3.3.3 交互式测试插件的标准输入和标准输出
[root@elk-web1 ~]#systemctl stop logstash.service
[root@elk-web1 ~]#/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/java-
log-to-es.conf
WARNING: Could not find logstash.yml which is typically located in
$LS_HOME/config or /etc/logstash. You can specify the path using --
path.settings. Continuing using the defaults
Could not find log4j2 configuration at path
/usr/share/logstash/config/log4j2.properties. Using default config which logs
errors to the console
[WARN ] 2021-02-0409:55:32.095 [LogStash::Runner] multilocal - Ignoring the
'pipelines.yml' file because modules or command line options are specified
[INFO ] 2021-02-0409:55:32.109 [LogStash::Runner] runner - Starting Logstash
{"logstash.version"=>"7.6.2"}
[INFO ] 2021-02-0409:55:32.141 [LogStash::Runner] agent - No persistent UUID
file found. Generating new UUID {:uuid=>"61a9bd43-18df-454c-aef6-3df4b98b4530",
:path=>"/usr/share/logstash/data/uuid"}
[INFO ] 2021-02-0409:55:34.094 [Converge PipelineAction::Create<main>]
Reflections - Reflections took 45 ms to scan 1 urls, producing 20 keys and 40
values
[WARN ] 2021-02-0409:55:35.467 [[main]-pipeline-manager] LazyDelegatingGauge -
A gauge metric of an unknown type (org.jruby.RubyArray) has been created for
key: cluster_uuids. This may result in invalid serialization.  It is recommended
to log an issue to the responsible developer/development team.
[INFO ] 2021-02-0409:55:35.472 [[main]-pipeline-manager] javapipeline -
Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>2,
"pipeline.batch.size"=>125, "pipeline.batch.delay"=>50,
"pipeline.max_inflight"=>250, "pipeline.sources"=>["/etc/logstash/conf.d/java-
log-to-es.conf"], :thread=>"#<Thread:0x3143f68e run>"}
[INFO ] 2021-02-0409:55:36.560 [[main]-pipeline-manager] javapipeline -
Pipeline started {"pipeline.id"=>"main"}
The stdin plugin is now waiting for input:
[INFO ] 2021-02-0409:55:36.671 [Agent thread] agent - Pipelines running
{:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[INFO ] 2021-02-0409:55:36.929 [Api Webserver] agent - Successfully started
Logstash API endpoint {:port=>9600}
line1       #输入测试数据
line2       #输入测试数据
line3       #输入测试数据
[2021-02-04T09:23:20,512][INFO ] test java log #输入测试数据
{
"tags"=> [
        [0] "multiline"
    ],
"message"=> "[\nline1\nline2\nline3",
"host"=> "elk-web1.wang.org",
"@timestamp"=> 2021-02-04T01:58:01.365Z,
"@version"=> "1"
}
line4       #输入测试数据
line5       #输入测试数据
line6       #输入测试数据
[2021-02-04T09:23:20,512][INFO ] test java log2 #输入测试数据
{
"tags"=> [
        [0] "multiline"
    ],
"message"=> "[2021-02-04T09:23:20,512][INFO ] test java
log\nline4\nline5\nline6",
"host"=> "elk-web1.wang.org",
"@timestamp"=> 2021-02-04T01:59:35.338Z,
"@version"=> "1"
}

4.4.3.3.4 配置读取日志文件至标准输出

[root@elk-web1 ~]#cat  /etc/logstash/conf.d/java-log-to-es.conf
input {
  file {
    path => "/data/java-log/es-cluster.log"
    type => "java-error-log"
    start_position => "beginning"
    stat_interval => "3"
    codec => multiline {
      pattern => "^\["
      negate => "true"
      what => "previous"
    }
  }
}
output {
  stdout {
    codec => "rubydebug"
  }
}

4.4.3.3.5 语法验证

#语法检查
[root@elk-web1 ~]#/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/java-
log-to-es.conf  -t
.....
Configuration OK
[INFO ] 2021-02-0411:10:59.275 [LogStash::Runner] runner - Using
config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash
#查看日志输出是否合并日志
[root@elk-web1 ~]#/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/java-
log-to-es.conf
4.4.3.3.6 将输出改为 Elasticsearch
[root@elk-web1 ~]#cat /etc/logstash/conf.d/java-log-to-es.conf
input {
  file {
    path => "/data/java-log/es-cluster.log"
    type => "java-error-log"
    start_position => "beginning"
    stat_interval => "3"
    codec => multiline {
      pattern => "^\["
      negate => "true"
      what => "previous"
    }
  }
}
output {
if [type] =="java-error-log" {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "java-error-log-0.107-%{+YYYY.ww}"#时间格式:年.周
    }
  }
}
[root@elk-web1 ~]#systemctl restart logstash.service
4.4.3.3.7 Head 插件查看索引

4.4.3.3.8 Kibana 界面添加索引

4.4.3.3.9 Kibana 界面查看数据

4.4.4 收集 Nginx Json 格式的日志并输出至 Elasticsearch

filebeat 可以收集json格式的数据

官方说明

https://www.elastic.co/guide/en/beats/filebeat/7.x/filebeat-input-log.html

范例:

  • [root@centos8 ~]#vim /etc/filebeat/filebeat.yml - type: log paths:

  • /var/log/nginx/access_json.log

  • json.keysZ_under_root: true json.overwrite_keys: true

4.4.4.1 部署 Nginx 服务

[root@elk-web1 ~]#wget http://nginx.org/download/nginx-1.18.0.tar.gz
[root@elk-web1 ~]#tar xvf nginx-1.18.0.tar.gz
[root@elk-web1 ~]#cd nginx-1.18.0/
[root@elk-web1 nginx-1.18.0]#./configure  --prefix=/apps/nginx
[root@elk-web1 nginx-1.18.0]#make && make install
4.4.4.2 将 Nginx 日志转换为 Json 格式
[root@elk-web1 ~]#vim /apps/nginx/conf/nginx.conf
user nginx
http {
......
#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  logs/access.log  main;
    log_format access_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"uri":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"tcp_xff":"$proxy_protocol_addr",'
'"http_user_agent":"$http_user_agent",'
'"status":"$status"}';
......
    server {
        access_log   /apps/nginx/logs/nginx.access_json.log access_json;
#access_log  logs/host.access.log  main;
.....
[root@elk-web1 ~]#useradd -r -s /sbin/nologin nginx
[root@elk-web1 ~]#/apps/nginx/sbin/nginx  -t
[root@elk-web1 ~]#/apps/nginx/sbin/nginx
#验证日志格式
[root@elk-web1 ~]#tail -n  1 /apps/nginx/logs/nginx.access_json.log
{"@timestamp":"2021-02-
04T12:18:12+08:00","host":"172.17.180.135","clientip":"61.148.74.134","size":676
46,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-
","http_host":"www.wangxiaochun.com","uri":"/wp-content/uploads/2020/01/favicon-
1.ico","domain":"www.wangxiaochun.com","xff":"-
","referer":"http://www.wangxiaochun.com/","tcp_xff":"","http_user_agent":"Mozil
la/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101
Firefox/85.0","status":"200"}

4.4.4.3 配置 Logstash 收集 Nginx 访问日志

[root@elk-web1 ~]#cat /etc/logstash/conf.d/nginx-log-to-es.conf
input {
  file {
    path => "/apps/nginx/logs/nginx.access_json.log"
    start_position => "beginning"
    stat_interval => "3"
    type => "nginx-accesslog"
    codec => json
  }
  file {
    path => "/apps/nginx/logs/error.log"
    start_position => "beginning"
    stat_interval => "3"
    type => "nginx-errorlog"
  }
}
output {
if [type] =="nginx-accesslog" {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "nginx-accesslog-0.107-%{+YYYY.MM.dd}"
    }
  }
if [type] =="nginx-errorlog" {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "nginx-errorlog-0.107-%{+YYYY.MM.dd}"
    }
  }
}
#语法检查
[root@elk-web1 ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/nginx-log-to-es.conf  -t
#重新启动
[root@elk-web1 ~]#systemctl restart logstash.service

4.4.4.4 利用 Head 插件查看索引

4.4.4.5 Kibana 界面添加索引

4.4.4.5.1 添加 Nginx 访问日志索引

4.4.4.5.2 添加 Nginx 错误日志索引

4.4.4.6 Kibana界面验证数据
4.4.4.6.1 Kibana界面验证 Nginx 访问日志索引

4.4.6.2 Kibana界面验证 Nginx 错误日志索引

4.4.5 基于 TCP/UDP 收集日志并输出至 Elasticsearch

利用logstash的 tcp/udp 插件也可以通过网络接收和收集日志

官方链接:

https://www.elastic.co/guide/en/logstash/current/plugins-inputs-tcp.html
4.4.5.1 准备 Logstash 配置文件先进行收集测试
[root@logstash ~]#cat /etc/logstash/conf.d/tcp-to-es.conf
input {
  tcp {
    port => "9527"
    host => "0.0.0.0"
    type => "tcplog"#可用于判断输出
    codec => json         #如果是json格式,必须加此行,如果不是Json格式,却添加此行也不会影
响结果
    mode => "server"#默认值,可省略
  }
}
output {
if [type] =='tcplog' {
    stdout {
        codec => "rubydebug"
    }
  }
}
[root@logstash ~]#systemctl stop logstash.service
[root@logstash ~]#/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/tcp-
to-es.conf -t
4.4.5.2 验证端口启动成功
[root@logstash ~]#/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/tcp-
to-es.conf
[root@logstash ~]#ss -ntl|grep 9527
LISTEN  0128         [::ffff:10.0.0.107]:9527                  *:*
4.4.5.3 通过 nc 命令测试

NetCat简称nc, 因其功能强大,被称为网络界的“瑞士军刀”,利用nc 可以实现基于TCP或UDP协议传输数据.

#向logstash服务器发送信息
[root@ubuntu1804 ~]#echo "test tcp log" | nc 10.0.0.107 9527
4.4.5.4 验证 Logstash 是否接收到数据
root@logstash ~]#/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/tcp-to-
es.conf
......
[INFO ] 2021-02-0415:40:45.734 [Api Webserver] agent - Successfully started
Logstash API endpoint {:port=>9600}
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/awesome_print-
1.7.0/lib/awesome_print/formatters/base_formatter.rb:31: warning: constant
::Fixnum is deprecated
{
"message"=> "test tcp log",
"@timestamp"=> 2021-02-04T07:41:56.115Z,
"port"=> 37472,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
4.4.5.5 通过 nc 命令发送一个文件
[root@logstash ~]#nc 10.0.0.107 9527 < /etc/os-release
4.4.5.6 Logstash验证数据
[root@elk-web1 ~]#/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/tcp-
to-es.conf
......
{
"message"=> "VERSION=\"18.04.5 LTS (Bionic Beaver)\"",
"@timestamp"=> 2021-02-04T07:44:18.472Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
{
"message"=> "ID_LIKE=debian",
"@timestamp"=> 2021-02-04T07:44:18.473Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
{
"message"=> "VERSION_ID=\"18.04\"",
"@timestamp"=> 2021-02-04T07:44:18.473Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
{
"message"=> "SUPPORT_URL=\"https://help.ubuntu.com/\"",
"@timestamp"=> 2021-02-04T07:44:18.473Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
{
"message"=> "PRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-
and-policies/privacy-policy\"",
"@timestamp"=> 2021-02-04T07:44:18.473Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
{
"message"=> "UBUNTU_CODENAME=bionic",
"@timestamp"=> 2021-02-04T07:44:18.474Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
{
"message"=> "NAME=\"Ubuntu\"",
"@timestamp"=> 2021-02-04T07:44:18.468Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
{
"message"=> "ID=ubuntu",
"@timestamp"=> 2021-02-04T07:44:18.473Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
{
"message"=> "PRETTY_NAME=\"Ubuntu 18.04.5 LTS\"",
"@timestamp"=> 2021-02-04T07:44:18.473Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
  • {
"message"=> "HOME_URL=\"https://www.ubuntu.com/\"",
"@timestamp"=> 2021-02-04T07:44:18.473Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
{
"message"=> "BUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"",
"@timestamp"=> 2021-02-04T07:44:18.473Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
{
"message"=> "VERSION_CODENAME=bionic",
"@timestamp"=> 2021-02-04T07:44:18.473Z,
"port"=> 37474,
"type"=> "tcplog",
"@version"=> "1",
"host"=> "10.0.0.108"
}
4.4.5.7 通过伪设备的方式发送消息

Linux系统中,设备分为块设备和字符设备,而块设备中有硬盘、内存的等对应实体的硬件,但是也有一些设备并不一定要对应物理设备,比如: /dev/null,/dev/zero,/dev/random,/dev/tcp,/dev/udp等, 这种没有对应关系的设备称为伪设备

[root@elk-web2 ~]#echo "伪设备测试" > /dev/tcp/10.0.0.107/9527
4.4.5.8 Logstash 验证数据

[root@elk-web1 ~]#/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/tcpto-es.conf ...... { "message" => " 伪设备测试 ", "@timestamp" => 2021-02-04T08:07:14.484Z, "port" => 37476, "type" => "tcplog", "@version" => "1", "host" => "10.0.0.108" } 4.4.5.9 将输出改为 Elasticsearch将输出改为 Elasticsearch Elasticsearch [root@elk-web1 ~]#cat /etc/logstash/conf.d/tcp-to-es.conf input { tcp { port => "9527" host => "10.0.0.107" type => "tcplog" mode => "server" } } output { if [type] == "tcplog" { elasticsearch { hosts => ["10.0.0.101:9200"] index => "tcplog-0.107-%{+YYYY.MM.dd}" } } } [root@elk-web1 ~]#systemctl restart logstash.service

4.4.5.9 将输出改为 Elasticsearch将输出改为 Elasticsearch Elasticsearch

4.4.5.10 通过 nc 命令或伪设备输入日志
#在任意主机都可以执行下面指令
[root@elk-web2 ~]#echo "伪设备测试1" > /dev/tcp/10.0.0.107/9527
[root@elk-web2 ~]#echo "伪设备测试2" > /dev/tcp/10.0.0.107/9527
[root@elk-web2 ~]#echo "伪设备测试3" > /dev/tcp/10.0.0.107/9527
[root@elk-web2 ~]#nc 10.0.0.107 9527 < /var/log/syslog
4.4.5.11 利用 Head 插件查看

4.4.5.12 在 Kibana 界面添加索引

4.4.5.13 验证数据

4.4.6 通过 Rsyslog 收集 Haproxy 日志并输出至 Elasticsearch

4.4.6.1 rsyslog 日志服务和 syslog 插件介绍

Linux系统中的 rsyslog 提供强大的日志管理功能, 不仅可以收集本机的日志,还可以接受来自各种来源的输入,转换再发送至不同的目标

此外rsyslog的性能也很强,根据官方的介绍,rsyslog(2013年版本)可以达到每秒转发百万条日志的级别

官方网址:http://www.rsyslog.com/

确认系统安装的版本命令如下:

[root@es-node1 ~]#dpkg -l rsyslog
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                              Version               Architecture
Description
+++-=================================-=====================-
=====================-
=======================================================================
ii  rsyslog                           8.32.0-1ubuntu4       amd64
  reliable system and kernel logging daemon

利用 logstash的syslog插件可以收集日志,经常用于收集网络设备的日志,比如:路由器,交换机等

官方链接:

https://www.elastic.co/guide/en/logstash/current/plugins-inputs-syslog.html
https://www.elastic.co/guide/en/logstash/7.x/plugins-inputs-syslog.html
4.4.6.2 安装并配置 Haproxy 的日志
[root@elk-web1 ~]#apt -y install haproxy
[root@elk-web1 ~]#vim /etc/haproxy/haproxy.cfg
global
#log /dev/log   local0         #默认会记录日志到/var/log/haproxy.log中,将此行加注
释
#log /dev/log   local1 notice  #将此行加注释
    log 127.0.0.1 local6  #添加下面一行,发送至本机的514/udp的local6日志级别中
#在文件最后加下面段
listen stats
 mode http
 bind 0.0.0.0:9999
 stats enable
 log global
 stats uri   /haproxy-status
 stats auth  admin:123456
[root@elk-web1 ~]#systemctl restart haproxy.service
#通过浏览器访问haproxy的状态页,生成访问日志

4.4.6.3 编辑 Rsyslog 服务配置文件
#在haproxy主机上配置rsyslog服务
[root@elk-web1 ~]#vim /etc/rsyslog.conf
#取消下面两行的注释,实现接收haproxy的日志
module(load="imudp")
input(type="imudp"port="514")
......
#备份原有haproxy的配置文件
[root@ubuntu2004 rsyslog.d]#mv 49-haproxy.conf  49-haproxy.conf.bak
#加下面行,将haproxy日志再利用UDP或TCP转发到logstash服务器
[root@elk-web1 ~]#cat /etc/rsyslog.d/haproxy.conf
local6.*  @10.0.0.104:514
[root@elk-web1 ~]#systemctl restart haproxy.service  rsyslog
4.4.6.4 编辑 Logstash 配置文件

配置logstash监听一个本地端口作为日志输入源,用于接收从rsyslog服务转发过来的haproxy服务器日志

logstash的服务器监听的IP:端口和rsyslog输出IP和端口必须相同

[root@elk-web1 ~]#cat /etc/logstash/conf.d/haproxy-syslog-to-es.conf
input {
  syslog {
    host => "0.0.0.0"
    port => "514"#指定监听的UDP/TCP端口,注意普通用户无法监听此端口
    type => "haproxy"
  }
}
output {
if [type] =='haproxy' {
    stdout {
        codec => "rubydebug"#默认值,可以省略
    }
  }
}
#修改用户
[root@elk-web1 ~]#vim /etc/systemd/system/logstash.service
User=root
Group=root
4.4.6.5 语法检查
[root@elk-web1 ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/haproxy-syslog-to-es.conf -t
5.4.6.6 启动并验证端口
[root@elk-web1 ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/syslog-to-es.conf
[root@elk-web1 ~]#ss -ntlup|grep 514
udp   UNCONN  000.0.0.0:514  0.0.0.0:*      users:(("java",pid=6975,fd=68))
tcp   LISTEN  050      *:514        *:*      users:(("java",pid=6975,fd=69))
4.4.6.7 Web 访问 haproxy 并验证数据

刷新页面,生成日志信息

#也可以使用logger命令测试生成日志
[root@elk-web2 ~]#logger -p "local6.info" "This is a test log"
#启动logstash
[root@elk-web1 ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/haproxy-syslog-to-es.conf
.....
[INFO ] 2021-02-0418:38:55.133 [Api Webserver] agent - Successfully started
Logstash API endpoint {:port=>9600}
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/awesome_print-
1.7.0/lib/awesome_print/formatters/base_formatter.rb:31: warning: constant
::Fixnum is deprecated
{
"pid"=> "16506",
"facility"=> 22,
"message"=> "Proxy stats started.",
"severity"=> 5,
"type"=> "syslog",
"facility_label"=> "local6",
"severity_label"=> "Notice",
"@timestamp"=> 2021-02-04T10:33:32.000Z,
"program"=> "haproxy",
"priority"=> 181,
"@version"=> "1",
"timestamp"=> "Feb  4 18:33:32",
"logsource"=> "localhost",
"host"=> "10.0.0.108"
}
{
"pid"=> "16507",
"facility"=> 22,
"message"=> "10.0.0.1:11742 [04/Feb/2021:18:41:31.143] stats
stats/<STATS> 0/0/0/0/0 200 10743 - - LR-- 2/2/0/0/0 0/0 \"GET /haproxy-status
HTTP/1.1\"",
"severity"=> 6,
"type"=> "syslog",
"facility_label"=> "local6",
"severity_label"=> "Informational",
"@timestamp"=> 2021-02-04T10:41:31.000Z,
"program"=> "haproxy",
"priority"=> 182,
"@version"=> "1",
"timestamp"=> "Feb  4 18:41:31",
"logsource"=> "localhost",
"host"=> "10.0.0.108"
}
4.4.6.8 将输出改为 Elasticsearch
[root@elk-web1 ~]#cat /etc/logstash/conf.d/haproxy-syslog-to-es.conf
input {
  syslog {
    port => "514"#普通用户无法监听
    host => "0.0.0.0"
    type => "haproxy"
  }
}
output {
if [type] =="haproxy" {
    stdout {
        codec => "rubydebug"
    }
    elasticsearch {
        hosts => ["10.0.0.101:9200","10.0.0.102:9200","10.0.0.103:9200"]
        index => "syslog-haproxy-%{+YYYY.MM.dd}"
    }
  }
}
[root@elk-web1 ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/haproxy-syslog-to-es.conf -t
[root@elk-web1 ~]#systemctl restart logstash.service
4.4.5.9 利用 Head 插件查看

4.4.5.10 Kibana界面添加索引

4.4.5.11 Kibana验证数据

4.4.7 收集应用特定格式的日志输出至 Elasticsearch 并利用 Kibana 展示

4.4.7.1 应用日志收集项目说明

应用的日志格式如下

[root@logstash ~]#head /var/log/mall_app.log
[INFO] 2018-06-2808:08:12 [www.mall.com] - DAU|9136|加入收藏|2018-06-28 01:05:02
[INFO] 2018-06-2808:08:14 [www.mall.com] - DAU|5035|搜索|2018-06-28 01:07:01
[INFO] 2018-06-2808:08:15 [www.mall.com] - DAU|669|使用优惠券|2018-06-28 08:05:13
[INFO] 2018-06-2808:08:19 [www.mall.com] - DAU|2564|搜索|2018-06-28 08:07:08

将日志收集利用 Logstash 进行格式转换后发给 Elasticsearch,并利用Kibana展示

4.4.7.2 实现过程
4.4.7.2.1 配置 Filebeat
[root@web01 ~]#cat /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
- /var/log/mall_app.log
output.logstash:
  hosts: ["logstash.wang.org:6666"]
[root@logstash ~]#systemctl restart filebeat.service

4.4.7.2.2 配置 Logstash

[root@logstash ~]#cat /etc/logstash/conf.d/app_filebeat_filter_es.conf
input {
    beats {
        port =>6666
    }
}
filter {
#mutate 切割操作
    mutate {
#字段分隔符
        split => { "message"=> "|" }
#添加字段
        add_field => {
"user_id"=> "%{[message][1]}"
"action"=> "%{[message][2]}"
"time"=> "%{[message][3]}"
#"[@metadata][target_index]" => "mall-app-%{+YYYY.MM.dd}"
        }
#删除无用字段
        remove_field => ["message"]
#对新添加字段进行格式转换
        convert => {
"user_id"=> "integer"
"action"=> "string"
"time"=> "string"
        }
    }
    date {
        match => ["time", "yyyy-MM-dd HH:mm:ss"]
        target => "@timestamp"
        timezone => "Asia/Shanghai"
    }
}
output {
    stdout {
        codec => rubydebug
    }
    elasticsearch {
        hosts => ["10.0.0.101:9200","10.0.0.102:9200","10.0.0.103:9200"]
        index => "mall-app-%{+YYYY.MM.dd}"
#index => "[@metadata][target_index]"
        template_overwrite => true
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/app_filebeat_filter_es.conf -r
.....
{
"@version"=> "1",
"log"=> {
"file"=> {
"path"=> "/var/log/mall_app.log"
        },
"offset"=> 86
    },
"time"=> "2018-06-28 01:05:02",
"user_id"=> "9136",
"tags"=> [
        [0] "beats_input_codec_plain_applied"
    ],
"@timestamp"=> 2018-06-27T17:05:02.000Z,
"agent"=> {
"version"=> "7.17.5",
"ephemeral_id"=> "19431877-35c9-4429-ab78-8c8de178b05e",
"id"=> "665bed82-0adb-4eb7-ba68-3810c753cb09",
"hostname"=> "web01.wang.org",
"type"=> "filebeat",
"name"=> "web01.wang.org"
    },
"input"=> {
"type"=> "log"
    },
"action"=> "加入收藏",
"ecs"=> {
"version"=> "1.12.0"
    },
"host"=> {
"name"=> "web01.wang.org"
    }
}
4.4.7.2.3 插件查看索引

4.4.7.2.4 Kibana 创建索引模式

4.4.7.2.5 Kibana 展示

5 Kibana 图形显示

5.1 Kibana 介绍

Kibana 是一款开源的数据分析和可视化平台,它是 Elastic Stack 成员之一,设计用于和 Elasticsearch 协作,可以使用 Kibana 对 Elasticsearch 索引中的数据进行搜索、查看、交互操作,您可以很方便的利用图表、表格及地图对数据进行多元化的分析和呈现。

Kibana 可以使大数据通俗易懂。它很简单,基于浏览器的界面便于您快速创建和分享动态数据仪表板来追踪 Elasticsearch 的实时数据变化。

Kibana 基于 TypeScript 语言开发

Kibana 官方下载链接:

https://www.elastic.co/cn/downloads/kibana
https://www.elastic.co/cn/downloads/past-releases#kibana

镜像网站下载链接:

https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x

官方demo

https://demo.elastic.co/

5.2 安装并配置 Kibana

可以通过包或者二进制的方式进行安装,可以安装在独立服务器,或者也可以和elasticsearch的主机安装在一起

注意: Kibana的版本要和 Elasticsearch 相同的版本,否则可能会出错

官方说明:

https://github.com/elastic/kibana

5.2.1 下载安装

5.2.1.1 Ubuntu 安装
[root@es-node1 ~]#wget
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/apt/pool/main/k/kibana/kib
ana-7.6.2-amd64.deb
[root@es-node1 ~]#dpkg -i kibana-7.6.2-amd64.deb
3.2.1.2 CentOS 安装
[root@es-node1 ~]#wget
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/yum/7.6.2/kibana-7.6.2-
x86_64.rpm
[root@es-node1 ~]#yum localinstall kibana-7.6.2-x86_64.rpm

5.2.2 修改配置

[root@es-node1 ~]#vim  /etc/kibana/kibana.yml
[root@es-node1 ~]#grep  "^[a-Z]" /etc/kibana/kibana.yml
server.port: 5601#监听端口,此为默认值
server.host: "0.0.0.0"#修改此行的监听地址,默认为localhost
elasticsearch.hosts: ["http://10.0.0.101:9200"] #修改此行,指向ES任意服务器地址,默认为
localhost
i18n.locale: "zh-CN"#修改此行,使用"zh-CN"显示中文界面,默认英文

5.2.3 启动 Kibana 服务并验证

[root@es-node1 ~]# systemctl enable --now kibana
[root@es-node1 ~]#systemctl status kibana
● kibana.service - Kibana
   Loaded: loaded (/etc/systemd/system/kibana.service; enabled; vendor preset:
enabled)
   Active: active (running) since Sun 2021-01-3111:29:31 CST; 1min 40s ago
 Main PID: 2013 (node)
    Tasks: 11 (limit: 9470)
   CGroup: /system.slice/kibana.service
           └─2013 /usr/share/kibana/bin/../node/bin/node
/usr/share/kibana/bin/../src/cli -c /etc/kibana/kibana.yml
Jan 3111:30:00 es-node1.wang.org kibana[2013]:
{"type":"log","@timestamp":"2021-01-31T03:30:00Z","tags":
["status","plugin:ui_metric@7.6.2","info"],"pid":2
Jan 3111:30:00 es-node1.wang.org kibana[2013]:
{"type":"log","@timestamp":"2021-01-31T03:30:00Z","tags":
["status","plugin:markdown_vis@7.6.2","info"],"pid
Jan 3111:30:00 es-node1.wang.org kibana[2013]:
{"type":"log","@timestamp":"2021-01-31T03:30:00Z","tags":
["status","plugin:metric_vis@7.6.2","info"],"pid":
Jan 3111:30:00 es-node1.wang.org kibana[2013]:
{"type":"log","@timestamp":"2021-01-31T03:30:00Z","tags":
["status","plugin:table_vis@7.6.2","info"],"pid":2
Jan 3111:30:00 es-node1.wang.org kibana[2013]:
{"type":"log","@timestamp":"2021-01-31T03:30:00Z","tags":
["status","plugin:tagcloud@7.6.2","info"],"pid":20
Jan 3111:30:00 es-node1.wang.org kibana[2013]:
{"type":"log","@timestamp":"2021-01-31T03:30:00Z","tags":
["status","plugin:vega@7.6.2","info"],"pid":2013,"
Jan 3111:30:04 es-node1.wang.org kibana[2013]:
{"type":"log","@timestamp":"2021-01-31T03:30:04Z","tags":
["reporting","warning"],"pid":2013,"message":"正在
Jan 3111:30:04 es-node1.wang.org kibana[2013]:
{"type":"log","@timestamp":"2021-01-31T03:30:04Z","tags":
["status","plugin:reporting@7.6.2","info"],"pid":2
Jan 3111:30:04 es-node1.wang.org kibana[2013]:
{"type":"log","@timestamp":"2021-01-31T03:30:04Z","tags":
["listening","info"],"pid":2013,"message":"Server
Jan 3111:30:04 es-node1.wang.org kibana[2013]:
{"type":"log","@timestamp":"2021-01-31T03:30:04Z","tags":
["info","http","server","Kibana"],"pid":2013,"mess
[root@es-node1 ~]#ss -ntlp |grep node
LISTEN   01280.0.0.0:5601             0.0.0.0:*
users:(("node",pid=2013,fd=18))
[root@es-node1 ~]#pstree  -p | grep node
           |-node(2013)-+-{node}(2021)
           |            |-{node}(2028)
           |            |-{node}(2029)
           |            |-{node}(2030)
           |            |-{node}(2031)
           |            |-{node}(2033)
           |            |-{node}(2037)
           |            |-{node}(2038)
           |            |-{node}(2039)
           |            `-{node}(2040)
[root@es-node1 ~]#ps aux |grep node
kibana     201317.9  4.6 1735212375236 ?      Ssl  11:29   0:40
/usr/share/kibana/bin/../node/bin/node /usr/share/kibana/bin/../src/cli -c
/etc/kibana/kibana.yml
root       21250.0  0.0  144361040 pts/0    S+11:33   0:00 grep--
color=auto node
[root@es-node1 ~]#id kibana
uid=113(kibana) gid=116(kibana) groups=116(kibana)

5.3 使用 Kibana

5.3.1 查看和操作Web界面

#浏览器访问下面链接
http://kabana-server:5601

新版界面

旧版界面

#查看状态
http://kabana-server:5601/status

5.3.2 管理索引

输入以下,再执行

GET _search

输入下面内容创建索引并执行

POST/index_wang/_doc/1
{
"username": "wang",
"age": 18,
"title": "cto"
}

查看索引

GET/index_wang/_doc/1

5.3.3 添加之前写入的索引

在logstash 上生成新的索引

[root@logstash ~]#/usr/share/logstash/bin/logstash -e  'input { file { path =>
"/var/log/dpkg.log" start_position => "beginning" stat_interval => "3" } } output
{ elasticsearch {hosts => ["10.0.0.101:9200"] index => "linux-%{+YYYY.MM.dd}"
}}'

查看之前的索引数据

添加索引

输入通配符匹配索引

5.3.4 Kibana 验证数据

如果默认没有显示柱状的图,可能是最近没有写入新的数据,可以查看较长日期当中的数据或者通过 logstash新写入数据即可:

#安装新包的,生成日志
[root@logstash ~]#apt -y install apache2

5.4 通过 Nginx 实现 Kibana 登录安全认证

将 Nginx 作为反向代理服务器,并增加登录用户认证的目的,可以有效避免其他人员随意访问kibana页面。

[root@node1 ~]#vim /etc/kibana/kibana.yml
server.port: 5601
server.host: "127.0.0.1"#修改此行为127.0.0.1
elasticsearch.hosts: ["http://10.0.0.101:9200"]
i18n.locale: "zh-CN"
[root@node1 ~]#systemctl restart kibana
[root@node1 ~]#ss -ntl |grep 5601
LISTEN  0128127.0.0.1:5601            0.0.0.0:*
[root@node1 ~]#apt -y install nginx apache2-utils
[root@node1 ~]#htpasswd -bc /etc/nginx/conf.d/kibana.users admin 123456
[root@node1 ~]#cat /etc/nginx/conf.d/kibana.users
admin:$apr1$kbJ8qki4$aFObR3QixrOCSeYOSpQ0Z1
[root@node1 ~]#cat /etc/nginx/nginx.conf
http {
......
    include /etc/nginx/conf.d/*.conf;
......
[root@node1 ~]#vim  /etc/nginx/conf.d/kibana.conf
[root@node1 ~]#cat /etc/nginx/conf.d/kibana.conf
upstream kibana {
    server 127.0.0.1:5601 max_fails=3fail_timeout=60;
}
server {
    listen 80;
    server_name kibana.wang.org;
    auth_basic "Kibana Website";
    auth_basic_user_file /etc/nginx/conf.d/kibana.users;
    location / {
        proxy_pass http://kibana;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
[root@node1 ~]#nginx -t
[root@node1 ~]#systemctl restart nginx
#名称解析kibana.wang.org后
#浏览器访问:http://kibana.wang.org/
#使用前面创建的用户admin和密码123456登录

5.5.Kibana 可视化画图功能

https://www.elastic.co/guide/cn/kibana/current/introduction.html

Kibana支持多种图形展示功能,需要日志是json格式的支持,具体如下:

5.5.1 lens 可视化

5.5.2 垂直条形图

5.5.4 水平条形图

5.5.5 Markdown

工作安排
| 时间 | 姓名 | 联系电话 |
| ---- | ---- | ---- |
| 周一 | user1 | 1234567890 |
| 周二 | user2 | 1234567890 |
| 周三 | user3 | 1234567890 |
| 周四 | user4 | 1234567890 |
| 周五 | user5 | 1234567890 |
| 周六 | user6 | 1234567890 |
| 周日 | user7 | 1234567890 |

5.5.6 仪表盘图

5.5.7 热力图

5.5.8 面积图

5.5.9 饼状图

5.5.10 数据表 Datatable

可以讲结果导出,再通过excel查看

5.5.11 线图 Line Chart

保存折线图

5.5.12 地图

5.6 Kibana 实现 Dashboard 仪表盘

5.6.1 先利用可视化功能实现多个图形

5.6.2 创建仪表盘

大小和位置都可以调整

5.6.3 共享仪表盘图形

5.6.3.1 方式1: 固定链接

将复制下来的链接地址粘贴至浏览器地址栏,可以访问上面的图形

5.6.3.2 方式2: 嵌入代码 嵌入代码的共享

创建一个html文件,内容如下

[root@elk-web1 ~]#cat dashboard.html
<html>
<head>
<metahttp-equiv=Content-Typecontent="text/html;charset=utf-8">
<title>kibana仪表盘</title>
</head>
<body>
<imgsrc="http://www.wang.com/wp-content/uploads/2017/09/logo.png">
<h1style="color:red">马哥教育运维ELK项目实战</h1>
<iframesrc="http://10.0.0.101:5601/goto/a61616c93be1f64df580ee3f16828173?
embed=true"height="1024"width="1280"></iframe>
</body>
</html>

用浏览器打开此文件,可以看到下面显示

6 ELK 综合实战案例

6.1 Filebeat 收集Nginx日志利用 Redis 缓存发送至 Elasticsearch

利用 Redis 缓存日志数据,主要解决应用解耦,异步消息,流量削锋等问题

将nginx 服务器的logstash收集之后的访问日志写入到redis服务器,然后通过另外的logstash将redis服务器的数据取出在写入到elasticsearch服务器。

官方文档:

https://www.elastic.co/guide/en/logstash/current/plugins-inputs-redis.html
https://www.elastic.co/guide/en/logstash/current/plugins-outputs-redis.html

局限性

不支持Redis 集群,存在单点问题,但是可以多节点负载均衡 Redis 基于内存,因此存放数据量有限

6.1.1 部署 Nginx 服务配置 Json 格式的访问日志

[root@elk-web1 ~]#apt -y install gcc make
[root@elk-web1 ~]#wget http://nginx.org/download/nginx-1.18.0.tar.gz
[root@elk-web1 ~]#tar xvf nginx-1.18.0.tar.gz
[root@elk-web1 ~]#cd nginx-1.18.0/
[root@elk-web1 nginx-1.18.0]#./configure  --prefix=/apps/nginx
[root@elk-web1 nginx-1.18.0]#make && make install
#将nginx访问日志转换为json格式
[root@elk-web1 ~]#vim /apps/nginx/conf/nginx.conf
user nginx
http {
......
#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  logs/access.log  main;
    log_format access_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"uri":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"tcp_xff":"$proxy_protocol_addr",'
'"http_user_agent":"$http_user_agent",'
'"status":"$status"}';
......
    server {
        access_log   /data/nginx/logs/access_json.log access_json;
#access_log  logs/nginx.access.log  main;
.....
[root@elk-web1 ~]#useradd -r -s /sbin/nologin nginx
[root@elk-web1 ~]#mkdir /data/nginx/logs/ -pv
[root@elk-web1 ~]#chown -R nginx.nginx /data/nginx
[root@elk-web1 ~]#/apps/nginx/sbin/nginx  -t
[root@elk-web1 ~]#/apps/nginx/sbin/nginx
#验证访问日志的json格式
[root@elk-web1 ~]#tail -n  1 /data/nginx/logs/access_json.log
{"@timestamp":"2021-02-
04T12:18:12+08:00","host":"172.17.180.135","clientip":"61.148.74.134","size":676
46,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-
","http_host":"www.wangxiaochun.com","uri":"/wp-content/uploads/2020/01/favicon-
1.ico","domain":"www.wangxiaochun.com","xff":"-
","referer":"http://www.wangxiaochun.com/","tcp_xff":"","http_user_agent":"Mozil
la/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101
Firefox/85.0","status":"200"}

6.1.2 安装配置 Redis

[root@redis ~]#apt -y install redis
[root@redis ~]#vim /etc/redis/redis.conf
bind 0.0.0.0
save ""#禁用rdb持久保存
#save 900 1
#save 300 10
#save 60 10000
requirepass 123456
[root@redis ~]#systemctl restart redis

6.1.3 利用 Filebeat 收集日志到 Redis

6.1.3.1 Filebeat 安装
[root@elk-web1 ~]#dpkg -i filebeat-7.6.2-amd64.deb
6.1.3.2 修改 Filebeat 配置
[root@elk-web2 ~]#cat /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
- /var/log/nginx/access_json.log
  json.keys_under_root: true#默认False会将json数据存储至message,改为true则会独立
message外存储
  json.overwrite_keys: true#设为true,覆盖默认的message字段,使用自定义json格式中的key
  tags: ["nginx-access"]
- type: log
  enabled: true
  paths:
- /var/log/nginx/error.log
  tags: ["nginx-error"]
- type: log
  enabled: true
  paths:
- /var/log/syslog
  tags: ["syslog"]
output.redis:
  hosts: ["10.0.0.105:6379"]
  password: "123456"
  db: "0"
  key: "filebeat"#所有日志都存放在key名称为filebeat的列表中,llen filebeat可查看长度,
即日志记录数
#也可以用下面的列表方式实现不同日志存放在不同的key
#keys:
#  - key: "nginx_access"
#    when.contains:
#    tags: "access"
#  - key: "nginx_error"
#    when.contains:
#    tags: "error"
6.1.3.3 启动 filebeat 服务
[root@elk-web2 ~]#systemctl enable --now filebeat.service

6.1.4 安装并配置logstash收集Redis数据发送至Elasticsearch

[root@logstash ~]#apt -y install openjdk-8-jdk
[root@logstash ~]#wget
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/apt/pool/main/l/logstash/l
ogstash-7.6.2.deb
[root@logstash ~]#dpkg -i logstash-7.6.2.deb
[root@logstash ~]#vim /etc/logstash/conf.d/redis-to-es.conf
input {
  redis {
    host => "10.0.0.105"
    port => "6379"
    password => "123456"
    db => "0"
    key => "filebeat"
    data_type => "list"
  }
#如果有多个key,用下面形式,从而实现将每个不同的key由不同的logstash消费,实现负载均衡
#redis {
#  host => ["10.0.0.105"]
#  port => "6379"
#  password => "123456"
#  data_type => "list"
#  key => "nginx_access"
#  db => "0"
#}
#redis {
#  host => ["10.0.0.105"]
#  port => "6379"
#  password => "123456"
#  data_type => "list"
#  key => "nginx_error"
#  db => "0"
#}
}
#filter {
#  mutate {
#    convert => ["upstreamtime","float"]
#  }
#}
output {
if"syslog"in [tags] {
        elasticsearch {
            hosts => ["10.0.0.101:9200"]
            index => "syslog-%{+YYYY.MM.dd}"
        }
    }
if"nginx-access"in [tags] {
        elasticsearch {
            hosts => ["10.0.0.101:9200","10.0.0.102:9200","10.0.0.103:9200"]
            index => "nginx-accesslog-%{+YYYY.MM.dd}"
            template_overwrite => true
        }
    }
if"nginx-error"in [tags] {
        elasticsearch {
            hosts => ["10.0.0.101:9200"]
            index => "nginx-errorlog-%{+YYYY.MM.dd}"
            template_overwrite => true
       }
    }
}
[root@logstash ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/redis-to-es.conf -t
[root@logstash ~]#systemctl restart logstash

6.1.5 通过 Head 插件查看索引

6.1.6 通过 Kibana 创建索引模式查看

6.1.6.1 创建索引模式

6.1.6.2 查看索引

6.1.7 监控 Redis 数据长度

实际生产环境当中,利用Redis 缓存日志,logstash由于性能等原因未能及时提取日志,可能会出现 Redis 当中堆积了大量的数据, 导致redis服务器的内存被大量使用,甚至出现内存即将被使用完毕的情景, 可以通过脚本程序监控redis 中key的长度,达到阈值进行及时报警

6.1.7.1 python脚本内容
[root@redis ~]#apt -y install python3-pip
[root@redis ~]#pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple redis
[root@redis ~]#cat check_key_length.py
#!/usr/bin/python3
#coding:utf-8
import redis
def redis_key_len():
pool=redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="123456")
  conn = redis.Redis(connection_pool=pool)
  data = conn.llen('filebeat')
  print(data)
redis_key_len()
[root@redis ~]#python3 check_key_length.py
737
4.8.7.2 shell 脚本内容
[root@redis ~]#cat check_key_length.sh
#!/bin/bash
#
#********************************************************************
#Author:            wangxiaochun
#QQ:                29308620
#Date:              2021-02-09
#FileName:          check_key_length.sh
#URL:               http://www.wangxiaochun.com
#Description:       The test script
#Copyright (C):     2021 All rights reserved
#********************************************************************
WARNING=10
REDIS=127.0.0.1
PASSWORD=123456
DB=0
for key in`redis-cli -h $REDIS -a $PASSWORD -n $DB keys '*' `;do
length=`redis-cli -h $REDIS -a $PASSWORD -n $DB -a 123456 -n 1 llen $key`
#    echo $length
if [ $length-gt$WARNING ];then
echo"$key is too big,length:$length"
fi
done

6.2 Filebeat 收集Nginx日志并写入 Kafka 缓存发送至 Elasticsearch

虽然利用redis 可以实现elasticsearch 缓存功能,减轻elasticsearch的压力,但不支持的redis集群,存在单点问题,可以利用kafka代替redis,且支持kafka集群,消除单点故障隐患

官方文档

https://www.elastic.co/guide/en/beats/filebeat/7.6/kafka-output.html

6.2.1 环境准备

#三台ES集群
10.0.0.101
10.0.0.102
10.0.0.103
#logstash
10.0.0.104 logstash1
10.0.0.105 logstash2
#准备三台kafka,安装过程略
10.0.0.201
10.0.0.202
10.0.0.203
#filebeat和nginx
10.0.0.106

[root@node1 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
[root@node2 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: leader
[root@node3 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower

6.2.2 Filebeat 收集 Nginx 的访问和错误日志并发送至 kafka

[root@web1 ~]#grep -Ev "#|^$" /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
- /var/log/nginx/access_json.log
  json.keys_under_root: true
  json.overwrite_keys: true
  tags: ["nginx-access"]
- type: log
  enabled: true
  paths:
- /var/log/nginx/error.log
  tags: ["nginx-error"]
- type: log
  enabled: true
  paths:
- /var/log/syslog
  tags: ["syslog"]
output.kafka:
  hosts: ["10.0.0.201:9092", "10.0.0.202:9092", "10.0.0.203:9092"]
  topic: filebeat-log   #指定kafka的topic
  partition.round_robin:
    reachable_only: true#true表示只发布到可用的分区,false时表示所有分区,如果一个节点
down,会block
  required_acks: 1#如果为0,错误消息可能会丢失,1等待写入主分区(默认),-1等待写入副本分
区
  compression: gzip
  max_message_bytes: 1000000#每条消息最大长度,以字节为单位,如果超过将丢弃
[root@web1 ~]#systemctl restart filebeat.service

6.2.3 配置 Logstash 发送读取 Kafka 日志到 Elasticsearch

[root@logstash ~]#cat /etc/logstash/conf.d/kafka-to-es.conf
input {
  kafka {
    bootstrap_servers => "10.0.0.201:9092,10.0.0.202:9092,10.0.0.203:9092"
    topics => "filebeat-log"
    codec => "json"
#group_id => "logstash"  #消费者组的名称
#consumer_threads => "3" #建议设置为和kafka的分区相同的值为线程数
#topics_pattern => "nginx-.*" #通过正则表达式匹配topic,而非像上面topics=>指定固定
值
  }
}
output {
#stdout {}   #调试使用
if"nginx-access"in [tags] {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "logstash-kafka-nginx-accesslog-%{+YYYY.MM.dd}"
    }
  }
if"nginx-error"in [tags] {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "logstash-kafka-nginx-errorlog-%{+YYYY.MM.dd}"
    }
  }
if"syslog"in [tags] {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "logstash-kafka-syslog-%{+YYYY.MM.dd}"
    }
  }
}
[root@logstash ~]#systemctl restart logstash.service

6.2.4 验证结果

利用 kafka tool 工具查看

6.3 通过坐标地图统计网站访问用户的 IP 所在城市

注意: 地图功能要求必须使用 logstash 开头的索引名称

6.3.1 下载并解压地址数据文件

先获取IP数据库两种方式

官方网站

elasticsearch和logstash包内置

官方网站链接

https://www.maxmind.com/

早期直接下载,现在必须注册登录后,在用户帐户页面下载

https://dev.maxmind.com/geoip/geolite2-free-geolocation-data?lang=en

[root@es-node1 ~]#wget
'https://download.maxmind.com/app/geoip_download_by_token?edition_id=GeoLite2-
City&date=20210202&suffix=tar.gz&token=v2.local.BgAHbu3hNj12U4MC0BNR1IEHJmykzhP3
eNMAtADgDcjcwc4AI4uShA3KLgabS1tian8XFMNpsULdUSlkyiJcJvl0rKQ3zvrAuDBLRIUGwml6_ewl
R24scqvtUK79oQ1HG0YmhSPHiPJsJsi93K-_8Jz4b5HFkCFSbnfvlTfes6j7MlLW01tks4SGviCb1u-
6r-8_8A' -O GeoLite2-City_`date +%Y%M%d`.tar.gz
[root@logstash1 ~]#ll -h GeoLite2-City_20210202.tar.gz
-rw-r--r--1 root root 29M Feb  923:03 GeoLite2-City_20210202.tar.gz
[root@logstash1 ~]#tar xf GeoLite2-City_20210202.tar.gz  -C /etc/logstash/
[root@logstash1 ~]#ln -s /etc/logstash/GeoLite2-City_20210202/
/etc/logstash/GeoLite2-City
[root@logstash1 ~]#ll -h /etc/logstash/GeoLite2-City/GeoLite2-City.mmdb
-rw-r--r--1 root root 59M Feb  300:01 /etc/logstash/GeoLite2-City/GeoLite2-
City.mmdb

范例:elasticsearch和logstash 包内置数据库

[root@ubuntu1804 ~]#dpkg -L elasticsearch |grep GeoLite2-City.mmdb|xargs ls -lh
-rw-r--r--1 root root 60M Mar 262020 /usr/share/elasticsearch/modules/ingest-
geoip/GeoLite2-City.mmdb
[root@ubuntu1804 ~]#dpkg -L logstash |grep GeoLite2-City.mmdb|xargs ls -lh
-rw-r--r--1 logstash logstash 59M Mar 262020
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-filter-geoip-6.0.3-
java/vendor/GeoLite2-City.mmdb

6.3.2 配置 Filebeat 配置文件

[root@centos8 ~]#cat /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
- /var/log/nginx/access_json.log
  json.keys_under_root: true
  json.overwrite_keys: true
  tags: ["nginx-access"]
- type: log
  enabled: true
  paths:
- /var/log/nginx/error.log
  tags: ["nginx-error"]
- type: log
  enabled: true
  paths:
- /var/log/syslog
  tags: ["syslog"]
output.kafka:
  hosts: ["10.0.0.201:9092", "10.0.0.202:9092", "10.0.0.203:9092"]
  topic: filebeat-log
  partition.round_robin:
    reachable_only: true
  required_acks: 1
  compression: gzip
  max_message_bytes: 1000000

6.3.2 配置 Logstash 使用地址库

#使用Logstash内置的地图库
[root@ubuntu1804 ~]#cp
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-filter-geoip-6.0.3-
java/vendor/GeoLite2-City.mmdb /etc/logstash/conf.d/
[root@ubuntu1804 ~]#ls -lh /etc/logstash/conf.d/
total 59M
-rw-r--r--1 root root  59M Aug 2708:50 GeoLite2-City.mmdb
-rw-r--r--1 root root 1.2K Aug 2710:59 kafka-to-es.conf
[root@logstash ~]#cat /etc/logstash/conf.d/kafka-to-es.conf
input {
  kafka {
    bootstrap_servers => "10.0.0.201:9092,10.0.0.202:9092,10.0.0.203:9092"
    topics => "filebeat-log"
    codec => "json"
  }
}
filter {
if"nginx-access"in [tags] {
    geoip {
source=> "clientip"#日志必须是json格式,且有一个clientip的key
      target => "geoip"
#database => "/etc/logstash/conf.d/GeoLite2-City.mmdb"    #指定数据库文件
#add_field => ["[geoip][coordinates]", "%{[geoip][longitude]}"] #添加经纬度字
段包括经度
#add_field => ["[geoip][coordinates]", "%{[geoip][latitude]}"] #添加经纬度字
段包括纬度
    }
#mutate {
#convert => [ "[geoip][coordinates]", "float"]       #转换经纬度为浮点数
#}
  }
}
output {
#stdout {}   #调试使用
if"nginx-access"in [tags] {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "logstash-kafka-nginx-accesslog-%{+YYYY.MM.dd}"
#注意: 地图功能要求必须使用 logstash 开头的索引名称
    }
  }
if"nginx-error"in [tags] {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "logstash-kafka-nginx-errorlog-%{+YYYY.MM.dd}"
    }
  }
if"syslog"in [tags] {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "logstash-kafka-syslog-%{+YYYY.MM.dd}"
    }
  }
}

6.3.4 写入 Nginx 的访问日志数据

[root@elk-web1 ~]#tail -n 1000 json.log  >>
/data/nginx/logs/nginx.access_json.log

6.3.5 Head 插件确认索引成功

6.3.6 Kibana 创建索引模式

确认出现geoip 相关字段

6.3.7 Kibana 创建地图数据

创建地图

6.4 Logstash收集日志写入 MySQL 数据库

ES中的日志后续会被删除,但有些重要数据,比如状态码、客户端IP、客户端浏览器版本等,后期可以会按月或年做数据统计等,因此需要持久保存

可以将重要数据写入数据库达到持久保存目的

6.4.1 安装 MySQL 数据库

[root@es-node1 ~]#apt -y install mysql-server
[root@es-node1 ~]#ss -ntl|grep 3306
LISTEN   080127.0.0.1:3306             0.0.0.0:*
[root@es-node1 ~]#vim /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address            =0.0.0.0
[root@es-node1 ~]#systemctl restart mysql.service
[root@es-node1 ~]#ss -ntl|grep 3306
LISTEN   0800.0.0.0:3306             0.0.0.0:*

6.4.2 创建库和表并授权用户登录

[root@es-node1 ~]#mysql
mysql> createdatabase elk characterset utf8 collate utf8_bin;
mysql> createuser elk@"10.0.0.%" identified by'123456';
mysql> grantallprivilegeson elk.* to elk@"10.0.0.%";
mysql> flushprivileges;
mysql> use elk
#创建表,字段对应需要保存的数据字段
mysql> createtable elklog (clientip varchar(39),responsetime float(10,3),uri
varchar(256),statuschar(3),timetimestampdefaultcurrent_timestamp );
mysql> desc elklog;

|+--------------+--------------
|Field | Type|+------+-----+-------------------+-------+
|Null |Key |Default | Extra || |---|---| |+--------------+--------------
| clientip |varchar(39)|+------+-----+-------------------+-------+
| YES | |NULL | || || responsetime |float(10,3)|| YES | |NULL | || || uri |varchar(256)|| YES | |NULL | || ||status |char(3)|| YES | |NULL | || ||time |timestamp||NO | |CURRENT_TIMESTAMP | || |+--------------+--------------
5 rowsin set (0.00 sec)|+------+-----+-------------------+-------+|

6.4.3 测试用户从 Logstash 主机远程登录

[root@logstash1 ~]#apt -y install mysql-client
[root@logstash1 ~]#mysql -uelk -p123456 -h10.0.0.101 -e 'show databases'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| elk                |
+--------------------+
[root@logstash1 ~]#

6.4.4 Logstash 配置 mysql-connector-java包

MySQL Connector/J是MySQL官方JDBC驱动程序,JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。

官方下载地址:https://dev.mysql.com/downloads/connector/

[root@logstash1 ~]#dpkg -i mysql-connector-java_8.0.23-1ubuntu18.04_all.deb
[root@logstash1 ~]#dpkg -L mysql-connector-java
/.
/usr
/usr/share
/usr/share/doc
  • /usr/share/doc/mysql-connector-java

  • /usr/share/doc/mysql-connector-java/CHANGES.gz

/usr/share/doc/mysql-connector-java/INFO_BIN
/usr/share/doc/mysql-connector-java/INFO_SRC
/usr/share/doc/mysql-connector-java/LICENSE.gz
/usr/share/doc/mysql-connector-java/README
/usr/share/doc/mysql-connector-java/changelog.Debian.gz
/usr/share/doc/mysql-connector-java/copyright
/usr/share/java
/usr/share/java/mysql-connector-java-8.0.23.jar
[root@logstash1 ~]#mkdir -p  /usr/share/logstash/vendor/jar/jdbc
[root@logstash1 ~]#cp /usr/share/java/mysql-connector-java-8.0.23.jar
/usr/share/logstash/vendor/jar/jdbc/
#如果logstash以root运行,下面可不做
[root@logstash1 ~]#chown -R logstash.logstash /usr/share/logstash/vendor/jar/
[root@logstash1 ~]#ll -h /usr/share/logstash/vendor/jar/jdbc/
total 2.4M
drwxr-xr-x 2 logstash logstash 4.0K Aug 2720:25 ./
drwxr-xr-x 3 logstash logstash 4.0K Aug 2720:25 ../
-rw-r--r--1 logstash logstash 2.4M Aug 2720:25 mysql-connector-java-8.0.23.jar

6.4.5 更改 Gem 源

Logstash 基于 Ruby 语言实现

ruby 语言使用国外的gem源, 由于网络原因,从国内访问很慢而且不稳定

其官方介绍推荐使用

https://gems.ruby-china.com

[root@logstash1 ~]#apt -y install ruby
[root@logstash1 ~]#gem -v
2.7.6
#修改指定国内的源
[root@logstash1 ~]#gem sources --add https://gems.ruby-china.com/ --remove
https://rubygems.org/
[root@logstash1 ~]#gem sources -l
*** CURRENT SOURCES ***
https://gems.ruby-china.com/

6.4.6 安装配置插件

#查看logstash-plugin帮助
[root@logstash1 ~]#/usr/share/logstash/bin/logstash-plugin --help
.......
Usage:
    bin/logstash-plugin [OPTIONS] SUBCOMMAND [ARG] ...
Parameters:
    SUBCOMMAND                    subcommand
    [ARG] ...                     subcommand arguments
Subcommands:
    list                          List all installed Logstash plugins
    install                       Install a Logstash plugin
    remove                        Remove a Logstash plugin
    update                        Update a plugin
    pack                          Package currently installed plugins,
Deprecated: Please use prepare-offline-pack instead
    unpack                        Unpack packaged plugins, Deprecated: Please use
prepare-offline-pack instead
    generate                      Create the foundation for a new plugin
    uninstall                     Uninstall a plugin. Deprecated: Please use
remove instead
    prepare-offline-pack          Create an archive of specified plugins to use
for offline installation
Options:
-h, --help                    print help
#查看安装拆插件,默认只有input-jdbc插件,需要安装output-jdbc插件
[root@logstash1 ~]#/usr/share/logstash/bin/logstash-plugin list|grep jdbc
......
logstash-integration-jdbc
 ├── logstash-input-jdbc
 ├── logstash-filter-jdbc_streaming
 └── logstash-filter-jdbc_static
#安装output-jdbc插件,可能会等较长时间
[root@logstash1 ~]#/usr/share/logstash/bin/logstash-plugin install  logstash-
output-jdbc
......
Validating logstash-output-jdbc
Installing logstash-output-jdbc

Installation successful

# 检查插件安装成功

[root@logstash1 ~]#/usr/share/logstash/bin/logstash-plugin list|grep jdbc
.....
logstash-integration-jdbc
 ├── logstash-input-jdbc
 ├── logstash-filter-jdbc_streaming
 └── logstash-filter-jdbc_static
logstash-output-jdbc

6.3.7 配置 Filebeat 配置文件

[root@centos8 ~]#cat /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
- /var/log/nginx/access_json.log
  json.keys_under_root: true
  json.overwrite_keys: true
  tags: ["nginx-access"]
- type: log
  enabled: true
  paths:
- /var/log/nginx/error.log
  tags: ["nginx-error"]
- type: log
  enabled: true
  paths:
- /var/log/syslog
  tags: ["syslog"]
output.kafka:
  hosts: ["10.0.0.201:9092", "10.0.0.202:9092", "10.0.0.203:9092"]
  topic: filebeat-log
  partition.round_robin:
    reachable_only: true
  required_acks: 1
  compression: gzip
  max_message_bytes: 1000000

6.4.8 配置 Logstash 将日志写入数据库

[root@ubuntu1804 ~]#ls -lh /etc/logstash/conf.d/
total 59M
-rw-r--r--1 root root  59M Aug 2708:50 GeoLite2-City.mmdb
-rw-r--r--1 root root 1.2K Aug 2710:59 kafka-to-es.conf
[root@logstash ~]#cat /etc/logstash/conf.d/kafka-to-es.conf
input {
  kafka {
    bootstrap_servers => "10.0.0.201:9092,10.0.0.202:9092,10.0.0.203:9092"
    topics => "filebeat-log"
    codec => "json"
  }
}
filter {
if"nginx-access"in [tags] {
    geoip {
source=> "clientip"#日志必须是json格式且有一个clientip的key
      target => "geoip"
      database => "/etc/logstash/conf.d/GeoLite2-City.mmdb"#指定数据库文件
      add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ]   #经度
      add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ]    #纬度
    }
    mutate {
      convert => [ "[geoip][coordinates]", "float"]
    }
  }
}
output {
#stdout {}   #调试使用
if"nginx-access"in [tags] {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "logstash-kafka-nginx-accesslog-%{+YYYY.MM.dd}"
    }
    jdbc {
      connection_string => "jdbc:mysql://10.0.0.101/elk?
user=elk&password=123456&useUnicode=true&characterEncoding=UTF8"
      statement => ["INSERT INTO elklog (clientip,responsetime,uri,status)
VALUES(?,?,?,?)","clientip","responsetime","uri","status"]
    }
  }
if"nginx-error"in [tags] {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "logstash-kafka-nginx-errorlog-%{+YYYY.MM.dd}"
    }
  }
if"syslog"in [tags] {
    elasticsearch {
      hosts => ["10.0.0.101:9200"]
      index => "logstash-kafka-syslog-%{+YYYY.MM.dd}"
    }
  }
}

6.4.9 检查 Logstash 配置并重启服务

[root@logstash1 ~]#/usr/share/logstash/bin/logstash -f
/etc/logstash/conf.d/kafka-to-es.conf -t
[root@logstash1 ~]#systemctl restart logstash.service

6.4.10 访问 Nginx 产生日志

[root@elk-web1 logs]#tail -n 1000 json.log  >>
/data/nginx/logs/nginx.access_json.log

6.4.11 验证数据库是否写入数据

[root@es-node1 ~]#mysql elk
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 30
Server version: 5.7.33-0ubuntu0.18.04.1 (Ubuntu)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h'for help. Type '\c' to clear the current input statement.
mysql> select * from elklog limit 10;
+----------------+--------------+-------------------------------------------+---
-----+---------------------+
| clientip       | responsetime | uri                                       |
status | time                |
+----------------+--------------+-------------------------------------------+---
-----+---------------------+
| 43.227.255.245 | 0.04         | /index.php                                |
200    | 2021-02-1023:27:48 |
| 43.227.255.245 | 0.0          | /wp-content/uploads/2020/01/favicon-1.ico |
200    | 2021-02-1023:27:48 |
| 43.227.255.245 | 0.0          | /wp-content/uploads/2020/01/favicon-1.ico |
200    | 2021-02-1023:27:48 |
| 43.227.255.245 | 0.0          | /wp-content/uploads/2020/01/favicon-1.ico |
200    | 2021-02-1023:27:48 |
| 43.227.255.245 | 0.0          | /wp-content/uploads/2020/01/favicon-1.ico |
200    | 2021-02-1023:27:48 |
| 43.227.255.245 | 0.0          | /wp-content/uploads/2020/01/favicon-1.ico |
200    | 2021-02-1023:27:48 |
| 43.227.255.245 | 0.0          | /wp-content/uploads/2020/01/favicon-1.ico |
200    | 2021-02-1023:27:48 |
| 43.227.255.245 | 0.0          | /wp-content/uploads/2020/01/favicon-1.ico |
200    | 2021-02-1023:27:48 |
| 43.227.255.245 | 0.044        | /wp-content/uploads/2020/01/favicon-1.ico |
200    | 2021-02-1023:27:48 |
| 123.56.174.200 | 0.0          | /wp-cron.php                              |
499    | 2021-02-1023:27:48 |
+----------------+--------------+-------------------------------------------+---
-----+---------------------+
10 rows inset (0.00 sec)

7 常见面试题

简述ELK的部署架构和工作原理