searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享

OpenTelemetry Collector 的新容器日志解析器

2024-11-07 09:25:16
2
0

文件日志接收器是 OpenTelemetry Collector 中使用最广泛的组件之一,这在最近的调查中得到了体现。根据同一调查,Kubernetes 成为 Collector 部署的主要平台(80.6%)也就不足为奇了。基于这两个事实,我们可以认识到在 Kubernetes 环境中无缝日志收集的重要性。

目前,文件日志接收器能够解析 Kubernetes Pods 的容器日志,但它需要广泛的配置,以便根据各种容器运行时格式正确解析日志。原因在于容器日志可能采用不同的已知格式,具体取决于容器运行时,因此需要执行一系列特定的操作以便正确解析它们:

  1. 在运行时检测传入日志的格式。
  2. 根据其特定格式的特点解析每种格式。例如,定义其是 JSON 还是纯文本,并考虑时间戳格式。
  3. 提取已知的元数据,依靠预定义的模式。

这样的高级操作序列可以通过将适当的段操作符连接在一起来处理。最终结果相当复杂。这种配置复杂性可以通过使用相应的 helm chart 预设来减轻。然而,尽管有预设,用户仍然可能会发现维护和故障排除这种高级配置具有挑战性。

社区过去曾提出改善 Kubernetes 日志收集体验的问题。实现这一目标的一步是提供一个简化且强大的选项,用于解析容器日志,而无需手动指定或维护实现细节。随着新容器解析器的提议和实施,所有这些实现细节都被封装并在解析器的实现中处理。另外,覆盖实现的单元测试和各种故障转移逻辑的能力表明,在容器日志解析方面有了显著的改进。

容器日志的样例

首先,让我们快速回顾一下可能出现的不同容器日志格式:

  • Docker 容器日志:{"log":"INFO: This is a docker log line","stream":"stdout","time":"2024-03-30T08:31:20.545192187Z"}
  • cri-o 日志:2024-04-13T07:59:37.505201169-05:00 stdout F This is a cri-o log line!
  • Containerd 日志: 2024-04-22T10:27:25.813799277Z stdout F This is an awesome containerd log line!

我们可以注意到 cri-o 和 containerd 的日志格式非常相似(都遵循 CRI 日志格式),但时间戳格式上有细微差别。

为了正确处理这三种不同格式,您需要三条不同的段操作符路线,正如我们在容器解析器操作符的问题中所看到的。

此外,CRI 格式可以提供部分日志,您可能希望将它们首先合并成一条,示例:

2024-04-06T00:17:10.113242941Z stdout P This is a very very long line th
2024-04-06T00:17:10.113242941Z stdout P at is really really long and spa
2024-04-06T00:17:10.113242941Z stdout F ns across multiple log entries

理想情况下,您希望我们的解析器能够在运行时自动检测格式并正确解析日志行。稍后我们将看到容器解析器将为我们做到这一点。

处理属性

容器日志文件遵循特定的命名模式,您可以从中提取有用的元数据信息。例如,从 /var/log/pods/kube-system_kube-scheduler-kind-control-plane_49cc7c1fd3702c40b2686ea7486091d3/kube-scheduler/1.log 中,您可以提取命名空间、Pod 的名称和 UID,以及容器的名称。

提取这些元数据后,您需要使用适当的属性正确存储它,遵循语义约定。这种处理也可以封装在解析器的实现中,从而消除用户手动定义的需要。

使用新容器解析器

考虑到以上所有因素,容器解析器可以这样配置:

receivers:
  filelog:
    include_file_path: true
    include:
      - /var/log/pods/*/*/*.log
    operators:
      - id: container-parser
        type: container

该配置足以正确解析日志行并提取所有有用的 Kubernetes 元数据。现在显然所需的配置大大减少。使用操作符的组合可能会导致约 69 行配置,正如在原始提案中指出的那样。

在 /var/log/pods/kube-system_kube-controller-kind-control-plane_49cc7c1fd3702c40b2686ea7486091d6/kube-controller/1.log 中写入的日志行 {"log":"INFO: This is a docker log line","stream":"stdout","time":"2024-03-30T08:31:20.545192187Z"} 将生成如下日志条目:

{
  "timestamp": "2024-03-30 08:31:20.545192187 +0000 UTC",
  "body": "INFO: This is a docker log line",
  "attributes": {
    "time": "2024-03-30T08:31:20.545192187Z",
    "log.iostream": "stdout",
    "log.file.path": "/var/log/pods/kube-system_kube-controller-kind-control-plane_49cc7c1fd3702c40b2686ea7486091d6/kube-controller/1.log"
  },
  "resource": {
    "attributes": {
      "k8s.pod.name": "kube-controller-kind-control-plane",
      "k8s.pod.uid": "49cc7c1fd3702c40b2686ea7486091d6",
      "k8s.container.name": "kube-controller",
      "k8s.container.restart_count": "1",
      "k8s.namespace.name": "kube-system"
    }
  }
}

您可以注意到,您不需要定义格式。解析器会自动检测格式并相应地解析日志。即使是 cri-o 或 containerd 运行时可能生成的部分日志也会被正确地重新组合,而无需任何特殊配置。

这非常方便,因为作为用户,您不需要关心指定格式,甚至不需要维护不同环境的不同配置。

实现细节

为了实现该解析器操作符,大部分代码是从头编写的,但我们能够在内部重用重新组合操作符来处理部分日志解析。为了实现这一点,需要进行一些小的重构,但这给了我们重用一个已经存在且经过良好测试的组件的机会。

在讨论实现此功能的过程中,出现了一个问题:为什么要将其实现为操作符而不是处理器?

一个基本原因是,传递到处理器的日志记录的顺序是不保证的。然而,我们需要确保这一点,以便正确处理部分日志解析。这就是为什么目前将其实现为操作符是可行的。此外,目前建议在收集期间尽可能多地进行工作,而拥有强大的解析能力可以实现这一点。

有关实施讨论的更多信息可以在相关的 GitHub 问题及其相关/链接的 PR 中找到。

最后但并非最不重要的是,我们应该提到,通过特定容器解析器的示例,我们可以注意到存在改进的空间,以及我们如何在未来对流行技术的已知日志格式进行进一步优化。

结论:使用 filelog 接收器,容器日志解析现在变得更容易

想要了解更多关于容器解析器的信息吗?请访问官方文档,如果您尝试后告诉我们您的想法。请随时在官方 CNCF Slack 工作区与我们联系,特别是在 #otel-collector 频道。

 

0条评论
0 / 1000
唐****程
14文章数
1粉丝数
唐****程
14 文章 | 1 粉丝

OpenTelemetry Collector 的新容器日志解析器

2024-11-07 09:25:16
2
0

文件日志接收器是 OpenTelemetry Collector 中使用最广泛的组件之一,这在最近的调查中得到了体现。根据同一调查,Kubernetes 成为 Collector 部署的主要平台(80.6%)也就不足为奇了。基于这两个事实,我们可以认识到在 Kubernetes 环境中无缝日志收集的重要性。

目前,文件日志接收器能够解析 Kubernetes Pods 的容器日志,但它需要广泛的配置,以便根据各种容器运行时格式正确解析日志。原因在于容器日志可能采用不同的已知格式,具体取决于容器运行时,因此需要执行一系列特定的操作以便正确解析它们:

  1. 在运行时检测传入日志的格式。
  2. 根据其特定格式的特点解析每种格式。例如,定义其是 JSON 还是纯文本,并考虑时间戳格式。
  3. 提取已知的元数据,依靠预定义的模式。

这样的高级操作序列可以通过将适当的段操作符连接在一起来处理。最终结果相当复杂。这种配置复杂性可以通过使用相应的 helm chart 预设来减轻。然而,尽管有预设,用户仍然可能会发现维护和故障排除这种高级配置具有挑战性。

社区过去曾提出改善 Kubernetes 日志收集体验的问题。实现这一目标的一步是提供一个简化且强大的选项,用于解析容器日志,而无需手动指定或维护实现细节。随着新容器解析器的提议和实施,所有这些实现细节都被封装并在解析器的实现中处理。另外,覆盖实现的单元测试和各种故障转移逻辑的能力表明,在容器日志解析方面有了显著的改进。

容器日志的样例

首先,让我们快速回顾一下可能出现的不同容器日志格式:

  • Docker 容器日志:{"log":"INFO: This is a docker log line","stream":"stdout","time":"2024-03-30T08:31:20.545192187Z"}
  • cri-o 日志:2024-04-13T07:59:37.505201169-05:00 stdout F This is a cri-o log line!
  • Containerd 日志: 2024-04-22T10:27:25.813799277Z stdout F This is an awesome containerd log line!

我们可以注意到 cri-o 和 containerd 的日志格式非常相似(都遵循 CRI 日志格式),但时间戳格式上有细微差别。

为了正确处理这三种不同格式,您需要三条不同的段操作符路线,正如我们在容器解析器操作符的问题中所看到的。

此外,CRI 格式可以提供部分日志,您可能希望将它们首先合并成一条,示例:

2024-04-06T00:17:10.113242941Z stdout P This is a very very long line th
2024-04-06T00:17:10.113242941Z stdout P at is really really long and spa
2024-04-06T00:17:10.113242941Z stdout F ns across multiple log entries

理想情况下,您希望我们的解析器能够在运行时自动检测格式并正确解析日志行。稍后我们将看到容器解析器将为我们做到这一点。

处理属性

容器日志文件遵循特定的命名模式,您可以从中提取有用的元数据信息。例如,从 /var/log/pods/kube-system_kube-scheduler-kind-control-plane_49cc7c1fd3702c40b2686ea7486091d3/kube-scheduler/1.log 中,您可以提取命名空间、Pod 的名称和 UID,以及容器的名称。

提取这些元数据后,您需要使用适当的属性正确存储它,遵循语义约定。这种处理也可以封装在解析器的实现中,从而消除用户手动定义的需要。

使用新容器解析器

考虑到以上所有因素,容器解析器可以这样配置:

receivers:
  filelog:
    include_file_path: true
    include:
      - /var/log/pods/*/*/*.log
    operators:
      - id: container-parser
        type: container

该配置足以正确解析日志行并提取所有有用的 Kubernetes 元数据。现在显然所需的配置大大减少。使用操作符的组合可能会导致约 69 行配置,正如在原始提案中指出的那样。

在 /var/log/pods/kube-system_kube-controller-kind-control-plane_49cc7c1fd3702c40b2686ea7486091d6/kube-controller/1.log 中写入的日志行 {"log":"INFO: This is a docker log line","stream":"stdout","time":"2024-03-30T08:31:20.545192187Z"} 将生成如下日志条目:

{
  "timestamp": "2024-03-30 08:31:20.545192187 +0000 UTC",
  "body": "INFO: This is a docker log line",
  "attributes": {
    "time": "2024-03-30T08:31:20.545192187Z",
    "log.iostream": "stdout",
    "log.file.path": "/var/log/pods/kube-system_kube-controller-kind-control-plane_49cc7c1fd3702c40b2686ea7486091d6/kube-controller/1.log"
  },
  "resource": {
    "attributes": {
      "k8s.pod.name": "kube-controller-kind-control-plane",
      "k8s.pod.uid": "49cc7c1fd3702c40b2686ea7486091d6",
      "k8s.container.name": "kube-controller",
      "k8s.container.restart_count": "1",
      "k8s.namespace.name": "kube-system"
    }
  }
}

您可以注意到,您不需要定义格式。解析器会自动检测格式并相应地解析日志。即使是 cri-o 或 containerd 运行时可能生成的部分日志也会被正确地重新组合,而无需任何特殊配置。

这非常方便,因为作为用户,您不需要关心指定格式,甚至不需要维护不同环境的不同配置。

实现细节

为了实现该解析器操作符,大部分代码是从头编写的,但我们能够在内部重用重新组合操作符来处理部分日志解析。为了实现这一点,需要进行一些小的重构,但这给了我们重用一个已经存在且经过良好测试的组件的机会。

在讨论实现此功能的过程中,出现了一个问题:为什么要将其实现为操作符而不是处理器?

一个基本原因是,传递到处理器的日志记录的顺序是不保证的。然而,我们需要确保这一点,以便正确处理部分日志解析。这就是为什么目前将其实现为操作符是可行的。此外,目前建议在收集期间尽可能多地进行工作,而拥有强大的解析能力可以实现这一点。

有关实施讨论的更多信息可以在相关的 GitHub 问题及其相关/链接的 PR 中找到。

最后但并非最不重要的是,我们应该提到,通过特定容器解析器的示例,我们可以注意到存在改进的空间,以及我们如何在未来对流行技术的已知日志格式进行进一步优化。

结论:使用 filelog 接收器,容器日志解析现在变得更容易

想要了解更多关于容器解析器的信息吗?请访问官方文档,如果您尝试后告诉我们您的想法。请随时在官方 CNCF Slack 工作区与我们联系,特别是在 #otel-collector 频道。

 

文章来自个人专栏
agent
14 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0