使用EFK快速搭建安全可靠的日志服务
1 前言
EFK是一套分布式日志服务解决方案,由各个组件构成。EFK分别是指:elasticsearch、filebeat、kibana。不过在真实的生产环境中,搭建日志服务可能还需要logstash来进行规制解析,使用kafka进行削峰填谷作为缓冲。在本文中,我主要介绍如何使用elasticsearch+filebeat+logstash+kibana来快速搭建一套分布式日志服务,来接入线上的多个产品线,并进行日志的统一管理。
2整体框架及各组件介绍
2.1 整体框架
2.2 各组件简介
filebeat:作为agent部署在需要收集日志的服务所在的机器上,进行日志的收集;
logstash:接收来自filebeat的日志流,进行规则解析,写入到es;
elasticsearch + searchguard:es用于日志的存储、查询;searchguard用于对es索引的安全防护;
kibana:进行日志查询的可视化界面。
3 日志收集&传输
3.1 logstash作为agent
在最初的ELK方案中,是将logstash作为agent部署在各个client上的进行日志的收集、解析直接写入到es中。但是在要接入的服务非常多、日质量不断增大的场景中,这种方式会造成以下影响:
- logstash非常占用内存,会影响到部署到本机器上的线上服务
- 直接写es会对es造成非常大的压力
filebeat使用go进行开发的,其轻量级特性非常适合作为agent进行部署。在本文的日志服务中,filebeat所扮演的角色,就是作为agent进行日志的收集,以及对于java异常日志multiline的处理。
3.2 filebeat作为agent
各公司都应该有自己的线上服务部署平台,由于要收集的服务是分布在许多不同的机器上的。建议将filebeat封装为一个服务,直接将二进制包打包到要部署服务的包中,根据不同的沙盒或者线上环境加载不同的filebeat.yml配置文件进行安装即可。
3.2.1 filebeat的日志收集文件说明
举例说明,我们要收集sonofelice模块的sonofelice.debug.log中的日志,针对这一个日志文件需要配置一个sonofelice_debug.yml日志收集文件,以便filebeat开启一个harvest通道开始日志收集。具体配置示例如下:
- type: log enabled: true paths: - /home/work/logs/sonofelice/debug/sonofelice.debug.log - /home/work/logs/sonofelice/debug/sonofelice.debug.log*/*.debug.log ignore_older: 72h close_inactive: 1h multiline: pattern: '^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d' negate: true match: after fields: productline: test module: sonofelice submodule: api type: debug language: java logpattern: java-std region: bj
在上述配置中,必选项及解释可以参考博客:https://www.cnblogs.com/smile...
上述配置中的各个字段会对应为es中的具体的document中的field。
3.2.2 filebeat.yml文件说明
在本文示例中通过filebeat写入的logstash,因此只需要配置如下几个部分即可。
- Filebeat modules模块用于配置3.2.1中对于每个日志文件配置的日志收集文件所在的路径。
- Logstash output部分用于配置要写入的logstash的各节点服务地址,以及证书相关信息
#============================= Filebeat modules =============================== filebeat.config.modules: # Glob pattern for configuration loading path: ${path.config}/modules.d/*.yml # Set to true to enable config reloading reload.enabled: true # Period on which files under path should be checked for changes reload.period: 10s path.data: /home/filebeat/data filebeat.shutdown_timeout: 300s filebeat.config.inputs: enabled: true path: inputs/*.yml reload.enabled: true reload.period: 10s queue.mem: events: 4096 flush.min_events: 512 flush.timeout: 1s #output.console: # pretty: true #----------------------------- Logstash output -------------------------------- output.logstash: # The Logstash hosts hosts: ["logstash-hosts1:5044", "logstash-hosts2:5044", "logstash-hosts3:5044"] loadbalance: true # Optional SSL. By default is off. # List of root certificates for HTTPS server verifications ssl.certificate_authorities: ['${FILEBEAT_ROOT_CA_PATH}'] # Certificate for SSL client authentication ssl.certificate: '${FILEBEAT_CRT_PEM_PATH}' # Client Certificate Key ssl.key: '${FILEBEAT_KEY_PEM_PATH}'
为了确保安全性,我们开启了证书访问,关于证书的生成部分,另有相关文章介绍,此处不再赘述。
如果希望将filebeat的相关监控信息写入到es,可以启用xpack monitoring,配置如下:
#============================== Xpack Monitoring =============================== # filebeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The # reporting is disabled by default. # Set to true to enable the monitoring reporter. xpack.monitoring.enabled: true # Uncomment to send the metrics to Elasticsearch. Most settings from the # Elasticsearch output are accepted here as well. Any setting that is not set is # automatically inherited from the Elasticsearch output configuration, so if you # have the Elasticsearch output configured, you can simply uncomment the # following line. xpack.monitoring.elasticsearch: hosts: ["es-host1:9920","es-host2:9920","es-host3:9920"] protocol: "https" username: "filebeat_system" password: "abcdefg" ssl.enabled: true ssl.verification_mode: full ssl.certificate_authorities: ['${FILEBEAT_ROOT_CA_PATH}'] # metric http server http.enabled: true http.host: localhost http.port: 5066
4 日志规则解析
Logstash 是一款强大的数据处理工具,它可以实现数据传输,格式处理,格式化输出,还有强大的插件功能,常用于日志处理。对于logstash的详细介绍可以参考:https://blog.csdn.net/u010739...
本文介绍的日志服务中,logstash的作用主要是接收来自filebeat收集上来的日志,匹配不同的规则,写入到不同的es索引中。
同filebeat一样,也非常建议将logstash封装为可以直接部署的服务。我们重点介绍logstash的基础配置,以及pipelines的配置。
4.1 logstash.yml配置解析
pipeline.batch.size: 500 pipeline.batch.delay: 100 config.reload.automatic: true config.reload.interval: 30s queue.type: persisted path.queue: /home/logstash/data/queue queue.max_bytes: 4gb queue.checkpoint.writes: 256 dead_letter_queue.enable: true dead_letter_queue.max_bytes: 100gb path.dead_letter_queue: /home/logstash/data/dead_letter_queue http.host: "127.0.0.1" http.port: 5044 # ------------ X-Pack Settings (not applicable for OSS build)-------------- # # X-Pack Monitoring # https://www.elastic.co/guide/en/logstash/current/monitoring-logstash.html xpack.monitoring.enabled: true xpack.monitoring.elasticsearch.username: logstash_system xpack.monitoring.elasticsearch.password: kdhlr953 xpack.monitoring.elasticsearch.url: ["https://es-host1:9920","https://es-host2:9920","https://es-host3:9920"] xpack.monitoring.elasticsearch.ssl.truststore.path: /home/work/certificate/truststore.jks xpack.monitoring.elasticsearch.ssl.truststore.password: sjaifdakdjf xpack.monitoring.elasticsearch.ssl.verification_mode: certificate xpack.monitoring.elasticsearch.sniffing: false xpack.monitoring.collection.interval: 10s xpack.monitoring.collection.pipeline.details.enabled: true
跟filebeat一样,我们开启了证书访问,因此也需要证书相关的支持。更多配置相关的介绍可以自行百度。后续也会有文章进行详细介绍。
4.2 pipelines配置解析
pipelines.yml文件主要配置logstash需要加载的pipelines的相关路径:
- pipeline.id: filebeat-log path.config: "pipelines/filebeat-log/*.conf"
4.3 pipelines热加载
pipelines主要分为三部分:input、fileter、output,这三部分可以配置到三个不同的配置文件中。
这三个配置文件的改动是热加载的。logstash会定期进行检测。
4.3.1 input.conf
主要是filter-beats插件的配置,配置示例如下:
input { beats { port => 5044 client_inactivity_timeout => 600 ssl => true ssl_certificate_authorities => ["/home/work/certificate/chain-ca.pem"] ssl_certificate => "/home/work/certificate/server.crt.pem" ssl_key => "/home/work/certificate/server.key.pem" ssl_verify_mode => "force_peer" } }
4.3.2 filter.conf
最挑战的就是fileter的配置部分。强烈推荐定义规则时先使用grok调试器进行在线调试后再加载到logstash中。https://grokdebug.herokuapp.com/
配置参考如下:
filter { # 备份一下事件时间,@timestamp在后面的日志处理过程中会被替换成日志内容中的时间 mutate { copy => { "@timestamp" => "event_timestamp" } } if [fields][language] == "go" and [fields][type] == "info" { grok { match => { "message" => "^\[%{GO_TIMESTAMP:[@metadata][log_timestamp]}\]\s+\[%{DATA:log_level}\]" } pattern_definitions => { "GO_TIMESTAMP" => "%{YEAR}/%{MONTHNUM}/%{MONTHDAY} %{HOUR}:%{MINUTE}:%{SECOND} %{TZ}" } } date { match => ["[@metadata][log_timestamp]", "yyyy/MM/dd HH:mm:ss z"] timezone => "Asia/Shanghai" } } if ![@metadata][index_name] { mutate { add_field => {"[@metadata][index_name]" => "%{[fields][productline]}-%{[fields][logpattern]}-%{[fields][type]}"} } } if ![@metadata][document_id] { mutate { add_field => {"[@metadata][document_id]" => "%{[@timestamp]}%{[offset]}%{[host][name]}"} } mutate { gsub => ["[@metadata][document_id]", "[.:TZ-]", ""] } } }
4.3.3 output.conf
output { if "_grokparsefailure" in [tags] or "_jsonparsefailure" in [tags] { file { path => "/home/work/logstash/failure_output/failure-%{+YYYY-MM-dd}.log" } } else { elasticsearch { hosts => ["https://es-host1:9920","https://es-host2:9920","https://es-host3:9920"] index => "logstash-%{[@metadata][index_name]}-%{+YYYY.MM.dd}" document_id => "%{[@metadata][document_id]}" ssl => true ssl_certificate_verification => true truststore => "/home/work/certificate/truststore.jks" truststore_password => "adofkoe" user => "logstash" password => "dafodmfkamkefadfg" } } }
如果filebeat收集的日志不满足fileter.conf中配置的grok表达式,会统一写入到failure文件中,方便问题排查。
5 日志存储查询
5.1 elasticsearch
elasticsearch是一个全文检索引擎,在本文中的日志服务中主要用于日志的结构化存储和查询。
为了将不同产品线的访问权限进行隔离,我们需要在es安装时加载search-guard插件。
在第一次部署es启动前需要进行系统配置更新(使用root权限),修改/etc/security/limit.conf,保存后logout然后再login一遍系统
- hard nofile 65536
- soft nofile 65536 work hard nofile 65536 work soft nofile 65536
- soft nproc 4096
- hard nproc 4096 work soft nproc 4096 work hard nproc 4096 work soft memlock unlimited work hard memlock unlimited
在/etc/sysctl.conf加入 vm.max_map_count=262144 保存后执行sysctl -p
对于search-guard插件,可以将es封装为可独立部署的线上服务,在部署脚本中加载search-guard插件。关于插件的安装在本文中先不进行过多介绍,重点介绍一下search-guard插件的账号体系配置。
sgconfig中的用户密码需要通过执行es节点部署路径中plugin/search-guard-6/tools/hash.sh脚本来生成hash值。 执行命令为bash hash.sh -p $PASSWORD 然后将生成的hash填入sg_internal_users.yml中,并执行bin/sg_update.sh脚本
具体执行步骤如下:
第一步: 在es节点部署路径中,执行以下命令,得到一个哈希值
bash plugins/search-guard-6/tools/hash.sh -p tsdb123
第二步: 将第一步中的哈希值写入到sgconfig目录下的sg_internal_users.yml文件中
#password is: tsdb123 tsdb: hash: $2y$12$nRgsuDYm36ZKCTjPf3/CeusU9BSGNDCOGOC.JKT7lhj9tVE.nVtS2 roles: - tsdb
此处填写的roles: -tsdb角色需要在
第三步: 在sg_roles_mapping.yml文件中添加角色映射
sg_tsdb: readonly: true backendroles: - tsdb
第四步: 在sg_roles.yml文件中添加索引控制。此处添加kibana是为了让用户可以有kibana的访问权限,否则是无法通过kibana进行查询的。
sg_tsdb: readonly: true cluster: - CLUSTER_COMPOSITE_OPS_RO indices: 'logstash-tsdb-*': '*': - READ '?kibana*': '*': - READ
第五步: 生效配置,执行以下命令:
sh bin/sg_update.sh sgconfig/
其中sg_update.sh脚本可以自行编写,主要用于加载sg的各个配置文件。
5.2 kibana
kibana用于进行日志的查询、报表展示,可以理解为es的一个可视化操作界面。
kibana同上述的所有服务,也可以封装为单独的服务包进行安装部署,其最主要的就是kibana.yml的配置。主要配置kibana的端口,es的地址,访问es需要的用户名、密码,证书的地址等信息。
使用5,1中分配的账号进行kibana登录即可查看对应索引的相关信息。
总结
至此,搭建完上述的各个组件,依次检查filebeat的日志是否能够正确收集到对应的日志文件、logstash能否正确接收到filebeat传输过来的信息并且正确解析,检查es是否能够生成索引,kibana是否能够进行不同账号的登录以及对应es索引的日志查询。没有问题之后,分布式日志服务就搭建完毕了。