概述
Banzai logging operator 已经出到了 v3 版本。这个项目以 Fluentd 为基础,使用 Operator 的实现模式,在 Kubernetes 上用 CRD 的形式,对日志的采集行为进行定制,并进行过滤、路由等操作,最终可以将日志输出到 Elasticsearch、Loki、S3、Kafka 等多种后端。

图中可见,Logging 把日志分为了采集、路由和输出三个阶段。这三个阶段对应三种不同的 CRD:
-
采集:
使用 fluentbit 对日志进行采集
-
路由:
在 fluentd 中使用多种条件对日志条目进行过滤,并将结果发往目标
-
输出:
可以定义各种后端用于接收存储日志。
安装
可以使用 Helm 进行安装:
$ kubectl create ns loggingnamespace/logging created$ helm repo add banzaicloud-stable \ https://kubernetes-charts.banzaicloud.com"banzaicloud-stable" has been added to your repositories$ helm install --namespace logging \ logging banzaicloud-stable/logging-operator \ --set createCustomResource=false...
安装之后,会看到 logging 命名空间中的 Pod:
$ kubectl get po -n loggingNAME READY STATUS RESTARTS AGE...logging-logging-operator-7b4f9987f9-86clp 1/1 Running 0 120m
Logging
首先可以定义一个新的 Logging 对象:
apiVersion: logging.banzaicloud.io/v1beta1kind: Loggingmetadata: name: default-logging-simplespec: fluentd: {} fluentbit: {} controlNamespace: logging
提交到集群:
$ kubectl apply -f empty-logging.yamllogging.logging.banzaicloud.io/empty-logging created$ kubectl get podsNAME READY STATUS RESTARTS AGEempty-logging-fluentbit-2pghs 0/1 ContainerCreating 0 0sempty-logging-fluentbit-cc4r4 0/1 ContainerCreating 0 0sempty-logging-fluentbit-jzkpr 0/1 ContainerCreating 0 0sempty-logging-fluentd-0 0/2 Pending...
Describe 新生成的 Pod,会发现它们加载了几个 Secret 作为配置文件。例如 fluentbit 的内容:
$ kubectl view-secret empty-logging-fluentbitChoosing key: fluent-bit.conf...[OUTPUT] Name forward Match * Host empty-logging-fluentd.logging.svc Port 24240 Retry_Limit False
这里的配置表明,采集器收集到的日志会输出到 empty-logging-fluentd 的服务之中。
追查一下 fluentd 的配置内容,发现其输出配置为空,也就是说,没有提供输出能力。
查看 operator 的日志:
$ kubectl logs -f -l app.kubernetes.io/name=logging-operator...{"level":"info","ts":1583835777.4591844,"logger":"controllers.Logging","msg":"resource created","name":"empty-logging-fluentbit","namespace":"logging","apiVersion":"apps/v1","kind":"DaemonSet"}...{"level":"info","ts":1583835834.1114376,"logger":"controllers.Logging","msg":"no flows found, generating empty model"}
输出日志中表示,缺乏 flow 定义。
Output
先使用 Helm 安装 Loki,然后定义一个 output:
apiVersion: logging.banzaicloud.io/v1beta1kind: Outputmetadata: name: loki-outputspec: loki: url: http://loki-1583844504.loki:3100 configure_kubernetes_labels: true buffer: timekey: 1m timekey_wait: 30s timekey_use_utc: true
创建这个资源之后,Secret 和 Pod 都没发生什么变化,甚至 Operator Pod 的日志都没有输出内容,看来还是需要创建 Flow 将日志输出过去。
Flow
创建如下的 Flow 对象:
apiVersion: logging.banzaicloud.io/v1beta1kind: Flowmetadata: name: loki-flowspec: filters: - tag_normaliser: {} - parser: remove_key_name_field: true reserve_data: true parse: type: nginx match: - select: labels: app.kubernetes.io/name: log-generator outputRefs: - loki-output
其中 filters 成员中标识了我们要对应用进行的处理,使用 tag_normaliser 加入 Kubernetes 标签。
在 match 中使用标签加入过滤功能,这里选择了 app.kubernetes.io/name: log-generator 的标签对
outputRefs 指定输出到前面创建的 loki-output。
CRD 创建之后
进入 fluentd Pod 的 Shell,会发现配置发生变化:
$ cat fluentd/app-config/fluentd.conf<match **>... <match> labels app.kubernetes.io/name:log-generator namespaces logging... <match kubernetes.**> @type tag_normaliser @id loki-flow_0_tag_normaliser format ${namespace_name}.${pod_name}.${container_name} </match> <filter **> @type parser @id loki-flow_1_parser... <parse> @type nginx... <match **> @type loki
部署一个应用:
apiVersion: apps/v1kind: Deploymentmetadata: name: log-generatorspec: selector: matchLabels: app.kubernetes.io/name: log-generator replicas: 1 template: metadata: labels: app.kubernetes.io/name: log-generator spec: containers: - name: nginx image: banzaicloud/log-generator:0.3.2
此时打开 Loki 的 Grafana,就能对日志进行查询了:

结语
这个产品很好的展示了 Operator 固化运维技能的特征。化繁为简,将日志集采过程中所需的复杂知识,精选为一系列的配置组合,以 CRD 的形式呈现给非专家型客户,开箱即用。
kubectl 的 view-secret 插件,Bug 比较严重,不要问我是怎么知道的。