ELK+Filebeat日志收集分析
文章目录1.什么是ELK2.ELK架构3.为什么采用ELK架构4.环境准备ES的配置方式ES的节点5.单实例方式部署ELK6. 集群部署ELK6.1 不区分集群中的节点角色6.2 区分集群中节点角色7.使用Filebeat监控收集容器日志8.统一部署1.安装elasticsearch2.安装elasticsearch-head3.logstash4.kibana5.filebeat作者邮箱时间潘顾
文章目录
作者 | 邮箱 | 时间 |
---|---|---|
潘顾昌 | guchang.pan@hand-china.com | 2020/01/29 |
1.什么是ELK
E: elasticsearch
L:logstash
K:kibana
Elasticsearch是一个开源的分布式搜索和分析引擎,可以用于全文检索、结构化检索和分析,它构建在Lucene搜索引擎库之上,是当前使用较为广泛的开源搜索引擎之一。
Logstash是一个开源的数据搜集引擎是一个用来搜集、分析、过滤日志的工具,使用它可以将搜集来的日志信息进行处理然后进行输出。Logstash支持许多功能强大的插件,可以合理使用这些插件来对搜集到 的日志信息进行过滤和处理。
Kibana是一个基于Web的图形界面,可以使用它对Elasticsearch索引中的数据进行搜索、查看、交互操作。还可以很方便的利用图表、表格及地图对数据进行多元化的分析和呈现。
Filebeat是一个轻量级的日志搜集器,用于搜集和转发日志数据,Filebeat一般都会安装在需要搜集日志的服务器上,指定需要搜集日志的日志文件的位置,搜集日志信息并转发到Elasticsearch 或Logstash上进行索引。
2.ELK架构
ELK日志监控平台架构图如下:
其中, Filebeat 主要用于在服务器中采集服务日志信息并输出到 Logstash, Logstash 负责接收所有 Filebeat 传递过来的日志数据,并对数据进行过滤筛选处理后输出到 Elasticsearch, Elasticsearch 主要用于日志消息的存储,搜索和分析,在 Elasticsearch 中存储的索引信息最终会通过 Kibana 在页面上直观的进行展示。最终用户可以在 Kibana 页面中操作索引,查询日志, 监控 Elasticsearch 和 Kibana 的健康状态,以及配置多种 Dashboard 来展示聚合数据信息。
总结来说,ELK 日志监控大体上分为两部分,Elasticsearch、Logstash 和 Filebeat 负责数据的搜集,过滤,存储和分析,Kibana 负责操作存储在 Elasticsearch 中的索引信息,监控 Elasticsearch 和 Kibana 的健康状态以及管理用户信息。 同时用户还可以配置多种 Dashboard 来展示数据聚合信息。
3.为什么采用ELK架构
1.Elasticsearch、Logstash、Kibana、Filebeat 均为开源组件,并且使用 ELK 搭建日志监控系统的方案也比较成熟。
2.一般的日志监控系统架构都是采用 ELK(Elasticsearch、Logstash、Kibana)架构去搭建的,但是由于 Logstash 本身是基于 jdk 的,且它集成了许多插件,所以占用内存较大,在每台服务器上都部署一 个 Logstash 有些占用资源,因此我们使用轻量级的 Filebeat 组件来完成搜集日志的操作。但是 Filebeat 只能采集日志数据却无法对数据进行过滤,因此我们在将日志信息输出到 Elasticsearch 之前先使 用 Logstash 对数据进行过滤处理,再将处理好的数据输出到 Elasticsearch。
3.在微服务场景下,可能存在如下两种情况:
(1)开发或生产环境的微服务项目部署在多台服务器上,此时需要监控多台服务器下的日志信息情况;
(2)一台服务器下既存在开发环境的微服务项目,又存在生产环境的微服务项目,此时需要将搜集到的日志信息加以区分。
这种情况下我们可以在 Filebeat 采集日志时为日志信息指定每个不同环境的唯一前缀后再输出。例如:采集融合开发环境的日志时,我们可以在 Filebeat 中进行配置,将采集到的日志添加统一的前缀 (integration_dev-服务名称)加以区分。这样我们可以针对不同的环境,在采集日志输出之前都为其添加唯一的前缀,最终在 Kibana 中使用我们配置的唯一前缀(integration_dev-*)来创建索引模式来获取我们所需环境的日志信息。 而在这种场景下,使用 FileBeat 就要比使用 Logstash 更加节约资源了。
4.环境准备
Elasticsearch运行时要求vm.max_map_count
内核参数必须大于262144,因此开始之前需要确保这个参数正常调整过。
$ sysctl -w vm.max_map_count=262144
也可以在ES的的编排文件中增加一个initContainer来修改内核参数,但这要求kublet启动的时候必须添加了--allow-privileged
参数,但是一般生产中不会给加这个参数,因此最好在系统供给的时候要求这个参数修改完成。
ES的配置方式
- 使用Cluster Update Setting API动态修改配置
- 使用配置文件的方式,配置文件默认在 config 文件夹下,具体位置取决于安装方式。
- elasticsearch.yml 配置Elasticsearch
- jvm.options 配置ES JVM参数
- log4j.properties 配置ES logging参数
- 使用Prompt方式在启动时输入
最常使用的配置方式为使用配置文件,ES的配置文件为yaml格式,格式要求和Kubernetes的编排文件一样。配置文件中可以引用环境变量,例如node.name: ${HOSTNAME}
ES的节点
ES的节点Node可以分为几种角色:
- Master-eligible node,是指有资格被选为Master节点的Node,可以统称为Master节点。设置
node.master: true
- Data node,存储数据的节点,设置方式为
node.data: true
。 - Ingest node,进行数据处理的节点,设置方式为
node.ingest: true
。 - Trible node,为了做集群整合用的。
对于单节点的Node,默认是master-eligible和data,对于多节点的集群,就要仔细规划每个节点的角色。
5.单实例方式部署ELK
单实例部署ELK的方法非常简单,可以参考Github上的elk-single.yaml文件,整体就是创建一个ES的部署,创建一个Kibana的部署,创建一个ES的Headless服务,创建一个Kiana的NodePort服务,本地通过节点的NodePort访问Kibana。
创建elk-single.yaml
kind: List
apiVersion: v1
items:
- apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: kb-single
spec:
replicas: 1
template:
metadata:
name: kb-single
labels:
app: kb-single
spec:
containers:
- image: docker.elastic.co/kibana/kibana:6.4.0
name: kb
env:
- name: ELASTICSEARCH_URL
value: "http://es-single:9200"
ports:
- name: http
containerPort: 5601
- apiVersion: v1
kind: Service
metadata:
name: kb-single-svc
spec:
type: NodePort
ports:
- name: http
port: 5601
targetPort: 5601
nodePort: 32601
selector:
app: kb-single
- apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: es-single
spec:
replicas: 1
template:
metadata:
name: es-single
labels:
app: es-single
spec:
containers:
- image: docker.elastic.co/elasticsearch/elasticsearch:6.4.0
name: es
env:
- name: network.host
value: "_site_"
- name: node.name
value: "${HOSTNAME}"
- name: discovery.zen.ping.unicast.hosts
value: "${ES_SINGLE_NODEPORT_SERVICE_HOST}"
- name: cluster.name
value: "test-single"
- name: ES_JAVA_OPTS
value: "-Xms128m -Xmx128m"
volumeMounts:
- name: es-single-data
mountPath: /usr/share/elasticsearch/data
volumes:
- name: es-single-data
emptyDir: {}
- apiVersion: v1
kind: Service
metadata:
name: es-single-nodeport
spec:
type: NodePort
ports:
- name: http
port: 9200
targetPort: 9200
nodePort: 31200
- name: tcp
port: 9300
targetPort: 9300
nodePort: 31300
selector:
app: es-single
- apiVersion: v1
kind: Service
metadata:
name: es-single
spec:
clusterIP: None
ports:
- name: http
port: 9200
- name: tcp
port: 9300
selector:
app: es-single
[root@hzero_dev3 elk]# kubectl apply -f elk-single.yaml
deployment.apps/kb-single created
service/kb-single-svc created
deployment.apps/es-single created
service/es-single-nodeport created
service/es-single created
6. 集群部署ELK
6.1 不区分集群中的节点角色
创建文件:elk-cluster.yaml
kind: List
apiVersion: v1
items:
- apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: kb-single
labels:
author: shiqiang
spec:
replicas: 1
template:
metadata:
name: kb-single
labels:
app: kb-single
author: shiqiang
spec:
containers:
- image: docker.elastic.co/kibana/kibana:6.4.0
name: kb
env:
- name: ELASTICSEARCH_URL
value: "http://es-cluster:9200"
ports:
- name: http
containerPort: 5601
- apiVersion: v1
kind: Service
metadata:
name: kb-single-svc
labels:
author: shiqiang
spec:
type: NodePort
ports:
- name: http
port: 5601
targetPort: 5601
nodePort: 32601
selector:
app: kb-single
- apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: es-cluster
spec:
serviceName: es-cluster
replicas: 3
template:
metadata:
name: es-cluster
labels:
app: es-cluster
author: shiqiang
spec:
containers:
- image: docker.elastic.co/elasticsearch/elasticsearch:6.4.0
name: es
resources:
limits:
cpu: 300m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
env:
- name: network.host
value: "_site_"
- name: node.name
value: "${HOSTNAME}"
- name: discovery.zen.ping.unicast.hosts
value: "es-cluster"
- name: discovery.zen.minimum_master_nodes
value: "2"
- name: cluster.name
value: "test-cluster"
- name: ES_JAVA_OPTS
value: "-Xms128m -Xmx128m"
volumeMounts:
- name: es-cluster-data
mountPath: /usr/share/elasticsearch/data
volumes:
- name: es-cluster-data
emptyDir: {}
- apiVersion: v1
kind: Service
metadata:
name: es-cluster-nodeport
labels:
author: shiqiang
spec:
type: NodePort
ports:
- name: http
port: 9200
targetPort: 9200
nodePort: 31200
- name: tcp
port: 9300
targetPort: 9300
nodePort: 31300
selector:
app: es-cluster
- apiVersion: v1
kind: Service
metadata:
name: es-cluster
labels:
author: shiqiang
spec:
clusterIP: None
ports:
- name: http
port: 9200
- name: tcp
port: 9300
selector:
app: es-cluster
[root@hzero_dev3 elk]# kubectl apply -f elk-cluster.yaml
deployment.apps/kb-single created
service/kb-single-svc created
deployment.apps/es-single created
service/es-single-nodeport created
service/es-single created
效果如下
6.2 区分集群中节点角色
如果需要区分节点的角色,就需要建立两个StatefulSet部署,一个是Master集群,一个是Data集群。Data集群的存储我这里为了简单使用了emptyDir
,可以使用localStorage
或者hostPath
,关于存储的介绍,可以参考Kubernetes存储系统介绍。这样就可以避免Data节点在本机重启时发生数据丢失而重建索引,但是如果发生迁移的话,如果想保留数据,只能采用共享存储的方案了。具体的编排文件在这里elk-cluster-with-role
创建:elk-cluster-with-role.yaml
kind: List
apiVersion: v1
items:
- apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: kb-single
labels:
author: shiqiang
spec:
replicas: 1
template:
metadata:
name: kb-single
labels:
app: kb-single
author: shiqiang
spec:
containers:
- image: docker.elastic.co/kibana/kibana:6.4.0
name: kb
env:
- name: ELASTICSEARCH_URL
value: "http://es-cluster:9200"
ports:
- name: http
containerPort: 5601
- apiVersion: v1
kind: Service
metadata:
name: kb-single-svc
labels:
author: shiqiang
spec:
type: NodePort
ports:
- name: http
port: 5601
targetPort: 5601
nodePort: 32601
selector:
app: kb-single
- apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: es-cluster
spec:
serviceName: es-cluster
replicas: 3
selector:
matchLabels:
app: es-cluster
template:
metadata:
name: es-cluster
labels:
app: es-cluster
author: shiqiang
role: master
spec:
containers:
- image: docker.elastic.co/elasticsearch/elasticsearch:6.4.0
name: es
resources:
limits:
cpu: 300m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
env:
- name: network.host
value: "_site_"
- name: node.name
value: "${HOSTNAME}"
- name: discovery.zen.ping.unicast.hosts
value: "es-cluster"
- name: discovery.zen.minimum_master_nodes
value: "2"
- name: cluster.name
value: "test-cluster"
- name: node.master
value: "true"
- name: node.data
value: "false"
- name: node.ingest
value: "false"
- name: ES_JAVA_OPTS
value: "-Xms128m -Xmx128m"
volumeMounts:
- name: es-cluster-storage
mountPath: /usr/share/elasticsearch/data
volumes:
- name: es-cluster-storage
emptyDir: {}
- apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: es-cluster-data
spec:
serviceName: es-cluster-data
replicas: 3
selector:
matchLabels:
app: es-cluster-data
template:
metadata:
name: es-cluster-data
labels:
app: es-cluster-data
author: shiqiang
role: master
spec:
containers:
- image: docker.elastic.co/elasticsearch/elasticsearch:6.4.0
name: es-data
resources:
limits:
cpu: 300m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
env:
- name: network.host
value: "_site_"
- name: node.name
value: "${HOSTNAME}"
- name: discovery.zen.ping.unicast.hosts
value: "es-cluster"
- name: discovery.zen.minimum_master_nodes
value: "2"
- name: cluster.name
value: "test-cluster"
- name: node.master
value: "false"
- name: node.data
value: "true"
- name: node.ingest
value: "false"
- name: ES_JAVA_OPTS
value: "-Xms128m -Xmx128m"
volumeMounts:
- name: es-cluster-storage
mountPath: /usr/share/elasticsearch/data
volumes:
- name: es-cluster-storage
emptyDir: {}
- apiVersion: v1
kind: Service
metadata:
name: es-cluster-nodeport
labels:
author: shiqiang
spec:
type: NodePort
ports:
- name: http
port: 9200
targetPort: 9200
nodePort: 31200
- name: tcp
port: 9300
targetPort: 9300
nodePort: 31300
selector:
app: es-cluster
- apiVersion: v1
kind: Service
metadata:
name: es-cluster
labels:
author: shiqiang
spec:
clusterIP: None
ports:
- name: http
port: 9200
- name: tcp
port: 9300
selector:
app: es-cluster
[root@hzero_dev3 elk]# kubectl apply -f elk-cluster-with-role.yaml
deployment.apps/kb-single created
service/kb-single-svc created
deployment.apps/es-single created
service/es-single-nodeport created
service/es-single created
效果如下
7.使用Filebeat监控收集容器日志
使用Logstash,可以监测具有一定命名规律的日志文件,但是对于容器日志,很多文件名都是没有规律的,这种情况比较适合使用Filebeat来对日志目录进行监测,发现有更新的日志后上送到Logstash处理或者直接送入到ES中。
每个Node节点上的容器应用日志,默认都会在/var/log/containers
目录下创建软链接,这里我遇到了两个小问题,第一个就是当时挂载hostPath
的时候没有挂载软链接的目的文件夹,导致在容器中能看到软链接,但是找不到对应的文件;第二个问题是宿主机上这些日志权限都是root,而Pod默认用filebeat用户启动的应用,因此要单独设置下。
8.统一部署
1.安装elasticsearch
docker pull elasticsearch:6.8.2
运行elasticsearch
docker run -p 9200:9200 -p 9300:9300 --name elasticsearch \
-e "discovery.type=single-node" \
-e "cluster.name=elasticsearch" \
-d elasticsearch:6.8.2
测试:
curl -XGET 'localhost:9200'
2.安装elasticsearch-head
docker pull mobz/elasticsearch-head:5
启动服务
docker run -d --name elasticsearch-head -p 9100:9100 docker.io/mobz/elasticsearch-head:5
进入容器配置elasticsearch跨域
docker exec -it 9188378a1ad9 /bin/bash
安装vim
yum -y install vim*
进入到/config/elasticsearch.yml配置文件,添加一下两行代码
http.cors.enabled: true
http.cors.allow-origin: "*"
3.logstash
安装包:
链接:https://pan.baidu.com/s/1MiS2vTvQue4pm54r-HzMlw
提取码:kbrh
解压,调整配置文件,参数修改完成后保存即可
tar -zxvf logstash-6.8.2.tar.gz
mv logstash-6.8.2 logstash
cd logstash/config
cp logstash-sample.conf syslog.conf
vim syslog.conf
示例配置如下:
input {
beats {
# 端口信息
port => 5044
}
}
# 对filebeat中传输过来的信息进行过滤
filter {
mutate {
rename => { "[host][name]" => "host" }
}
# 排除tag中无用的参数,避免生成的ES索引格式有问题。注意:若不操作filebeat的tag时则无需该if条件及里面的mutate配置
if "beats_input_codec_plain_applied" in [tags] {
mutate {
remove_tag => ["beats_input_codec_plain_applied"]
}
}
# 标准配置,若无特殊需求可不做修改
grok {
match => { "message" => [
"\[%{TIMESTAMP_ISO8601:logtime}\]\s*\[%{LOGLEVEL:loglevel}\]\s*\[%{IPORHOST:instancehost}\]\s*\[%{DATA:module}\]\s*%{JAVACLASS:class}\s*\[pic:%{DATA:pic}\]\s*\[%{DATA:keys}\]\s*%{GREEDYDATA:content}",
"\[%{TIMESTAMP_ISO8601:logtime}\]\s*\[%{LOGLEVEL:loglevel}\]\s*\[%{IPORHOST:instancehost}\]\s*\[%{DATA:module}\]\s*%{JAVACLASS:class}\s*\[pic:%{DATA:pic}\]\s*%{GREEDYDATA:content}",
"\[%{TIMESTAMP_ISO8601:logtime}\]\s*%{GREEDYDATA:content}",
"%{GREEDYDATA:content}"
]}
}
# 标准配置,若无特殊需求可不做修改
date {
match => [ "logtime", "ISO8601", "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss,SSS", "yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd HH:mm:ss,SSS" ]
target => "@timestamp"
timezone => "Asia/Shanghai"
}
}
# 配置输出到ES中的索引格式
output {
elasticsearch {
# elasticsearch的hosts地址。注意:需将localhost修改为实际的地址
hosts => ["http://172.28.8.104:9200"]
# 以filebeat定义的tags为前缀,日期为后缀组成索引,例如:(integration_dev-hzero-platform-2019.11.02)。注意:该配置需修改为实际想要的索引格式。
index => "%{[tags]}-%{+YYYY.MM.dd}"
# elastic用户名
user => "elastic"
# 注意:此处的密码需修改为实际elastic用户的密码,未修改时默认为changeMe,建议统一进行修改
password => "changeMe"
}
}
启动logstash
# 直接启动
./logstash -f ../config/syslog.conf
# 后台启动
nohup ./bin/logstash -f ./config/syslog.conf &
4.kibana
下载
链接:https://pan.baidu.com/s/1HDBwF8bXHnTKs8dDAqwUwQ
提取码:tdhh
解压,调整配置文件
tar -zxvf kibana-6.8.3.tar.gz
mv kibana-6.8.3 kibana
cd kibana/config
vim kibana.yml
示例配置如下:
server.port: 5601 # Kibana端口号
server.host: "localhost" # kibana地址。注意:该配置需修改为实际kibana的host地址。
elasticsearch.hosts: ["http://localhost:9200"] # kibana连接es的host。注意:该配置需修改为实际es的host地址。
elasticsearch.username: "elastic" # es用户名,当es开启认证授权时需要配置。
elasticsearch.password: "changeMe" # es密码,当es开启认证授权时需要配置,该配置需修改为实际elastic账户的密码。
i18n.locale: "zh-CN" # 配置中文Kibana环境。注意:该配置按需进行配置,不加时默认为英文操作环境。
启动Kibana
# 直接启动
./bin/kibana
# 后台启动
nohup ./bin/kibana &
访问:http://172.28.8.104:5601
5.filebeat
安装
链接:https://pan.baidu.com/s/1E0o-0qKRJ0m1SnidtZrGYQ
提取码:jwkh
解压,调整配置文件
tar -zxvf filebeat-6.8.3-linux-x86_64.tar.gz
mv filebeat-6.8.3 filebeat
cd filebeat
vim filebeat.yml
示例配置如下:
force_close_files: true # 当文件改名或删除时,会自动关闭文件
# 配置filebeat传输到logstash中的参数,其中tags字段中的内容是我们定义的最终es的索引格式,在logstash中会在其后面拼接时间戳来区分相同服务不同日期的日志信息。
filebeat.prospectors:
- type: log
enabled: true
# 指定需要搜集的日志文件路径。注意:该配置需修改为实际需搜集的服务日志文件路径。
paths:
- /hzero-repo/hzero-platform/target/app.log
# 标记tag,用于logstash中设置索引。注意:该配置需修改为实际要设置的索引前缀,推荐格式:环境类型+服务名称,例如融合开发环境平台服务则为integration_dev-hzero-platform。
tags: ["integration_dev-hzero-platform"]
multiline.pattern: ^\[
multiline.negate: true
multiline.match: after
# 开启filebeat输出到logstash。注意:在此之前需要禁用掉默认开启的es输出
output.logstash:
# Logstash hosts。注意:该配置需修改为实际logstash的hosts地址
hosts: ["localhost:5044"]
processors:
- add_host_metadata:
netinfo.enabled: true
cache.ttl: 5m
- add_cloud_metadata: ~
启动filebeat
nohup ./filebeat &
实时查看日志
更多推荐
所有评论(0)