目录[-]
系统环境:
资源地址:
Kubernetes 集群中会编排非常多的服务,各个服务不可能保证服务一定能稳定的运行,于是每个服务都会打印出各自的日志信息方便调试。由于服务的众多,每个服务挨个查看日志显然是一件非常复杂的事情,故而日志的统一收集、整理显得尤为重要。这里用流行方案 EFK 进行日志收集整理工作。
基于云原生十二原则规范,一般要求所有日志信息最好都打印输出到控制台,且打印出的日志都会以 *-json 的命名方式保存在 /var/lib/docker/containers/ 目录下,所以只要指定 Fluentd 收集地址为该目录即可方便进行日志收集工作。
Fluentd是一个用于统一日志层的开源数据收集器。使用起来简单而灵活,且能统一记录层,经过全球多家公司实际考验其能力。
Elasticsearch 是一个分布式的搜索和分析引擎,可以用于全文检索、结构化检索和分析,并能将这三者结合起来。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便,轻松扩展服务节点,更能用于日志收集快速检索等等一些列功能。
Kibana是一个为Elasticsearch平台分析和可视化的开源平台,使用Kibana能够搜索、展示存储在Elasticsearch中的索引数据。使用它可以很方便用图表、表格、地图展示和分析数据。
请查看 “安装 ElasticSearch & Kibana”
采集过程简单说就是利用 Fluentd 采集 Kubernetes 节点服务器的 “/var/log” 和 “/var/lib/docker/container” 两个目录下的日志信息,然后汇总到 ElasticSearch 集群中,再经过 Kibana 展示的一个过程。
具体日志收集过程如下所述:
详情请访问 Kubernetes Fluentd Github地址:https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/fluentd-elasticsearch
下载 Kubernetes ConfigMap 的配置 yaml 文件,里面包含了 Fluentd 采集 Kubernetes 集群日志的相关配置,需要提前将其下载修改一些配置让其更适合我们 Kubernetes 集群日志采集。
$ https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/fluentd-es-configmap.yaml
下载完后查看配置文件,这里将描述个别重要的配置段。
kind: ConfigMap
apiVersion: v1
metadata:
name: fluentd-es-config-v0.2.0
namespace: kube-system
labels:
addonmanager.kubernetes.io/mode: Reconcile
data:
###### 系统配置,默认即可 #######
system.conf: |-
root_dir /tmp/fluentd-buffers/
###### 容器日志—收集配置 #######
containers.input.conf: |-
# ------采集 Kubernetes 容器日志-------
# -----检测Exception异常日志连接到一条日志中------
# 关于插件请查看地址:https://github.com/GoogleCloudPlatform/fluent-plugin-detect-exceptions
#---匹配tag为raw.kubernetes.**日志信息
@id raw.kubernetes
@type detect_exceptions #---使用detect-exceptions插件处理异常栈信息,放置异常只要一行而不完整
remove_tag_prefix raw #---移出raw前缀
message log #---JSON记录中包含应扫描异常的单行日志消息的字段的名称。
# 如果将其设置为'',则插件将按此顺序尝试'message'和'log'。
# 此参数仅适用于结构化(JSON)日志流。默认值:''。
stream stream #---JSON记录中包含“真实”日志流中逻辑日志流名称的字段的名称。
# 针对每个逻辑日志流单独处理异常检测,即,即使逻辑日志流 的
# 消息在“真实”日志流中交织,也将检测到异常。因此,仅组合相
# 同逻辑流中的记录。如果设置为'',则忽略此参数。此参数仅适用于
# 结构化(JSON)日志流。默认值:''。
multiline_flush_interval 5 #---以秒为单位的间隔,在此之后将转发(可能尚未完成)缓冲的异常堆栈。
# 如果未设置,则不刷新不完整的异常堆栈。
max_bytes 500000
max_lines 1000
# -------日志拼接-------
@id filter_concat
@type concat #---Fluentd Filter插件,用于连接多个事件中分隔的多行日志。
key message
multiline_end_regexp /\n$/ #---以换行符“\n”拼接
separator ""
# ------过滤Kubernetes metadata数据使用pod和namespace metadata丰富容器日志记录-------
# 关于插件请查看地址:https://github.com/fabric8io/fluent-plugin-kubernetes_metadata_filter
@id filter_kubernetes_metadata
@type kubernetes_metadata
# ------修复ElasticSearch中的JSON字段------
# 关于插件请查看地址:https://github.com/repeatedly/fluent-plugin-multi-format-parser
@id filter_parser
@type parser #---multi-format-parser多格式解析器插件
key_name log #---在要解析的记录中指定字段名称。
reserve_data true #---在解析结果中保留原始键值对。
remove_key_name_field true #---key_name解析成功后删除字段。
@type multi_format
format json
format none
###### Kuberntes集群节点机器上的日志收集 ######
system.input.conf: |-
# ------Kubernetes minion节点日志信息,可以去掉------
#
# ------启动脚本日志,可以去掉------
#
# ------Docker 程序日志,可以去掉------
#
#------ETCD 日志,因为ETCD现在默认启动到容器中,采集容器日志顺便就采集了,可以去掉------
#
#------Kubelet 日志------
#
创建 fluentd-es-config.yaml 文件
$ vi fluentd-es-config.yaml
添加如下内容:
kind: ConfigMap
apiVersion: v1
metadata:
name: fluentd-es-config
namespace: logging
labels:
addonmanager.kubernetes.io/mode: Reconcile
data:
#------系统配置参数-----
system.conf: |-
root_dir /tmp/fluentd-buffers/
#------Kubernetes 容器日志收集配置------
containers.input.conf: |-
@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
@type multi_format
format json
time_key time
time_format %Y-%m-%dT%H:%M:%S.%NZ
format /^(?
@id raw.kubernetes
@type detect_exceptions
remove_tag_prefix raw
message log
stream stream
multiline_flush_interval 5
max_bytes 500000
max_lines 1000
@id filter_concat
@type concat
key message
multiline_end_regexp /\n$/
separator ""
@id filter_kubernetes_metadata
@type kubernetes_metadata
@id filter_parser
@type parser
key_name log
reserve_data true
remove_key_name_field true
@type multi_format
format json
format none
#------系统日志收集-------
system.input.conf: |-
@id journald-docker
@type systemd
matches [{ "_SYSTEMD_UNIT": "docker.service" }]
@type local
persistent true
path /var/log/journald-docker.pos
read_from_head true
tag docker
@id journald-container-runtime
@type systemd
matches [{ "_SYSTEMD_UNIT": "{{ fluentd_container_runtime_service }}.service" }]
@type local
persistent true
path /var/log/journald-container-runtime.pos
read_from_head true
tag container-runtime
@id journald-kubelet
@type systemd
matches [{ "_SYSTEMD_UNIT": "kubelet.service" }]
@type local
persistent true
path /var/log/journald-kubelet.pos
read_from_head true
tag kubelet
@id journald-node-problem-detector
@type systemd
matches [{ "_SYSTEMD_UNIT": "node-problem-detector.service" }]
@type local
persistent true
path /var/log/journald-node-problem-detector.pos
read_from_head true
tag node-problem-detector
@id kernel
@type systemd
matches [{ "_TRANSPORT": "kernel" }]
@type local
persistent true
path /var/log/kernel.pos
fields_strip_underscores true
fields_lowercase true
read_from_head true
tag kernel
#------输出到 ElasticSearch 配置------
output.conf: |-
@id elasticsearch
@type elasticsearch
@log_level info
type_name _doc
include_tag_key true
host elasticsearch-client #改成自己的 ElasticSearch 地址
port 9200
logstash_format true
logstash_prefix kubernetes
logst
@type file
path /var/log/fluentd-buffers/kubernetes.system.buffer
flush_mode interval
retry_type exponential_backoff
flush_thread_count 5
flush_interval 8s
retry_forever
retry_max_interval 30
chunk_limit_size 5M
queue_limit_length 10
overflow_action block
compress gzip #开启gzip提高日志采集性能
$ kubectl apply -f fluentd-es-config.yaml
创建 fluentd-rbac.yaml 文件
$ vi fluentd-rbac.yaml
添加如下内容:
apiVersion: v1
kind: ServiceAccount
metadata:
name: fluentd-es
namespace: logging
labels:
k8s-app: fluentd-es
addonmanager.kubernetes.io/mode: Reconcile
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: fluentd-es
labels:
k8s-app: fluentd-es
addonmanager.kubernetes.io/mode: Reconcile
rules:
- apiGroups:
- ""
resources:
- "namespaces"
- "pods"
verbs:
- "get"
- "watch"
- "list"
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: fluentd-es
labels:
k8s-app: fluentd-es
addonmanager.kubernetes.io/mode: Reconcile
subjects:
- kind: ServiceAccount
name: fluentd-es
namespace: logging
apiGroup: ""
roleRef:
kind: ClusterRole
name: fluentd-es
apiGroup: ""
创建 Fluentd ServiceAccount
$ kubectl apply -f fluentd-rbac.yaml
当节点出现问题时,优先级低的 Pod 在资源不足时,容易首先被驱逐,因而对于重要的 daemonset 或者重要的应用组件,用户可以设置较高的优先级防止被抢占。这里创建一个优先级资源,方便后面应用到 fluentd。
创建 fluentd-rbac.yaml 文件
$ vi fluentd-priorityclass.yaml
创建 fluenntd-priorityclass.yaml
apiVersion: scheduling.k8s.io/v1beta1
kind: PriorityClass
metadata:
name: fluentd-priority
value: 1000000
globalDefault: false
description: ""
创建 Fluentd PriorityClass
$ kubectl apply -f fluentd-priorityclass.yaml
创建 fluentd-rbac.yaml 文件
$ vi fluentd.yaml
添加如下内容:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-es
namespace: logging
labels:
k8s-app: fluentd-es
version: v2.5.2
addonmanager.kubernetes.io/mode: Reconcile
spec:
selector:
matchLabels:
k8s-app: fluentd-es
version: v2.5.2
template:
metadata:
labels:
k8s-app: fluentd-es
version: v2.5.2
#此注释确保如果节点被驱逐,fluentd不会被驱逐
#支持关键的基于pod注释的优先级方案。
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
seccomp.security.alpha.kubernetes.io/pod: 'docker/default'
spec:
priorityClassName: fluentd-priority #给 Fluentd 设置优先级资源
serviceAccountName: fluentd-es #给 Fluentd 分配权限账户
#设置容忍所有污点,这样可以收集所有节点日志如 Master 节点一般都被设污,不设置无法在其节点启动 fluentd。
tolerations:
- operator: "Exists"
containers:
- name: fluentd-es
image: mydlqclub/fluentd-elasticsearch:v2.5.2
env:
- name: FLUENTD_ARGS
value: --no-supervisor -q #不启用管理,-q 命令用平静时期于减少warn级别日志(-qq:减少error日志)
resources:
limits:
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: config-volume
mountPath: /etc/fluent/config.d
terminationGracePeriodSeconds: 30 #Kubernetes 将会给应用发送SIGTERM信号,用来优雅地关闭应用
volumes:
- name: varlog #将 Kubernetes 节点服务器日志目录挂入
hostPath:
path: /var/log
- name: varlibdockercontainers #挂入 Docker 容器日志目录
hostPath:
path: /var/lib/docker/containers
- name: config-volume #挂入 Fluentd 的配置参数
configMap:
name: fluentd-es-config
创建 Fluentd
$ kubectl apply -f fluentd.yaml
$ kubectl get pod,daemonset -n logging | grep fluent
pod/fluentd-es-cw6tj 1/1 Running 0 2m45s
pod/fluentd-es-lt4cz 1/1 Running 0 2m45s
pod/fluentd-es-x6hfg 1/1 Running 0 2m45s
pod/fluentd-es-zpxql 1/1 Running 0 2m45s
daemonset.extensions/fluentd-es 4 4 4 4 4 2m46s
(1)、Kibana 中设置检索的索引
由于在 Fluentd 输出配置中配置了 “logstash_prefix kubernetes” 这个参数,所以索引是以 kubernetes 为前缀显示,如果未设置则默认为 “logstash” 为前缀。