使用fluentbit解析containerd多行日志



在从Docker转移到containerd作为我们的kubernetes使用的Docker引擎后,我们无法通过可视化应用程序(Grafana(以正确的方式显示多行日志,因为容器本身已经在容器/pod日志中准备了一些细节(即时间戳、流和日志严重性,具体而言,它附加了以下内容,如以下示例所示:2022-07-25T06:43:17.20958947Z stdout F(,这使得开发人员和应用程序所有者。

我在这里展示了应用程序生成的日志的伪样本,以及在containerd准备好上述细节后,它是如何打印在kuberenets节点的节点中的。

应用程序生成的以下日志(kubectl日志(:

2022-07-25T06:43:17,309ESC[0;39m dummy-[txtThreadPool-2] ESC[39mDEBUGESC[0;39m
  ESC[36mcom.pkg.sample.ComponentESC[0;39m - Process message meta {
  timestamp: 1658731397308720468
  version {
      major: 1
      minor: 0
      patch: 0
  }
}

当我检查文件系统中的日志(/var/log/container/ABCXYZ.log(时:

2022-07-25T06:43:17.20958947Z stdout F 2022-07-25T06:43:17,309ESC[0;39m dummy-[txtThreadPool-2]
ESC[39mDEBUGESC[0;39m
ESC[36mcom.pkg.sample.ComponentESC[0;39m - Process message meta {
2022-07-25T06:43:17.20958947Z stdout F timestamp: 1658731449723010774
2022-07-25T06:43:17.209593379Z stdout F version {
2022-07-25T06:43:17.209595933Z stdout F major: 14
2022-07-25T06:43:17.209598466Z stdout F minor: 0
2022-07-25T06:43:17.209600712Z stdout F patch: 0
2022-07-25T06:43:17.209602926Z stdout F }
2022-07-25T06:43:17.209605099Z stdout F }

我可以用fluentbit解析多行日志,但问题是我无法删除containerd注入的详细信息(>2022-07-25T06:43:17.209605099Z stdout F……(。那么,是否可以将containerd配置为不在日志中以某种方式预处理这些详细信息,并在从应用程序/容器生成这些详细信息时将其打印出来?

另一方面,是否有任何插件可以从fluentbit端删除这些细节。。根据现有的插件,它们都不能操作或更改日志(这是合乎逻辑的,因为日志代理不应该对日志进行任何更改(。

提前谢谢。

这是我通过应用额外的fluentbit过滤器和多行解析器来显示Grafana中的多行日志行的解决方法。

1-首先,我通过尾部输入接收流,后者通过多行解析器(multilineKubeParser(对其进行解析。

2-然后另一个过滤器将拦截流,由正则表达式解析器(kubeParser(进行进一步处理。

3-之后,另一个过滤器将通过lua解析器((删除containerd添加的详细信息。

fluent-bit.conf: |-
[SERVICE]
HTTP_Server    On
HTTP_Listen    0.0.0.0
HTTP_PORT      2020
Flush          1
Daemon         Off
Log_Level      warn
Parsers_File   parsers.conf
[INPUT]
Name           tail
Tag            kube.*
Path           /var/log/containers/*.log
multiline.Parser         multilineKubeParser
Exclude_Path   /var/log/containers/*_ABC-logging_*.log
DB             /run/fluent-bit/flb_kube.db
Mem_Buf_Limit  5MB
[FILTER]
Name           kubernetes
Match          kube.*
Kube_URL       https://kubernetes.default.svc:443
Merge_Log On
Merge_Parser   kubeParser
K8S-Logging.Parser Off
K8S-Logging.Exclude On
[FILTER]
Name           lua
Match          kube.*
call remove_dummy
Script filters.lua
[Output]
Name grafana-loki
Match kube.*
Url http://loki:3100/api/prom/push
TenantID ""
BatchWait 1
BatchSize 1048576
Labels {job="fluent-bit"}
RemoveKeys kubernetes
AutoKubernetesLabels false
LabelMapPath /fluent-bit/etc/labelmap.json
LineFormat json
LogLevel warn
labelmap.json: |-
{
"kubernetes": {
"container_name": "container",
"host": "node",
"labels": {
"app": "app",
"release": "release"
},
"namespace_name": "namespace",
"pod_name": "instance"
},
"stream": "stream"
}
parsers.conf: |-
[PARSER]
Name        kubeParser
Format      regex
Regex       /^([^ ]*).* (?<timeStamp>[^a].*) ([^ ].*)[(?<requestId>[^]]*)] (?<severity>[^ ]*) (?<message>[^ ].*)$/
Time_Key    time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Time_Keep   On
Time_Offset +0200
[MULTILINE_PARSER]
name          multilineKubeParser
type          regex
flush_timeout 1000           
rule      "start_state"   "/[^ ]* stdout .s+W*w+dddd-dd-dd dd:dd:dd,ddd.*$/"  "cont"
rule      "cont"          "/[^ ]* stdout .s+(?!W+w+dddd-dd-dd dd:dd:dd,ddd).*$/"   "cont"
filters.lua: |-
function remove_dummy(tag, timestamp, record)
new_log=string.gsub(record["log"],"%d+-%d+-%d+T%d+:%d+:%d+.%d+Z%sstdout%sF%s","")
new_record=record
new_record["log"]=new_log
return 2, timestamp, new_record
end

正如我所提到的,这是一种变通方法,直到我能找到任何其他/更好的解决方案。

containerd的配置选项中,似乎无法以任何方式配置日志记录。你可以在这里看到配置文档。

此外,我检查了containerd内的日志记录代码,当日志从容器的stdout重定向时,这似乎是为日志准备的。您可以看到这里的测试用例通过";"分裂";收到的日志行。它检查日志的content之前的tagstream条目。我想这就是containerd中处理日志的方式。

最好的做法是用你的设计需求在项目中打开一个问题,也许团队可以为你开发可配置的stdout重定向。

这可能会有所帮助。他们使用自定义regex来捕获消息日志和日志中的其余信息,然后在嵌套过滤器中使用lift来压平json。https://github.com/microsoft/fluentbit-containerd-cri-o-json-log

最新更新