根据官方文档以及其他资料翻译和总结而来:Getting started with the Elastic Stack
嘿,你在寻找如何快速安装和配置ELK的教程吗?来对地方了!你可以在单台虚拟机上安装ELK,甚至可以在你的笔记本上快速搭建一个学习坏境!
- Elasticsearch
- Kibana
- Beats
Logstash可以提供强大的数据解析和传输功能,但不是必须安装的,如果你需要Logstash,参考:Getting Started with Logstash.
ELK介绍
你为什么需要ELK?
我们在引入一个技术栈之前,务必考虑清楚,你为什么需要这个东西,否则会给日后的维护工作埋下隐患。
日常工作中,经常有分析线上日志的需求,对于Linux老手使用grep awk这些工具就可以轻松获得想要的信息。但是这种方法仅限于规模较小的应用,一旦应用规模较大,日志往往分散在多个系统之中,排查起来就非常的困难了。
如果有这样一个系统,可以将我们所有应用的日志都集中到一起,并且进行一些加工处理,便于检索,那么问题就迎刃而解了。ELk就是目前业界主流的日志系统,它提供了一整套的技术栈,且都是同一家公司的产品,彼此间可以完美衔接。
为什么叫ELK?
ELK日志系统需要用到组件有下面这些:
- Elasticsearch:基于Lucence的开源分布式搜索引擎,提供搜集、分析、存储数据的功能
- Logstash:提供日志的搜集、分析、过滤功能
- Kibana:Kibana可以为Logtash和Elasticsearch提供友好的UI界面,用于数据的可视化展示
Beats:
- Packetbeat:采集网络数据
- Metricbeat:采集系统指标,如CPU、MEM占用等
- Filebeat:采集日志文件
- Winlogbeat:采集Windows时间日志
- Auditbeat:采集审计日志
- Heartbeat:运行状态监控
由于Logstash过于笨重,Elastic家族产生了一个叫Beats的工具,用于代替Logstash Forwoarder进行轻量级的日志采集,因此Elastic也将ELK Stack改名为Elastic Stack。
Elastic Stack 单节点部署
安装前准备
需要一台安装CentOS的主机,由于Elastic是运行在JVM上的,对于内存的需求比较大,并且为了快速索引都会用到内存缓存,所以内存越大越好。
我使用的配置为:8核心处理器 16GB内存 1TB数据硬盘。
在使用Elastic Stack时,每个组件的版本必须保持一致,以获得最大的兼容性和稳定性。
本文创作时稳定版本为:7.15.0,因此每个组件的版本为:
- Elasticsearch-7.15.0
- Logstash-7.15.0
- Kibana-7.15.0
- Filebeat-7.15.0
安装组件
Elastic提供了主流操作系统的预编译包,尽量使用这些包进行快速安装,也便于后续的升级和管理。对于比较冷门的系统,才建议使用通用二进制或者源码编译的方式安装。
对于CentOS使用的RPM包管理工具,Elastic Stack提供了对应YUM源,如果服务器具有网络访问权限,建议通过添加YUM源的方式安装。如果是内网环境,可以预先下载RPM包,然后上传安装。
方式1、使用YUM源安装
导入公钥:
rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
添加仓库:
cat << EOF > /etc/yum.repos.d/elastic.repo
[elastic-7.x]
name=Elastic repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF
安装本指南中所需组件:
yum install elasticsearch kibana filebeat logstash
方式2、下载RPM包安装
下载链接:
# 证书
https://artifacts.elastic.co/GPG-KEY-elasticsearch
https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.15.0-x86_64.rpm
https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.15.0-x86_64.rpm
https://artifacts.elastic.co/downloads/kibana/kibana-7.15.0-x86_64.rpm
https://artifacts.elastic.co/downloads/logstash/logstash-7.15.0-x86_64.rpm
安装:
# 导入证书
rpm --import GPG-KEY-elasticsearch
rpm -ivh elasticsearch-7.15.0-x86_64.rpm
rpm -ivh filebeat-7.15.0-x86_64.rpm
rpm -ivh kibana-7.15.0-x86_64.rpm
rpm -ivh logstash-7.15.0-x86_64.rpm
配置Elasticsearch
配置文件目录:/etc/elasticsearch
配置完成后的有效配置:
grep -Ev '^$|^#' /etc/elasticsearch/elasticsearch.yml
cluster.name: ELK-Cluster
node.name: node-standalone
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 172.16.243.160
http.port: 9200
discovery.type: single-node
network.host
,Elasticsearch默认只能使用localhost进行访问,如果需要在其他主机上向Elasticsearch发送数据,需要修改绑定地址,一般配置为所使用网卡的IP,也可以配置成0.0.0.0
绑定所有接口。
discovery.type
,需要自己添加到配置文件中,设置为single-node可以避免Elasticsearch扫描网络中的其他节点。
path.data
、path.logs
,这两个参数需要注意,根据Elasticsearch数据量考虑,配置到容量足够的目录。
启动Elasticsearch并且配置自动运行:
systemctl enable --now elasticsearch
测试Elasticsearch:
curl http://localhost:9200
如果看到类似下面的返回结果就说明成功了。
{
"name" : "node-standalone",
"cluster_name" : "ELK-Cluster",
"cluster_uuid" : "Y00Y4qzbQAqqbuVQjsCMGQ",
"version" : {
"number" : "7.15.0",
"build_flavor" : "default",
"build_type" : "rpm",
"build_hash" : "79d65f6e357953a5b3cbcc5e2c7c21073d89aa29",
"build_date" : "2021-09-16T03:05:29.143308416Z",
"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"
}
配置Kibana
配置文件目录:/etc/kibana
配置完成后的有效配置:
grep -Ev '^$|^#' /etc/kibana/kibana.yml
server.port: 5601
server.host: "172.16.243.160"
server.basePath: "/"
server.publicBaseUrl: "http://172.16.243.160:5601/"
server.name: "ELK Stack"
elasticsearch.hosts: ["http://172.16.243.160:9200"]
i18n.locale: "zh-CN"
server.host
,Kibana默认也是只能通过localhost访问,需要配置成具体接口IP或者是0.0.0.0
绑定所有接口。
server.basePath
、server.publicBaseUrl
,用于配置对外访问地址,如果不配置页面会有警告信息,最好配置一下。publicBaseUrl
和basePath
保持一致,也可以添加前缀用于反向代理,例如:
server.basePath: "/elk/"
server.publicBaseUrl: "http://172.16.243.160:5601/elk/"
启动Kibana并且配置自动运行:
systemctl enable --now kibana
使用浏览器访问,例如:http://172.16.243.160:5601。
配置FileBeat
配置文件目录:/etc/filebeat
配置完成后的有效配置:
grep -Ev '^$|#|^#' /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
enabled: false
paths:
- /var/log/*.log
- type: filestream
enabled: false
paths:
- /var/log/*.log
filebeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: false
setup.template.settings:
index.number_of_shards: 1
setup.kibana:
host: "172.16.243.160:5601"
output.elasticsearch:
hosts: ["172.16.243.160:9200"]
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- add_cloud_metadata: ~
- add_docker_metadata: ~
- add_kubernetes_metadata: ~
setup.kibana.host
,用于载入仪表盘,可以不配置。
在filebeat.inputs
中启用了log类型的采集器,采集/var/log/*.log
目录下的所有日志文件,这里主要用于测试目的,可以根据实际需要配置你想要采集的日志目录。
filebeat还附带了一些集成的模块,这些模块会根据当前操作系统,寻找默认的日志目录进行采集,下面看一个简单的示例:
查看可用的模块:
filebeat modules list
启用nginx模块:
filebeat modules enable nginx
模块的配置信息在/etc/filebeat/modules.d
目录下,启用模块实质是就是将文件后缀.disabled
移除,可以根据需要修改这些模块,或者添加自己的模块。我们查看nginx模块默认的采集目录。
- module: nginx
access:
var.paths: ["/var/log/nginx/access.log*"]
查看所有的模块使用方法:Modules
启动Filebeat并且配置为自动运行:
systemctl enable --now filebeat
打开Kibana页面,点击Discover,选择filebeat-*
索引,查看是否有数据,如果看不到数据,将时间范围设置大一点。
配置Metricbeat
curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-7.15.0-x86_64.rpm
rpm -ivh metricbeat-7.15.0-x86_64.rpm
Metricbeat提供了一些预装的模块,快速实现系统的监控。
启用system
模块:
metricbeat modules enable system
设置初始化环境:
metricbeat setup -e
setup命令加载Kibana的仪表盘,如果已经加载过了,忽略这条命令。-e
参数是可选的,作用是将日志输出到标准输出而不是系统日志。
如果修改了kibana的绑定地址,需要修改配置文件:
metricbeat.yml
setup.kibana.host: "http://localhost:5601"
启动Metricbeat
systemctl enable --now metricbeat
kibana可视化展示系统指标
打开浏览器,访问:http://localhost:5601/app/kibana#/dashboard/Metricbeat-system-overview-ecs。
如果在Kibana中看不到数据,可以尝试将日期范围设置大一点,Kibana默认展示过去15分钟的数据。如果出现错误信息,请确保Metricbeat服务正常运行,然后刷新页面。
配置Logstash
Filebeat收集的日志非常原始和杂乱。必要时可以添加Logstash进行处理然后发送给Elasticsearch存储。
配置文件目录:/etc/logstash
复制一份logstash-smaple.conf到
conf.d`目录,根据需要重新命名,配置完成后如下:
input {
beats {
port => 5044
}
}
output {
stdout { codec => rubydebug }
}
这是一个简单的Beats -> Logstash -> Elasticsearch流水线,监听在5044端口,我们将原本输出到Elasticsearch改为输出到标准输出,便于调试。
修改Filebeat配置文件,将原来的直接输出到Elasticsearch改为将数据输出到Logstash。
output.logstash:
hosts: ["172.16.243.160:5044"]
测试Logstash
/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/test.conf --config.test_and_exit
重启Filebeat,启动Logstash:
systemctl restart filebeat
/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/test.conf
如果一切正常将会在标准输出上看到JSON格式的日志信息。
一切都正常将Logstash的输出改回Elasticsearch:
input {
beats {
port => 5044
}
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
}
}
不要忘了重启一下。
使用Grok插件过滤Web日志
Grok是Logstash自带的几个插件之一,可以用来对非结构化的数据进行处理,比如将日志解析成Json格式。
Grok是通过正则表达式来匹配日志内容的,为了便于使用,Grok提供了一些内置的模式,例如INT模式对应的正则表达式为(?:[+-]?(?:[0-9]+))
,使用这些模式可以帮助我们快速解析日志,并且增强可读性。
Grok的语法:
%{SYNTAX:SEMANTIC}
SYNTAX表示要匹配的内容,SEMANTIC表示匹配成功后存储的字段名称。
除了使用内置的模式,还可以自定义模式:
(?<field_name>the pattern here)
(?<userName>[a-zA-Z]{3,5}) 3-5位字母的用户名
在线调试表达式:https://grokdebug.herokuapp.com/
通过一个例子来看一下如何使用Grok进行数据过滤,首先准备测试数据。
2021-10-10 11:57:16.825 [http-nio-10002-exec-10] DEBUG c.c.f.s.f.UsernamePasswordFilter - request failed: com.demo.authentication.BadCredentialsException: 用户名或密码错误
at com.demo.authenticate(AuthenticationProvider.java:151)
对应的匹配模式:
(?m)%{TIMESTAMP_ISO8601:createTime} \[%{DATA:threadName}\] %{LOGLEVEL:LEVEL} %{JAVACLASS:javaClass} - %{GREEDYDATA:msg}
解析成功的数据格式:
{
"createTime": [
[
"2021-10-10 11:57:16.825"
]
],
"YEAR": [
[
"2021"
]
],
"MONTHNUM": [
[
"10"
]
],
"MONTHDAY": [
[
"10"
]
],
"HOUR": [
[
"11",
null
]
],
"MINUTE": [
[
"57",
null
]
],
"SECOND": [
[
"16.825"
]
],
"ISO8601_TIMEZONE": [
[
null
]
],
"threadName": [
[
"http-nio-10002-exec-10"
]
],
"LEVEL": [
[
"DEBUG"
]
],
"javaClass": [
[
"c.c.f.s.f.UsernamePasswordFilter"
]
],
"msg": [
[
"request failed: com.demo.authentication.BadCredentialsException: 用户名或密码错误\n at com.demo.authenticate(AuthenticationProvider.java:151)"
]
]
}
在这里栽了跟头,打印日志的时候,有些地方多了一个少了一个空格,导致解析不出来,建议空格用%{SPACE}代替。
配置过滤器
input {
beats {
port => 5044
type => "kube-log"
}
}
filter {
match => { "message" => "(?m)%{TIMESTAMP_ISO8601:createTime} \[%{DATA:threadName}\] %{LOGLEVEL:LEVEL} %{JAVACLASS:javaClass} - %{GREEDYDATA:msg}" }
remove_field => ["message"]
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
}
}
message解析完成后,就没有必要了,所以移除,节省空间。
Elastic安全性配置
在浏览服务器指标仪表盘时,会弹出安全警告,因为我们没有配置Elastic安全访问。
Elastic提供了三种级别的安全配置:
- 最低安全性(开发)
- 普通安全性(生产)
- 增强安全性(在普通安全性基础上增加TLS加密)
最低安全性配置
开启安全功能
首先启用Elastic安全功能,然后为内置用户设置密码,在这之后你也可以添加更多的用户。
要求:
- 安装配置好Elasticsearch和Kibana
- 使用的许可证包含所需的安全功能
在/etc/elasticsearch/elasticsearch.yml
配置文件添加:
xpack.security.enabled: true
为系统内建用户创建密码
为了与集群通信,你必须给内建的用户配置密码,除非你启用匿名访问,否则任何不包含用户名和密码的请求都会被拒绝。
使用最低安全性或者普通安全性时,你只需要设置elastic和kibana_system用户的密码。
在每个节点上,启动Elasticsearch,在安装目录找到elasticsearch-setup-passwords
,使用PRM包安装的话,在/usr/share/elasticsearch/bin/elasticsearch-setup-passwords
。
使用auto
参数随机生成密码,如果有必要可以稍后再修改。
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
如果你想自己设置密码,使用interactive
参数替代auto
参数,这个模式会逐步为每个内建用户设置密码。
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive
配置Kibina使用密码连接Elasticsearch
编辑配置文件${KIB_PATH_CONF}/kibana.yml
:
elasticsearch.username: "kibana_system"
也许你注意到了,配置文件中也可以设置密码,但是明文的密码不具备安全性,可以通过密钥库的方式存储密码。
在Kibana安装目录找到kibana-keystore
,对于RPM安装,在/usr/share/kibana/bin/kibana-keystore
。
创建密钥库:
/usr/share/kibana/bin/kibana-keystore create
向密钥库中添加kibana_system用户的密码:
/usr/share/kibana/bin/kibana-keystore add elasticsearch.password
当提示出现时,输入kibana_system用户的密码。
Filebeat也需要添加,和Kibbana类似,不载赘述。
最后重启Kibina,然后通过浏览器访问,使用elastic用户登录,创建其他用户和角色,对于单节点模式的话,到这里就可以结束了。
其他安全性配置
对于单节点,不需要配置,以后有需要再来补充。