掌握Fluent Bit:在Kubernetes上控制日志的实践指南

本文详细介绍了如何在Kubernetes集群中使用Fluent Bit构建中心化日志收集管道,涵盖从基础安装、配置输入输出插件到使用过滤器和修饰器实现日志筛选与增强的全过程,是掌握云原生环境可观测性的实用教程。

:本文是对先前发布的《在Kubernetes上使用Fluent Bit控制日志(第4部分)》的特殊更新。此次更新的原因是在周末发现,收购了VMware(Bitnami目录的托管方)的博通公司,将目录转移到了一个“遗留目录”中且不再更新。这迫使Logs Control Easy Install项目、相关研讨会及本文必须全部更新。

让我们看看这些变化对原文意味着什么,并为您提供一份使用Fluent Bit控制Kubernetes集群日志的新指南。

与系列所有文章一样,我将先简要介绍Fluent Bit,然后分享如何在Kubernetes集群上使用Fluent Bit遥测管道来控制生成的所有日志。

什么是Fluent Bit?

在深入Fluent Bit之前,我们先看看这个项目在Fluent组织中的位置。查看Github上的Fluent组织,可以发现Fluentd和Fluent Bit项目。背景是,该项目始于日志解析项目Fluentd,后加入CNCF并于2019年达到毕业状态。

当世界进入云原生Kubernetes环境时,显然该解决方案并非为Kubernetes所需的灵活轻量要求而设计。Fluent Bit正是为了满足云原生Kubernetes环境对低资源消耗、高吞吐量、高可扩展性日志管理解决方案的需求而诞生的。该项目于2017年在Fluent组织内作为子项目启动,上周随着v4版本的发布,现已拥有10年历史!

Fluent Bit已远不止一个灵活轻量的日志管道解决方案,它现在能够处理指标和追踪,正成为那些希望在数据收集源头控制遥测数据的人首选的遥测管道收集工具。

让我们开始使用Fluent Bit,看看它能做些什么!

为什么要在Kubernetes集群上控制日志?

当您深入云原生世界时,这意味着您正在Kubernetes上部署容器。随着您的应用程序和微服务在这个动态的基础设施环境中交互,复杂性急剧增加。

部署可以自动扩缩,Pod根据需要启动和关闭,而所有这些底层是各种Kubernetes控制组件。所有这些都会生成遥测数据,Fluent Bit是一种在Kubernetes集群中控制它们的绝佳方式。它提供了一种通过中央遥测管道随时收集所有数据的方法,同时提供了解析、过滤和路由所有遥测数据的能力。

对于开发者,本文将演示在开发Kubernetes集群上使用Fluent Bit作为单个日志收集点,并结合已部署的工作负载。最后,本文中的所有示例均在OSX上完成,并假设读者能够将此处展示的操作转换到自己的本地机器上执行。

从何处开始

为确保您已准备好开始控制Kubernetes集群日志,本文其余部分假设您已阅读并完成了前文的所有步骤。这确保了:

  • 您正在运行一个两节点的Kubernetes集群
  • 有以Ghost CMS形式运行的工作负载
  • 安装了Fluent Bit来收集所有容器日志。

如果您没有完成前文,我提供了一个Logs Control Easy Install项目仓库,您可以下载、解压并运行一个命令,在本地机器上启动具备上述设置的Kubernetes集群。

无论选择哪种路径,一旦设置完成,您就可以查看包含此运行集群上生成的所有内容的Fluent Bit日志。这包括两个命名空间(kube-systemlogging)的日志。

您可以通过浏览这些命名空间来验证它们正在运行,以下是我本地机器的示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ kubectl --kubeconfig target/logdemoconfig.yaml get pods --namespace kube-system

NAME                                           READY   STATUS   RESTARTS  AGE
coredns-668d6bf9bc-2skfg                       1/1     Running  0         2m43s
coredns-668d6bf9bc-79jpn                       1/1     Running  0         2m43s
etcd-logdemo-control-plane                     1/1     Running  0         2m51s
kindnet-7lm5s                                  1/1     Running  0         2m43s
kube-apiserver-logdemo-control-plane           1/1     Running  0         2m50s
kube-controller-manager-logdemo-control-plane  1/1     Running  0         2m50s
kube-proxy-2q9db                               1/1     Running  0         2m43s
kube-scheduler-logdemo-control-plane           1/1     Running  0         2m50s


$ kubectl --kubeconfig target/logdemoconfig.yaml get pods --namespace default

NAME                             READY   STATUS    RESTARTS   AGE
log-generator-7cdff9fcf8-qgw9k   1/1     Running   0          5m4s


$ kubectl --kubeconfig target/logdemoconfig.yaml get pods --namespace logging

NAME               READY   STATUS    RESTARTS   AGE
fluent-bit-vk2rf   1/1     Running   0          4m49s

在我们的设置中使用的 fluent-bit-helm.yaml 配置文件(如下所示,加粗部分)为Fluent Bit实例提供了初始配置,用于从所有命名空间收集所有容器日志:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 args:
  - --workdir=/fluent-bit/etc
  - --config=/fluent-bit/etc/conf/fluent-bit.yaml

config:
  extraFiles:
    fluent-bit.yaml: |
      service:
       flush: 1
       log_level: info
       http_server: true
       http_listen: 0.0.0.0
       http_port: 2020
      pipeline:
        inputs:
          - name: tail
            tag: kube.*
            read_from_head: true
            path: /var/log/containers/*.log
            multiline.parser: docker, cri
        outputs:
          - name: stdout
            match: '*'

要查看收集到的所有日志,我们可以使用上面找到的Pod名称转储Fluent Bit日志文件,如下所示:

1
2
3
4
$ kubectl --kubeconfig target/logdemoconfig.yaml logs fluent-bit-vk2rf --nanmespace logging

[OUTPUT-CUT-DUE-TO-LOG-VOLUME]
...

在浏览时,您可能会注意到有错误和信息消息,如果仔细观察,还会发现来自Kubernetes Pod、应用程序工作负载甚至您的Fluent Bit实例的日志。作为在集群上工作的开发人员,如何在这片日志海洋中找到有用的东西?好消息是您确实有一个集中查看日志的地方!

另一点需要提及的是,通过使用Fluent Bit的tail输入插件并将其设置为从每个日志文件的开头读取,我们确保了遥测数据取自所有日志。如果我们不设置从日志文件开头收集,我们的遥测管道将错过Fluent Bit实例启动前生成的所有内容。这确保了我们拥有工作负载的启动消息,并且每次修改管道配置时,都可以在标准日志遥测事件上进行测试。

让我们开始控制日志,看看作为开发人员如何利用我们希望在本地开发测试期间看到的日志数据。

重新获得控制权

首先,我们可以将日志收集工作仅集中在我们感兴趣的工作负载上。在本示例中,我们旨在发现Log Generator应用程序部署中的问题。由于您对 kube-system 命名空间中发生的任何日志不感兴趣,可以将Fluent Bit输入插件的关注范围缩小到仅检查Log Generator日志文件。

这可以通过创建一个名为 myfluent-bit-helm.yaml 的新配置文件并更改默认路径(如下加粗所示)来实现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
args:
  - --workdir=/fluent-bit/etc
  - --config=/fluent-bit/etc/conf/fluent-bit.yaml

config:
  extraFiles:
    fluent-bit.yaml: |
      service:
       flush: 1
       log_level: info
       http_server: true
       http_listen: 0.0.0.0
       http_port: 2020
      pipeline:
        inputs:
          - name: tail
            tag: kube.*
            read_from_head: true
            path: /var/log/containers/*generator*
            multiline.parser: docker, cri
        outputs:
          - name: stdout
            match: '*'

下一步是使用helm更新命令更新Fluent Bit实例,如下所示:

1
2
3
4
$ helm upgrade --kubeconfig target/logdemoconfig.yaml --install fluent-bit fluent/fluent-bit --set image.tag=4.0.0 --namespace=logging --create-namespace --values=myfluent-bit-helm.yaml

NAME               READY   STATUS    RESTARTS   AGE
fluent-bit-mzktk   1/1     Running   0          28s

现在,探索Fluent Bit收集的日志,注意所有 kube-system 命名空间的日志都不再出现,我们可以专注于已部署的工作负载。

1
2
3
4
5
6
7
$ kubectl --kubeconfig target/logdemoconfig.yaml logs fluent-bit-mzktk --nanmespace logging

...
[0] kube.var.log.containers.log-generator-7cdff9fcf8-qgw9k_default_log-generator-f1be04153240cf686ba99566f79d64a0e2496a4b555dd833000e1ff222f73dc8.log: [[1762440627.216814972, {}], {"time"=>"2025-11-06T14:50:27.216814972Z", "stream"=>"stdout", "_p"=>"F", "log"=>"Thu Nov  6 14:50:27 UTC 2025 - This is a log message from the log generator."}]
[0] kube.var.log.containers.log-generator-7cdff9fcf8-qgw9k_default_log-generator-f1be04153240cf686ba99566f79d64a0e2496a4b555dd833000e1ff222f73dc8.log: [[1762440630.220889184, {}], {"time"=>"2025-11-06T14:50:30.220889184Z", "stream"=>"stdout", "_p"=>"F", "log"=>"Thu Nov  6 14:50:30 UTC 2025 - {message:true 200 success}"}]
[0] kube.var.log.containers.log-generator-7cdff9fcf8-qgw9k_default_log-generator-f1be04153240cf686ba99566f79d64a0e2496a4b555dd833000e1ff222f73dc8.log: [[1762440633.226102188, {}], {"time"=>"2025-11-06T14:50:33.226102188Z", "stream"=>"stderr", "_p"=>"F", "log"=>"Thu Nov  6 14:50:33 UTC 2025 - {message:false 500 error}"}]
...

这只是总输出中的部分日志行。如果仔细观察,会发现这些日志有自己的格式,因此让我们对其进行标准化,使输出格式为JSON,并通过更改Fluent Bit输出插件配置使各种时间戳更易读,如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
args:
  - --workdir=/fluent-bit/etc
  - --config=/fluent-bit/etc/conf/fluent-bit.yaml

config:
  extraFiles:
    fluent-bit.yaml: |
      service:
       flush: 1
       log_level: info
       http_server: true
       http_listen: 0.0.0.0
       http_port: 2020
      pipeline:
        inputs:
          - name: tail
            tag: kube.*
            read_from_head: true
            path: /var/log/containers/*ghost*
            multiline.parser: docker, cri
        outputs:
          - name: stdout
            match: '*'
            format: json_lines
            json_date_format: java_sql_timestamp

使用helm更新命令更新Fluent Bit实例,如下所示:

1
2
3
4
$ helm upgrade --kubeconfig target/logdemoconfig.yaml --install fluent-bit fluent/fluent-bit --set image.tag=4.0.0 --namespace=logging --create-namespace --values=myfluent-bit-helm.yaml

NAME               READY   STATUS    RESTARTS   AGE
fluent-bit-gqsc8   1/1     Running   0          42s

现在探索Fluent Bit收集的日志,注意输出变化:

1
2
3
4
5
6
$ kubectl --kubeconfig target/logdemoconfig.yaml logs fluent-bit-gqsc8 --nanmespace logging
...
{"date":"2025-11-06 14:51:44.314963","time":"2025-11-06T14:51:44.314963452Z","stream":"stdout","_p":"F","log":"Thu Nov  6 14:51:44 UTC 2025 - This is a log message from the log generator."}
{"date":"2025-11-06 14:51:47.317883","time":"2025-11-06T14:51:47.317883265Z","stream":"stdout","_p":"F","log":"Thu Nov  6 14:51:47 UTC 2025 - {message:true 200 success}"}
{"date":"2025-11-06 14:51:50.321730","time":"2025-11-06T14:51:50.321730204Z","stream":"stderr","_p":"F","log":"Thu Nov  6 14:51:50 UTC 2025 - {message:false 500 error}"}
...

现在,如果更仔细地查看消息数组,作为开发人员,我们已经注意到混合了stderrstdout日志行。让我们重新控制,剔除所有不包含stderr的行,因为我们只对出错的内容感兴趣。

我们需要在Fluent Bit配置中添加一个过滤器部分,使用grep过滤器,并针对键stream或值stderr选择正则表达式,如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
args:
  - --workdir=/fluent-bit/etc
  - --config=/fluent-bit/etc/conf/fluent-bit.yaml

config:
  extraFiles:
    fluent-bit.yaml: |
      service:
       flush: 1
       log_level: info
       http_server: true
       http_listen: 0.0.0.0
       http_port: 2020
      pipeline:
        inputs:
          - name: tail
            tag: kube.*
            read_from_head: true
            path: /var/log/containers/*ghost*
            multiline.parser: docker, cri
        filters:
          - name: grep
            match: '*'
            regex: stream stderr
        outputs:
          - name: stdout
            match: '*'
            format: json_lines
            json_date_format: java_sql_timestamp

使用helm更新命令更新Fluent Bit实例,如下所示:

1
2
3
4
$ helm upgrade --kubeconfig target/logdemoconfig.yaml --install fluent-bit fluent/fluent-bit --set image.tag=4.0.0 --namespace=logging --create-namespace --values=myfluent-bit-helm.yaml

NAME               READY   STATUS    RESTARTS   AGE
fluent-bit-npn8n   1/1     Running   0          12s

现在探索Fluent Bit收集的日志,注意输出变化:

1
2
3
4
5
6
7
8
$ kubectl --kubeconfig target/logdemoconfig.yaml logs fluent-bit-npn8n --nanmespace logging
...
{"date":"2025-11-06 14:52:56.411711","time":"2025-11-06T14:52:56.411711621Z","stream":"stderr","_p":"F","log":"Thu Nov  6 14:52:56 UTC 2025 - {message:false 500 error}"}
{"date":"2025-11-06 14:53:07.426493","time":"2025-11-06T14:53:07.426493474Z","stream":"stderr","_p":"F","log":"Thu Nov  6 14:53:07 UTC 2025 - {message:false 500 error}"}
{"date":"2025-11-06 14:53:18.441807","time":"2025-11-06T14:53:18.441807795Z","stream":"stderr","_p":"F","log":"Thu Nov  6 14:53:18 UTC 2025 - {message:false 500 error}"}
{"date":"2025-11-06 14:53:29.453509","time":"2025-11-06T14:53:29.453509211Z","stream":"stderr","_p":"F","log":"Thu Nov  6 14:53:29 UTC 2025 - {message:false 500 error}"}
{"date":"2025-11-06 14:53:40.462905","time":"2025-11-06T14:53:40.462905134Z","stream":"stderr","_p":"F","log":"Thu Nov  6 14:53:40 UTC 2025 - {message:false 500 error}"}
...

现在我们不再看到标准输出日志事件,因为我们的遥测管道经过过滤,只显示标记为stderr的错误日志!

这个练习展示了如何在Kubernetes集群上使用Fluent Bit遥测管道来格式化和修剪日志。现在,让我们看看如何丰富日志遥测数据。

我们将在每个标准错误行中添加标签,以告知待命的开发人员需要联系的SRE人员。为此,我们扩展Fluent Bit配置的过滤器部分,使用修改过滤器,针对键stream或值stderr,删除这些键并添加两个新键STATUSACTION,如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
args:
  - --workdir=/fluent-bit/etc
  - --config=/fluent-bit/etc/conf/fluent-bit.yaml

config:
  extraFiles:
    fluent-bit.yaml: |
      service:
       flush: 1
       log_level: info
       http_server: true
       http_listen: 0.0.0.0
       http_port: 2020
      pipeline:
        inputs:
          - name: tail
            tag: kube.*
            read_from_head: true
            path: /var/log/containers/*ghost*
            multiline.parser: docker, cri
        filters:
          - name: grep
            match: '*'
            regex: stream stderr
          - name: modify
            match: '*'
            condition: Key_Value_Equals stream stderr
            remove: stream
            add:
              - STATUS REALLY_BAD
              - ACTION CALL_SRE
        outputs:
          - name: stdout
            match: '*'
            format: json_lines
            json_date_format: java_sql_timestamp

使用helm更新命令更新Fluent Bit实例,如下所示:

1
2
3
4
$ helm upgrade --kubeconfig target/logdemoconfig.yaml --install fluent-bit fluent/fluent-bit --set image.tag=4.0.0 --namespace=logging --create-namespace --values=myfluent-bit-helm.yaml

NAME               READY   STATUS    RESTARTS   AGE
fluent-bit-ftfs4   1/1     Running   0          32s

现在,探索Fluent Bit收集的日志,注意输出变化,其中stream键已消失,并且在每个错误日志事件末尾添加了两个新键:

1
2
3
4
5
6
7
8
9
$ kubectl --kubeconfig target/logdemoconfig.yaml logs fluent-bit-ftfs4 --nanmespace logging

...
[CUT-LINE-FOR-VIEWING] {message:false 500 error}","STATUS":"REALLY_BAD_ERROR","ACTION":"CALL_SRE"}
[CUT-LINE-FOR-VIEWING] {message:false 500 error}","STATUS":"REALLY_BAD_ERROR","ACTION":"CALL_SRE"}
[CUT-LINE-FOR-VIEWING] {message:false 500 error}","STATUS":"REALLY_BAD_ERROR","ACTION":"CALL_SRE"}
[CUT-LINE-FOR-VIEWING] {message:false 500 error}","STATUS":"REALLY_BAD_ERROR","ACTION":"CALL_SRE"}
[CUT-LINE-FOR-VIEWING] {message:false 500 error}","STATUS":"REALLY_BAD_ERROR","ACTION":"CALL_SRE"}
...

至此,我们有了一个正在运行的Kubernetes集群、一个生成日志的应用程序工作负载,以及一个用于收集和控制日志遥测数据的Fluent Bit遥测管道。

最初,我们发现收集所有日志遥测数据令人应接不暇,难以筛选出对开发需求重要的事件。然后,我们开始通过缩小收集策略、进行过滤,最后通过丰富遥测数据,重新获得了对日志遥测数据的控制权。

系列更多内容

在本文中,您学习了如何在Kubernetes集群上使用Fluent Bit来控制遥测数据。本文基于这个(已更新的)免费在线研讨会。

随着您继续学习如何配置、运行、管理和掌握Fluent Bit在实际中的应用,本系列将有更多内容。接下来是Fluent Bit服务部分配置的开发人员指南。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计