容器化让应用交付变得轻量,但排查问题时的上下文却更容易丢失。一次请求可能穿过多个 Pod、Service 和中间件,如果只有分散的 stdout 日志,很难还原完整调用链。OpenTelemetry 通过统一的 API、SDK 和 Collector 把指标、日志与链路整合成一条数据管道,而容器平台要做的是让这些数据自动带上 Pod、命名空间、节点等关键元数据。

实际落地时,容器集成不是简单地把探针打进镜像。更值得关注的是采集端如何跟随 Pod 调度、如何自动发现服务、如何把 Kubernetes 的资源信息注入到遥测数据中。下面从容器环境的特殊性讲起,再逐步拆解 Collector 部署、自动注入和关联配置。
容器环境对可观测性提出的特殊要求
传统的虚拟机上,一个服务通常长期运行在固定地址,采集器只要在配置里写明 IP 和端口就能稳定工作。容器环境完全不同,Pod 会因为滚动发布、扩缩容、节点驱逐或资源不足而被随时销毁和重建。每次重建之后,IP、主机名甚至运行节点都可能变化。可观测性系统如果还依赖静态目标列表,就会频繁遇到采集中断或数据错配。
容器平台也把日志和指标分散到了不同层级。应用日志可能输出到 stdout,由容器运行时写到节点上的 /var/log/containers 目录;kubelet 和容器运行时自己的指标需要在节点级采集;应用暴露的 Prometheus 指标又需要通过 ServiceMonitor 或注解发现。链路数据则要求请求在跨 Pod、跨节点传播时保持上下文。不同层级的数据如果不能用同一套标签关联,排查问题就只能在多个平台之间跳转。
因此,容器集成的重点不只是把数据发出去,而是让每一份遥测数据都天然带上 Kubernetes 的元数据,包括 Pod 名称、命名空间、节点、容器名和部署对象。OpenTelemetry 的资源属性和处理器机制正好适合承担这个任务,它可以在数据离开集群前完成元数据补全,而不用修改业务代码。
用 OpenTelemetry Collector 搭建容器数据管道
OpenTelemetry Collector 是集成的核心组件,它承担接收、处理和导出的职责。在 Kubernetes 里通常有三种部署形态。DaemonSet 模式每个节点部署一个采集器,适合收集节点级日志、kubelet 指标以及接收本节点 Pod 上报的 OTLP 数据;Deployment 模式作为集群级网关,适合做集中式过滤、路由和批量导出;Sidecar 模式与应用 Pod 同生命周期,适合对网络隔离要求高或需要本地缓冲的场景。
如果刚起步,建议先采用 DaemonSet 加一个中心 Collector 的两层结构。DaemonSet 负责靠近数据源做轻量处理和元数据补全,中心 Collector 负责把数据转发到 Prometheus、Tempo、Elasticsearch 或云厂商后端。这样既能减少中心 Collector 的连接压力,也能在节点级提前发现异常。
下面是一个 DaemonSet Collector 的关键配置,重点是通过 k8sattributes 处理器从 Kubernetes API 补全 Pod 和命名空间信息,并通过 filelog 接收器采集节点上的容器日志。
receivers:
otlp:
protocols:
grpc:
http:
filelog:
include:
- /var/log/containers/*.log
start_at: end
include_file_name: false
operators:
- type: container
id: container-parser
processors:
memory_limiter:
check_interval: 1s
limit_mib: 512
k8sattributes:
auth_type: "serviceAccount"
passthrough: false
extract:
metadata:
- k8s.pod.name
- k8s.namespace.name
- k8s.node.name
- k8s.container.name
pod_association:
- sources:
- from: resource_attribute
name: k8s.pod.name
- from: resource_attribute
name: k8s.namespace.name
exporters:
otlp:
endpoint: "otel-gateway:4317"
tls:
insecure: true
service:
pipelines:
logs:
receivers: [filelog]
processors: [memory_limiter, k8sattributes]
exporters: [otlp]
traces:
receivers: [otlp]
processors: [memory_limiter, k8sattributes]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [memory_limiter, k8sattributes]
exporters: [otlp]
这段配置里的 filelog 接收器会跟踪节点上的容器日志文件,container 算子负责从文件名中解析容器 ID 和 Pod 信息。之后 k8sattributes 处理器会调用 Kubernetes API 查询这些 Pod 的标签、命名空间和节点信息,把它们写入日志和链路数据的资源属性。导出到中心 Collector 后,后端就能按命名空间或 Pod 名称进行过滤和聚合。
通过 Operator 和自动注入减少业务侵入
如果每个服务都要手工在 Dockerfile 里下载探针、修改启动命令、配置导出地址,容器规模稍大就难以维护。OpenTelemetry Operator 提供了一种更自动化的方式,它通过 Instrumentation 自定义资源为不同语言注入探针,不需要重新构建镜像,也基本不侵入业务代码。
Operator 的工作方式是在 Pod 创建时通过 Kubernetes 的准入 Webhook 注入一个 init container 和若干环境变量。init container 会把 Java、Node.js、Python 等语言的 OpenTelemetry 探针拷贝到共享卷,业务容器启动时通过 JAVA_TOOL_OPTIONS、NODE_OPTIONS 等机制自动加载探针。这样业务镜像依然保持纯净,探针版本也可以由平台统一升级。
下面是一个 Java 应用的自动注入配置,它指定了探针镜像和导出端点,只要给应用 Pod 打上对应注解,Operator 就会完成后续注入。
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: java-instrumentation
namespace: demo
spec:
exporter:
endpoint: http://otel-collector.observability:4318
propagators:
- tracecontext
- baggage
- b3
java:
image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:latest
env:
- name: OTEL_METRICS_EXPORTER
value: otlp
- name: OTEL_LOGS_EXPORTER
value: otlp
应用侧只需要在 Pod 的 metadata.annotations 中加上 instrumentation.opentelemetry.io/inject-java: "true",Operator 就会读取这个 Instrumentation 定义并自动注入。不同语言对应不同注解,例如 Python 使用 inject-python,Node.js 使用 inject-nodejs。这种模式在测试环境非常方便,但在生产环境建议同时绑定探针版本和资源配置,避免 latest 标签带来不可控变更。
日志、指标、链路关联与采样策略
容器排查问题最怕的是日志链路互相独立。OpenTelemetry 的价值在于让三类信号使用同一套上下文。应用日志输出时如果能把 trace_id 和 span_id 写入结构化字段,就能从一条错误日志直接跳转到对应链路,再从链路视图看到调用过的数据库和缓存操作。具体做法是在日志格式中加入占位符,例如 Python 的 logging 模块可以通过 OpenTelemetry 日志集成自动补齐这些字段。
在 Collector 侧,除了 k8sattributes 补全 Pod 元数据,还可以通过 resource 处理器统一重命名属性,避免不同探针生成不同字段名。比如把 service.name 保持为应用名,把 k8s.namespace.name 作为环境标识。这样在 Prometheus 查询指标、在 Tempo 查询链路、在 Elasticsearch 查询日志时,可以用同一组标签定位问题。
采样策略也需要在容器集成时提前设计。高并发的容器服务会产生大量链路数据,全部保留成本很高。建议在应用 SDK 或 Collector 中使用概率采样,保留错误和慢请求的链路。Collector 可以使用 tailsampling 处理器按延迟阈值决定保留哪些 trace,也可以使用 probabilistic 采样器按固定比例采样。同时为 Collector 设置 memory_limiter 和合理的 CPU、内存资源限制,防止采集组件本身在节点资源紧张时被 OOM 杀掉。
最后需要说明,容器集成不是一次配置就能一劳永逸。随着集群规模增长,还应当关注 Collector 的副本数、导出端的批量大小、队列长度和重试策略。把 OpenTelemetry 的采集层作为平台基础设施来治理,才能真正让可观测性跟上容器化的演进节奏。
OpenTelemetry容器集成可观测性修改时间:2026-09-28 18:06:18