问卷链接(https://www.wjx.cn/jq/9714648...)
作者:Juraci Paixão Kröhling
OpenTelemetry 收集器是一个二进制程序,通常作为代理部署在运行业务应用程序的主机上,但是现在越来越多的应用程序运行在像 Kubernetes 这样的容器平台上。
在 Kubernetes 上运行 OpenTelemetry 收集器需要什么呢?
OpenTelemetry 收集器项目附带了一个示例文件以供 Kubernetes 使用,但是该示例文件的目的是作为一个指南,而不是作为一个可用于生产的解决方案。收集器是如此通用,以至于几乎不可能实现一刀切的部署配置。
部署模式
收集器的裸金属部署很容易规划和执行:它是作为主机上的守护进程运行的单个二进制文件。然而,对于 Kubernetes,我们有几个选择:
- Deployment,多个副本可能在同一个节点上共存
- DaemonSet,每个 Kubernetes 节点都有一个实例
- StatefulSet,始终存在精确数量的副本,每个副本都有一个可预测的名称(collector-1, collector-2,…)
- Sidecar,一个实例作为容器与运行你的业务应用程序的每个 pod 一起存在,扮演代理的角色
最常见的情况是,你可以混合使用 Deployment 和 Sidecar:Deployment 具有高度弹性,可以通过水平 Pod Autoscale 自动伸缩,而 Sidecar 允许你的应用程序将遥测数据卸载到运行在同一“主机”中的进程。Sidecar 更有可能拥有特定于业务应用程序的定制配置(即处理器),而 Deployment 通常是更通用的配置。
DaemonSet 最常用于单租户、多云部署,在这种情况下,需要确保来自应用程序的遥测数据在到达公共 internet 之前由同一个节点中的一个进程进行预处理。
当收集器实例的副本数量不会频繁更改,并且你正在使用可以从稳定的主机名列表(例如负载平衡导出器)中受益的处理器时,应该使用 StatefulSet。
开列清单
为部署设计好拓扑之后,就可以开始编制清单了!对于本例,我们将使用经典的 Deployment+Sidecar 模式。
无论采用哪种部署模式,你都可能需要为收集器提供一个配置文件。因为这必须是一个实际的文件,我们将为它创建一个 ConfigMap,像这样:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: collector-config
data:
collector.yaml: |
receivers:
otlp:
protocols:
grpc:
processors:
exporters:
logging:
service:
pipelines:
traces:
receivers: [otlp]
processors: []
exporters: [logging]
---
apiVersion: v1
kind: ConfigMap
metadata:
name: agent-config
data:
agent.yaml: |
receivers:
otlp:
protocols:
grpc:
processors:
exporters:
otlp:
endpoint: "opentelemetrycollector.default.svc.cluster.local:4317"
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: []
exporters: [otlp]
接下来,我们可以创建我们的 Deployment。最简单的解决方案是:
apiVersion: apps/v1
kind: Deployment
metadata:
name: opentelemetrycollector
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: opentelemetrycollector
template:
metadata:
labels:
app.kubernetes.io/name: opentelemetrycollector
spec:
containers:
- name: otelcol
args:
- --config=/conf/collector.yaml
image: otel/opentelemetry-collector:0.18.0
volumeMounts:
- mountPath: /conf
name: collector-config
volumes:
- configMap:
items:
- key: collector.yaml
path: collector.yaml
name: collector-config
name: collector-config
我们现在有了一个启动并运行的收集器实例,但是它仍然不能接收数据:为此,我们需要一个Service来暴露我们在配置中声明的 OTLP 端口。以下是满足该需求的服务定义:
apiVersion: v1
kind: Service
metadata:
name: opentelemetrycollector
spec:
ports:
- name: grpc-otlp
port: 4317
protocol: TCP
targetPort: 4317
selector:
app.kubernetes.io/name: opentelemetrycollector
type: ClusterIP
测试
现在,我们已经为收集器准备好了所有部件,现在是时候启动一个生成跟踪并将其发送到收集器的应用程序了。为此,我们将创建一个 Deployment,其中包含一个应用程序,该应用程序为接收到的每个 HTTP 请求创建跟踪。这个应用程序被打包在一个名为quay.io/jpkroehling/generate-span-java:0.1.0的容器镜像中,我们可以使用如下 Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: myapp
template:
metadata:
labels:
app.kubernetes.io/name: myapp
spec:
containers:
- name: myapp
image: quay.io/jpkroehling/generate-span-java:0.1.0
- name: agent
image: otel/opentelemetry-collector:0.18.0
args:
- --config=/conf/agent.yaml
volumeMounts:
- mountPath: /conf
name: agent-config
volumes:
- configMap:
items:
- key: agent.yaml
path: agent.yaml
name: agent-config
name: agent-config
当 Deployment 就绪,我们就可以调用它的/orders 端点,它将为我们生成一些跨度。进行测试的最简单方法是执行端口转发,这样对 localhost:8080/orders 的调用就会落在 Kubernetes 集群中的应用程序上:
$ kubectl port-forward deployment/myapp 8080
Forwarding from 127.0.0.1:8080 -> 8080
现在让我们为我们的收集器跟踪日志:一旦我们调用了我们的服务,收集器中的 loggingexport 将确保在日志中记录这个事件。
$ kubectl logs deployments/opentelemetrycollector -f
...
2021-01-22T12:59:53.561Z info service/service.go:267 Everything is ready. Begin running and processing data.
最后,让我们生成一些跨度:
$ curl localhost:8080/order
Created
在收集器的日志中,我们现在应该看到如下内容:
2021-01-22T13:26:49.320Z INFO loggingexporter/logging_exporter.go:313 TracesExporter {"#spans": 2}
2021-01-22T13:26:49.430Z INFO loggingexporter/logging_exporter.go:313 TracesExporter {"#spans": 1}
2021-01-22T13:26:50.422Z INFO loggingexporter/logging_exporter.go:313 TracesExporter {"#spans": 4}
2021-01-22T13:26:50.571Z INFO loggingexporter/logging_exporter.go:313 TracesExporter {"#spans": 1}
这证实了在我们的应用程序中生成的跨已经通过 sidecar 代理转到收集器。在真实的设置中,我们将配置收集器以将我们的 span 导出到真实的后端,如 Jaeger 或 Zipkin。
其他选择
到目前为止,你可能已经意识到在 Kubernetes 上部署一个简单的 OpenTelemetry 收集器实例并不是那么困难。但第二天的问题该怎样,比如版本升级?或者如何使 Service 与 ConfigMap 保持同步,以便配置中定义的所有端口都通过服务自动暴露?自动将 sidecar 注入到业务部署中不是很好吗?这些都是OpenTelemetry Operator 可以完成的任务。
如果你更喜欢 Helm Charts,也有一个实验性的版本可以安装收集器。
总结
OpenTelemetry 收集器是一个非常灵活和轻量级的进程,使混合和匹配策略成为可能,允许根据你非常特定的需求构建收集器链。在 Kubernetes 中部署收集器的单个实例并不是一项复杂的任务,尽管维护这些实例可能会让你考虑使用像 Helm Charts 或 Operator 这样的工具。
感谢 Gary Brown。
CNCF (Cloud Native Computing Foundation)成立于2015年12月,隶属于Linux Foundation,是非营利性组织。
CNCF(云原生计算基金会)致力于培育和维护一个厂商中立的开源生态系统,来推广云原生技术。我们通过将最前沿的模式民主化,让这些创新为大众所用。扫描二维码关注CNCF微信公众号。