使用 OpenTelemetry 构建可观测性 04 - 收集器
在之前的博文中,我们讨论了如何使用 SDK 和链路追踪生产者来导出进程中的遥测数据。尽管有多种类型的导出器可供选择,但其中一个常见的目标是将数据导出到 OpenTelemetry Collector。本篇文章将深入探讨收集器以及如何使用它。
选 OTel Collector 还是其他
正如上一篇博客文章中提到的,我谈到了使用 OTLP 导出器将数据发送到 OTel Collector。此外我还提到,对导出器来说输出遥测数据的目的地是多样的。当导出器可以直接发送到 Jaeger、Prometheus 或控制台时,为什么还要选择 OTel Collector 呢?答案是由于灵活性:
- 将遥测数据从收集器同时发送给多个不同的目标
- 在发送之前对数据加工处理(添加/删除属性、批处理等)
- 解耦生产者和消费者
以下是 OTel Collector 工作原理的概览:

收集器的主要组件包括:
- 接收模块 - 从收集器外部收集遥测数据(例如 OTLP、Kafka、MySQL、syslog)
- 处理模块 - 处理或转换数据(例如属性、批次、Kubernetes 属性)
- 导出模块 - 将处理后的数据发送到另一个目标(例如 Jaeger、AWS Cloud Watch、Zipkin)
- 扩展模块 - 收集器增强功能的插件(例如 HTTP 转发器)
在 Kubernetes 中运行 OpenTelemetry Collector 的两种方式
运行 OTel Collector 的方法有多种,比如您可以将其作为独立进程运行。不过也有很多场景都会涉及到 Kubernetes 集群的使用,在 Kubernetes 中,有两种主要的方式来运行 OpenTelemetry Collector 收集器的运行方式主要有两种。
第一种方式(也是示例应用程序中使用的)是守护进程( DaemonSet ),每个集群节点上都有一个收集器 pod:

在这种情况下,产生遥测数据的实例将导出到同节点中收集器的实例里面。通常,还会有一个网关收集器,从节点中收集器的实例中汇总数据。
在 Kubernetes 中运行收集器的另一种方式是作为附加辅助容器和主程序部署在同一个Pod中的边车模式( sidecars )。也就是说,应用程序 Pod 和收集器实例之间存在一对一的映射关系,它们共享相同的资源,无需额外的网络开销,紧密耦合并共享相同的生命周期。

在 OpenTelemetry Operator 中是使用注释 sidecar.opentelemetry.io/inject 来实现将 sidecar 容器注入到应用程序 Pod 中。
核心版与贡献版的区别
正如您在上面所看到的,OTel Collector 是一个设计高度可插拔拓展的系统。这样的设计非常灵活,因为随着当前和未来各种接收模块、处理模块、导出模块和扩展模块的增加,我们就可以利用插件机制进行集成。 OpenTelemetry 引入收集器分发的概念,其含义是根据需要选择不同组件,以创建满足特定需求的定制化收集器版本。
在撰写本文时,有两个分发版:Core 和 contrib。核心分发版的命名恰如其分,仅包含核心模块。但贡献版呢?全部。可以看到它包含了一长串的接收模块、处理模块和导出模块的列表。
定制化收集器分发版的构建
如果核心版和贡献版都无法完全满足你的需求,你可以使用 OpenTelemetry 提供的 ocb 工具自定义自己的收集器分发版本。该工具可以帮助你选择和组合需要的功能和组件,以创建符合你特定需求的自定义收集器分发版本。这样你既可以获得所需的功能,又能避免贡献版中的不必要组件。
为了使用 ocb 工具构建自定义的收集器分发版本,你需要提供一个 YAML 清单文件来指定构建的方式。一种简单的做法是使用 contrib manifest.yaml ,在该文件的基础上删除不需要的组件,以创建适合应用程序需求的小型清单。这样你就可以得到一个只包含必要组件的自定义收集器分发版本,以满足当前收集器场景,而且没有多余的组件。
dist:
module: github.com/trstringer/otel-shopping-cart/collector
name: otel-shopping-cart-collector
description: OTel Shopping Cart Collector
version: 0.57.2
output_path: ./collector/dist
otelcol_version: 0.57.2
exporters:
- import: go.opentelemetry.io/collector/exporter/loggingexporter
gomod: go.opentelemetry.io/collector v0.57.2
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/jaegerexporter v0.57.2
processors:
- import: go.opentelemetry.io/collector/processor/batchprocessor
gomod: go.opentelemetry.io/collector v0.57.2
receivers:
- import: go.opentelemetry.io/collector/receiver/otlpreceiver
gomod: go.opentelemetry.io/collector v0.57.2
我修改了一些 dist 属性并删除了许多 exporters 、 processors 和 receivers 。现在可以根据需求构建定制化的收集器分发版了!
$ ocb --config ./collector/manifest.yaml
2022-08-09T20:38:24.325-0400 INFO internal/command.go:108 OpenTelemetry Collector Builder {"version": "0.57.2", "date": "2022-08-03T21:53:33Z"}
2022-08-09T20:38:24.326-0400 INFO internal/command.go:130 Using config file {"path": "./collector/manifest.yaml"}
2022-08-09T20:38:24.326-0400 INFO builder/config.go:99 Using go {"go-executable": "/usr/local/go/bin/go"}
2022-08-09T20:38:24.326-0400 INFO builder/main.go:76 Sources created {"path": "./collector/dist"}
2022-08-09T20:38:24.488-0400 INFO builder/main.go:108 Getting go modules
2022-08-09T20:38:24.521-0400 INFO builder/main.go:87 Compiling
2022-08-09T20:38:25.345-0400 INFO builder/main.go:94 Compiled {"binary": "./collector/dist/otel-shopping-cart-collector"}
最终输出一个二进制文件,在我的环境中,位于 ./collector/dist/otel-shopping-cart-collector 。不过还没结束,由于要在 Kubernetes 中运行这个收集器,所以需要创建一个容器映像。使用 contrib Dockerfile 作为基础模版,最终得到以下内容:
Dockerfile Dockerfile
FROM alpine:3.13 as certs
RUN apk --update add ca-certificates
FROM alpine:3.13 AS collector-build
COPY ./collector/dist/otel-shopping-cart-collector /otel-shopping-cart-collector
RUN chmod 755 /otel-shopping-cart-collector
FROM ubuntu:latest
ARG USER_UID=10001
USER ${USER_UID}
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=collector-build /otel-shopping-cart-collector /
COPY collector/config.yaml /etc/collector/config.yaml
ENTRYPOINT ["/otel-shopping-cart-collector"]
CMD ["--config", "/etc/collector/config.yaml"]
EXPOSE 4317 55678 55679
在本例中,我将 config.yaml 直接嵌入到镜像中,但您可以通过使用 ConfigMap 来使其更加动态:
config.yaml
receivers:
otlp:
protocols:
grpc:
http:
processors:
batch:
exporters:
logging:
logLevel: debug
jaeger:
endpoint: jaeger-collector:14250
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [logging, jaeger]
最后创建此镜像后,我需要创建 DaemonSet 清单:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: otel-collector-agent
spec:
selector:
matchLabels:
app: otel-collector
template:
metadata:
labels:
app: otel-collector
spec:
containers:
- name: opentelemetry-collector
image: "{{ .Values.collector.image.repository }}:{{ .Values.collector.image.tag }}"
imagePullPolicy: "{{ .Values.collector.image.pullPolicy }}"
env:
- name: MY_POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
ports:
- containerPort: 14250
hostPort: 14250
name: jaeger-grpc
protocol: TCP
- containerPort: 4317
hostPort: 4317
name: otlp
protocol: TCP
- containerPort: 4318
hostPort: 4318
name: otlp-http
protocol: TCP
dnsPolicy: ClusterFirst
restartPolicy: Always
terminationGracePeriodSeconds: 30
我使用的是Helm Chart 来部署,并设置了一些动态设置的配置值。安装时可以通过查看收集器的日志,来验证这些值是否正确地被应用:
2022-08-10T00:47:00.703Z info service/telemetry.go:103 Setting up own telemetry...
2022-08-10T00:47:00.703Z info service/telemetry.go:138 Serving Prometheus metrics {"address": ":8888", "level": "basic"}
2022-08-10T00:47:00.703Z info components/components.go:30 In development component. May change in the future. {"kind": "exporter", "data_type": "traces", "name":
2022-08-10T00:47:00.722Z info extensions/extensions.go:42 Starting extensions...
2022-08-10T00:47:00.722Z info pipelines/pipelines.go:74 Starting exporters...
2022-08-10T00:47:00.722Z info pipelines/pipelines.go:78 Exporter is starting... {"kind": "exporter", "data_type": "traces", "name": "logging"}
2022-08-10T00:47:00.722Z info pipelines/pipelines.go:82 Exporter started. {"kind": "exporter", "data_type": "traces", "name": "logging"}
2022-08-10T00:47:00.722Z info pipelines/pipelines.go:78 Exporter is starting... {"kind": "exporter", "data_type": "traces", "name": "jaeger"}
2022-08-10T00:47:00.722Z info pipelines/pipelines.go:82 Exporter started. {"kind": "exporter", "data_type": "traces", "name": "jaeger"}
2022-08-10T00:47:00.722Z info pipelines/pipelines.go:86 Starting processors...
2022-08-10T00:47:00.722Z info jaegerexporter@v0.57.2/exporter.go:186 State of the connection with the Jaeger Collector backend {"kind": "exporter", "data_type
2022-08-10T00:47:00.722Z info pipelines/pipelines.go:90 Processor is starting... {"kind": "processor", "name": "batch", "pipeline": "traces"}
2022-08-10T00:47:00.722Z info pipelines/pipelines.go:94 Processor started. {"kind": "processor", "name": "batch", "pipeline": "traces"}
2022-08-10T00:47:00.722Z info pipelines/pipelines.go:98 Starting receivers...
2022-08-10T00:47:00.722Z info pipelines/pipelines.go:102 Receiver is starting... {"kind": "receiver", "name": "otlp", "pipeline": "traces"}
2022-08-10T00:47:00.722Z info otlpreceiver/otlp.go:70 Starting GRPC server on endpoint 0.0.0.0:4317 {"kind": "receiver", "name": "otlp", "pipeline": "traces"}
2022-08-10T00:47:00.722Z info otlpreceiver/otlp.go:88 Starting HTTP server on endpoint 0.0.0.0:4318 {"kind": "receiver", "name": "otlp", "pipeline": "traces"}
2022-08-10T00:47:00.722Z info pipelines/pipelines.go:106 Receiver started. {"kind": "receiver", "name": "otlp", "pipeline": "traces"}
2022-08-10T00:47:00.722Z info service/collector.go:215 Starting otel-shopping-cart-collector... {"Version": "0.57.2", "NumCPU": 4}
最后一行显示了自定义分发版的名称:“otel-shopping-cart-collector”。就像这样,使用 Helm Chart 和自定义分发版的收集器可以提供灵活性和精确控制的优势,即能够满足特定的需求,也不会添加不必要的额外部分。
总结
OpenTelemetry Collector 是一个功能强大的工具,它的一大优点是您可以创建自己的收集器分发版来满足您的需求。在我看来,这种灵活性使得 OpenTelemetry Collector 在 OpenTelemetry 生态系统中具备重要作用。
本文翻译自:https://trstringer.com/otel-part4-collector/
扩展阅读:
使用 OpenTelemetry 构建可观测性 04 - 收集器的更多相关文章
- [一] java8 函数式编程入门 什么是函数式编程 函数接口概念 流和收集器基本概念
本文是针对于java8引入函数式编程概念以及stream流相关的一些简单介绍 什么是函数式编程? java程序员第一反应可能会理解成类的成员方法一类的东西 此处并不是这个含义,更接近是数学上的 ...
- JDK1.7 Update14 HotSpot虚拟机GC收集器
在测试服务器上使用如下命令可以查看当前使用的 GC收集器,当然不止这一个命令可以看到,还有其他一些方式 第三列”=”表示第四列是参数的默认值,而”:=” 表明了参数被用户或者JVM赋值了 [csii@ ...
- JAVA8给我带了什么——流的概念和收集器
到现在为止,笔者不敢给流下定义,从概念来讲他应该也是一种数据元素才是.可是在我们前面的代码例子中我们可以看到他更多的好像在表示他是一组处理数据的行为组合.这让笔者很难去理解他的定义.所以笔者不表态.各 ...
- jvm-垃圾收集器与内存分配策略
垃圾收集器与内存分配策略 参考: https://my.oschina.net/hosee/blog/644085 http://www.cnblogs.com/zhguang/p/Java-JVM- ...
- Stream01 定义、迭代、操作、惰性求值、创建流、并行流、收集器、stream运行机制
1 Stream Stream 是 Java 8 提供的一系列对可迭代元素处理的优化方案,使用 Stream 可以大大减少代码量,提高代码的可读性并且使代码更易并行. 2 迭代 2.1 需求 随机创建 ...
- JVM之GI收集器
Garbage-First,面向服务端的垃圾收集器. 并行与并发:充分利用多核环境减少停顿时间, 分代收集:不需要配合其它收集器 空间整合:整体上看属于标记整理算法,局部(region之间)数据复制算 ...
- JVM之SerialOld收集器
Serial收集器的老年代版本 单线程收集器 标记-整理算法 stop the world Client模式下的虚拟机使用 Server模式下,搭配Parallel Scavenge使用及CMS发生C ...
- JVM之Parallel Scavenge收集器
新生代收集器,复制算法,并行收集,面向吞吐量要求(吞吐量优先收集器). 吞吐量=用户代码运行时间/(用户代码运行时间+垃圾回收时间) -XX:MaxGCPauseMillis:控制最大垃圾收集停顿时间 ...
- JVM之ParNew收集器
新生代收集器,CMS默认搭配,Serial的多线程版本. -XX:UseParNewGC:指定使用ParNew收集器. -XX:ParalletGCThreads:指定限制垃圾收收集的线程数量. 默认 ...
- JVM实用参数(七)CMS收集器
HotSpot JVM的并发标记清理收集器(CMS收集器)的主要目标就是:低应用停顿时间.该目标对于大多数交互式应用很重要,比如web应用.在我们看一下有关JVM的参数之前,让我们简要回顾CMS收集器 ...
随机推荐
- 力扣32(java)-最长有效括号(困难)
题目: 给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度. 示例 1: 输入:s = "(()"输出:2解释:最长有效括号子串是 &quo ...
- 5G新基建 边缘计算乘风破浪
作者 | 张羽辰(同昭)阿里云交付专家 导读:如今,几乎所有的事情都离不开软件,当你开车时,脚踩上油门,实际上是车载计算机通过力度感应等计算输出功率,最终来控制油门,你从未想过这会是某个工程师的代码. ...
- K8s Ingress Provider 为什么选择 MSE 云原生网关?
简介:在虚拟化时期的微服务架构下,业务通常采用流量网关 + 微服务网关的两层架构,流量网关负责南北向流量调度和安全防护,微服务网关负责东西向流量调度和服务治理,而在容器和 K8s 主导的云原生时代, ...
- 分久必合的Lindorm传奇
简介: 2009年,阿里巴巴首先提出用分布式架构替代传统商业数据库,成功用自主开源的AliSQL支撑双11数据洪流:2016年,为应对超大规模业务场景,阿里云开始自研分布式数据库.十余年间,阿里巴巴数 ...
- 基于 MaxCompute 的智能推荐解决方案
简介: 在互联网行业红利已过.在获客成本越来越高.在用户在线时长全网基本无增长以及信息大爆炸的情况下,如何更好的转化新用户和提升老用户粘性就变得至关重要,智能化的个性化推荐无疑是经过验证的重要手段之一 ...
- 超好用的 Redis GUI 工具,你值得拥有
超好用的 Redis GUI 工具,你值得拥有 提供原生的性能,并且比使用 Electron 等 Web 技术开发的同等应用程序消耗的资源少得多. 下载地址:http://www.redisant.c ...
- 记录一个HttpClient超时连接配置不生效的问题排查过程
现象 首先有一个被服务由于内存有限,导致巨卡.导致调用他的服务出现线程阻塞.jstack打印线程池如下所示: 开始排查解决问题 第一步:检查代码看是否超时设置是否正确,因为感觉超时设置正确不可能阻塞. ...
- C++ Grammar Focus
一.结构体 1.基础模板 struct Node { <变量类型1> 变量名1; <变量类型2> 变量名2; ... } <定义变量名1>,<定义变量名2&g ...
- 【强化学习】Markov Decision processes【二】
目录 Markov Decision processes Markov Process Markov reward process Markov Decision processes 马尔可夫决策过程 ...
- 简说Python之循环语句
目录 Python的运算逻辑 Python条件语句 Python循环语句 Python while循环 Python for 循环 条件语句和循环语句是程序常用的一种基础语法,从语言上来说,能说清楚的 ...