k8s笔记10--fluentd收集k8s集群日志到es
1 介绍
本文通过 fluentd 采集 k8s 指定 ns 的日志,然后按需过滤掉一些字段,并将其写入到es 集群。
2 采集方案
对本方案进行测试的时候,需要预先安装一个k8s集群、一个es集群、一个kibana,具体安装方法参考笔者以下两篇文章,此处主要介绍fluentd 采集k8s集群日志到es集群,因此不介绍es和k8s的安装方法。
elk笔记1–搭建elk集群
k8s笔记6–使用kubeadm快速部署k8s集群 v1.19.4
本文采用循序渐进的方法,一步步完善相关功能,以便于让一个初次使用fluentd 的小伙伴能成功地将日志采集到k8s集群。
2.1 使用默认的方式安装
笔者使用自己搭建的es集群,因此只需要在kubernetes github cluster/addons/fluentd-elasticsearch 中下载 create-logging-namespace.yaml 、fluentd-es-configmap.yaml 和 fluentd-es-ds.yaml 三个文件即可。
按照需要修改 output.conf 中的match选项,使之能正确发送到es集群。修改完成后依次apply上述三个文件即可。
默认情况下 logstash_format为true,索引为 logstash-yyyy.mm.dd类别的字段;
include_tag_key true
include_timestamp true
host 10.192.155.237
port 9200
user elastic
password elastic
logstash_format true
logstash_format为false后,设置索引名称为 fluentd.${tag},那么默认索引格式为 fluentd.kubernetes.var.log.containers.busybox-log-6c5dc946b4-7x2ns_sre-test_busybox-463230e3342d38e89c79f0d997c81b445b00d1032311ac9b641d439607d4cce4.log
index_name fluentd.${tag}
logstash_format false
2.2 采集指定ns的日志
参考文档 configuration/config-file#how-do-the-match-patterns-work ,将多个ns 匹配规则添加到 match 中,使用空格隔开即可;
如图: sre-test,logging,kube-admin,default 中都有日志输出;由于配置了 <match kubernetes.var.**_sre-test_** kubernetes.var.**_logging_** kubernetes.var.**_kube-admin_**> ,因此只收集了 sre-test logging kube-admin 等3个ns的日志,没有收集default ns的日志。
下图为几个常见输出日志的pod:
实际采集日志的ns:
2.3 定制字段,避免默认字段过多问题
默认情况下 kubernetes_metadata 有很多多余的字段,然而实际中很多字段是不需要的,因此有必要删除不用的字段。
https://github.com/fabric8io/fluent-plugin-kubernetes_metadata_filter 介绍kubernetes_metadata 哪些字段可调整, 参考文档去掉多余的字段即可
<filter kubernetes.**>
@id filter_kubernetes_metadata
@type kubernetes_metadata
skip_container_metadata true
skip_labels true
skip_master_url true
</filter>
如下图,label, container_image, container_image_id 等字段被去掉
2.4 直接发送日志到es总配置
https://docs.fluentd.org/output/elasticsearch 介绍了输出到es的常见配置
根据文档添加 include_timestamp index_name suppress_type_name 等字段,并配置一些常见选项,一下为笔者最终的配置文档。
kind: ConfigMap
apiVersion: v1
metadata:
name: fluentd-es-config-v0.2.1
namespace: logging
labels:
addonmanager.kubernetes.io/mode: Reconcile
data:
system.conf: |-
<system>
root_dir /tmp/fluentd-buffers/
</system>
containers.input.conf: |-
# Json Log Example:
# {"log":"[info:2016-02-16T16:04:05.930-08:00] Some log text here\n","stream":"stdout","time":"2016-02-17T00:04:05.931087621Z"}
# CRI Log Example:
# 2016-02-17T00:04:05.931087621Z stdout F [info:2016-02-16T16:04:05.930-08:00] Some log text here
<source>
@id fluentd-containers.log
@type tail
path /var/log/containers/*.log
pos_file /var/log/es-containers.log.pos
tag raw.kubernetes.**
read_from_head true
<parse>
@type multi_format
<pattern>
format json
time_key time
keep_time_key true
time_format %Y-%m-%dT%H:%M:%S.%NZ
</pattern>
<pattern>
format /^(?<time>.+) (?<stream>stdout|stderr) [^ ]* (?<log>.*)$/
time_format %Y-%m-%dT%H:%M:%S.%N%:z
</pattern>
</parse>
</source>
# Detect exceptions in the log output and forward them as one log entry.
# <match raw.kubernetes.var.log.containers.*_sre-test_**>
<match raw.kubernetes.**>
@id raw.kubernetes
@type detect_exceptions
remove_tag_prefix raw
message log
stream stream
multiline_flush_interval 5
max_bytes 500000
max_lines 1000
</match>
# Concatenate multi-line logs
<filter **>
@id filter_concat
@type concat
key message
multiline_end_regexp /\n$/
separator ""
</filter>
# Enriches records with Kubernetes metadata
<filter kubernetes.**>
@id filter_kubernetes_metadata
@type kubernetes_metadata
skip_container_metadata true
skip_labels true
skip_master_url true
</filter>
# Fixes json fields in Elasticsearch
<filter kubernetes.**>
@id filter_parser
@type parser
key_name log
reserve_data true
remove_key_name_field true
<parse>
@type multi_format
<pattern>
format json
</pattern>
<pattern>
format none
</pattern>
</parse>
</filter>
monitoring.conf: |-
# Prometheus Exporter Plugin
# input plugin that exports metrics
<source>
@id prometheus
@type prometheus
</source>
<source>
@id monitor_agent
@type monitor_agent
</source>
# input plugin that collects metrics from MonitorAgent
<source>
@id prometheus_monitor
@type prometheus_monitor
<labels>
host ${hostname}
</labels>
</source>
# input plugin that collects metrics for output plugin
<source>
@id prometheus_output_monitor
@type prometheus_output_monitor
<labels>
host ${hostname}
</labels>
</source>
# input plugin that collects metrics for in_tail plugin
<source>
@id prometheus_tail_monitor
@type prometheus_tail_monitor
<labels>
host ${hostname}
</labels>
</source>
output.conf: |-
# <match **>
<match kubernetes.var.**_sre-test_** kubernetes.var.**_logging_** kubernetes.var.**_kube-admin_**>
@id elasticsearch
@type elasticsearch
@log_level info
type_name _doc
include_tag_key true
include_timestamp true
host 10.192.148.109
port 9200
user elastic
password elastic
index_name fluentd_k8s_test_v1_write
logstash_format false
suppress_type_name true
<buffer>
@type file
path /var/log/fluentd-buffers/kubernetes.system.buffer
flush_mode interval
retry_type exponential_backoff
flush_thread_count 2
flush_interval 5s
retry_forever
retry_max_interval 30
chunk_limit_size 2M
total_limit_size 500M
overflow_action block
</buffer>
</match>
3 注意事项
- 向es写入数据报错 [types removal] Specifying types in bulk requests is deprecated
报错内容如下:
参考文档: ES 7.x: [types removal] Specifying types in bulk requests is deprecated. #785warning: 299 Elasticsearch-7.10.2-747e1cc71def077253878a59143c1f785afa92b9 "[types removal] Specifying types in bulk requests is deprecated." 解决方法: 在output 的match 中添加 suppress_type_name true 即可