就我而言,我使用的是最新版本的aws-for-fluent-bit V2.15.0,因为我想将应用程序日志保存在 cloudwatch 中,并且此映像已准备好处理该问题。
我没有使用 Kubernetes 过滤器,因为它添加了很多我可以直接在集群中看到的东西,我只需要 cloudwatch 中的应用程序日志供开发人员使用。所以我使用这个亚马逊提供的 yaml作为基础,只使用容器日志的INPUT尾部和container_firstline解析器。
正如您将看到的,我创建了自己的过滤器,称为“解析器”,它获取日志并执行正则表达式。我的日志很特别,因为我们在某些情况下使用嵌入 JSON,所以最后,我有 2 种类型的日志,一种只有文本,另一种带有 JSON,如下所示:
2021-06-09 15:01:26: a5c35b84: block-bridge-5cdc7bc966-cq44r: clients::63 INFO: Message received from topic block.customer.get.info
2021-06-09 15:01:28: a5c35b84: block-bridge-5cdc7bc966-cq44r: block_client::455 INFO: Filters that will be applied (parsed to PascalCase): {"ClientId": 88888, "ServiceNumber": "BBBBBBFA5527", "Status": "AC"}
这 2 种类型的日志,让我创建了 2 个 PARSER 类型的正则表达式和 1 个称为解析器的自定义 FILTER。过滤器使用解析器(parser_logs 和 parser_json)匹配这两种类型的日志。
主要问题是 JSON 部分未正确解析,始终使用反斜杠 (\) 获取 JSON 部分以转义双引号 ("),如下所示:
2021-06-09 15:01:28: a5c35b84: block-bridge-5cdc7bc966-cq44r: block_client::455 INFO: Filters that will be applied (parsed to PascalCase): {\"ClientId\": 88888, \"ServiceNumber\": \"BBBBBBFA5527\", \"Status\": "AC"}
解决方案是添加许多人说不需要的Decode_Field_As 。就我而言,我需要它来删除那些反斜杠()。您会看到我只使用与 JSON 完全匹配的字段“additional_message”。
最后,这是我的配置:
.
.
[INPUT]
Name tail
Tag kube.*
Exclude_Path /var/log/containers/cloudwatch-agent*, /var/log/containers/fluent-bit*, /var/log/containers/aws-node*, /var/log/containers/kube-proxy*
Path /var/log/containers/*.log
Docker_Mode On
Docker_Mode_Flush 5
Docker_Mode_Parser container_firstline
Parser docker
DB /var/fluent-bit/state/flb_kube.db
Mem_Buf_Limit 10MB
Skip_Long_Lines Off
Refresh_Interval 10
[FILTER]
Name parser
Match kube.*
Key_Name log
Parser parser_json
Parser parser_logs
.
.
.
[PARSER]
Name parser_logs
Format regex
Regex ^(?<time_stamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}): (?<environment>.*?): (?<hostname>.*?): (?<module>.*?)::(?<line>\d+) (?<log_level>[A-Z]+): (?<message>[a-zA-Z0-9 _.,:()'"!¡]*)$
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
[PARSER]
Name parser_json
Format regex
Regex ^(?<time_stamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}): (?<environment>.*?): (?<hostname>.*?): (?<module>.*?)::(?<line>\d+) (?<log_level>[A-Z]+): (?<message>[^{]*)(?<message_additional>{.*)$
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
Decode_Field_As escaped_utf8 message_additional do_next
Decode_Field_As escaped message_additional do_next
Decode_Field_As json message_additional
[PARSER]
Name container_firstline
Format regex
Regex (?<log>(?<="log":")\S(?!\.).*?)(?<!\\)".*(?<stream>(?<="stream":").*?)".*(?<time>\d{4}-\d{1,2}-\d{1,2}T\d{2}:\d{2}:\d{2}\.\w*).*(?=})
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%LZ
[PARSER]
Name docker
Format json
Time_Key @timestamp
Time_Format %Y-%m-%dT%H:%M:%S.%L
Time_Keep Off
要记住的一件事是Decode_Field_As需要将要解码的字段必须完全是 JSON(以“{”开头并以“}”结尾)。如果它有文本,然后是 JSON,则解码将失败。这就是为什么我必须创建 2 PARSER regex.. 以完全匹配一个名为“message_additional”的唯一字段内的某些日志中的 JSON。
这是我在 cloudwatch 中解析的新日志:
{
"environment": "a5c35b84",
"hostname": "block-bridge-5cdc7bc966-qfptx",
"line": "753",
"log_level": "INFO",
"message": "Message received from topic block.customer.get.info",
"module": "block_client",
"time_stamp": "2021-06-15 10:24:38"
}
{
"environment": "a5c35b84",
"hostname": "block-bridge-5cdc7bc966-m5sln",
"line": "64",
"log_level": "INFO",
"message": "Getting ticket(s) using params ",
"message_additional": {
"ClientId": 88888,
"ServiceNumber": "BBBBBBFA5527",
"Status": "AC"
},
"module": "block_client",
"time_stamp": "2021-06-15 10:26:04"
}