使用 OpenTelemetry Operator 管理 Collector 与自动插桩
将 Collector 和插桩声明为 Kubernetes 资源,并通过 Pod 注解注入 agent。
OpenTelemetry Operator 将两样东西作为 Kubernetes 资源来管理:Collector(一个 OpenTelemetryCollector 对象)和自动插桩(一个 Instrumentation 对象,外加告诉 Operator 注入 agent 的 Pod 注解)。应用团队只需添加一个注解就能获得遥测数据,而不必编辑 Dockerfile,平台团队则把设置集中保存在 Git 的一处。
安装 Operator
Operator 使用准入 webhook,需要 TLS 证书。最简单的途径是 cert-manager,chart 默认期望它。如果没有 cert-manager,让 Helm 生成自签名证书:
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update
helm install my-opentelemetry-operator open-telemetry/opentelemetry-operator \
--namespace opentelemetry-operator-system --create-namespace \
--set "manager.collectorImage.repository=otel/opentelemetry-collector-k8s" \
--set admissionWebhooks.certManager.enabled=false \
--set admissionWebhooks.autoGenerateCert.enabled=true
如果已经安装了 cert-manager,你可以保持证书设置为默认值,或者通过 admissionWebhooks.certManager.issuerRef 引用你自己的 issuer。用 --version 固定 chart 版本,并把 values 放在文件或 Flux HelmRelease 中,而不是 --set 参数里。
声明一个 Collector
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: demo
namespace: observability
spec:
mode: deployment # deployment, daemonset, statefulset, or sidecar
replicas: 2
config:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 80
spike_limit_percentage: 20
batch: {}
exporters:
debug: {}
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [debug]
config 块就是你一直在编写的同样的 Collector YAML,嵌入在资源中。Operator 创建工作负载和一个名为 <name>-collector(这里是 demo-collector)的 Service,暴露你的 receiver 所使用的端口。可用的 mode 值对应于部署指南中的模式:daemonset 用于 agent,deployment 用于 gateway,sidecar 用于注入到应用 pod 中的 Collector。请检查你集群中可用的 CRD 版本(kubectl get crd opentelemetrycollectors.opentelemetry.io),因为 API 版本在各个发布版本中有过变化。
声明插桩设置
Instrumentation 资源保存 Operator 注入到被注解 pod 中的 SDK 设置:
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: demo-instrumentation
namespace: webapp
spec:
exporter:
endpoint: http://demo-collector.observability.svc.cluster.local:4318
propagators:
- tracecontext
- baggage
sampler:
type: parentbased_traceidratio
argument: "0.25"
java:
env:
- name: OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED
value: "true"
重要的细节:
- 如果省略
exporter.endpoint,它默认为http://localhost:4317,这通常什么也送不到。请始终把它设为你的 Collector 的 Service。 - 对于位于另一个命名空间中的 Collector,请使用完整的 DNS 名称
<service>.<namespace>.svc.cluster.local。 - 文档中的示例对 .NET、Go、Java 和 Python 使用端口
4318(HTTP),对 Node.js 使用4317(gRPC)。请让端口与该语言 agent 所使用的协议相匹配。 - 特定于语言的环境变量放在
spec.<language>.env下,比如spec.java.env或spec.python.env。
请在应用之前创建 Instrumentation。 Operator 在创建 pod 时注入 agent。如果该资源当时还不存在,pod 会在没有 init 容器的情况下启动,你就得重启它。
用注解让工作负载选择加入
在 Deployment 的 pod 模板上添加一个注解:
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkout
namespace: webapp
spec:
selector:
matchLabels: { app: checkout }
template:
metadata:
labels: { app: checkout }
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
spec:
containers:
- name: checkout
image: myorg/checkout:1.4.2
每种语言的注解:
| 语言 | 注解 |
|---|---|
| Java | instrumentation.opentelemetry.io/inject-java: "true" |
| Python | instrumentation.opentelemetry.io/inject-python: "true" |
| Node.js | instrumentation.opentelemetry.io/inject-nodejs: "true" |
| .NET | instrumentation.opentelemetry.io/inject-dotnet: "true" |
| Go | instrumentation.opentelemetry.io/inject-go: "true"(外加目标可执行文件注解) |
| 仅 SDK 设置 | instrumentation.opentelemetry.io/inject-sdk: "true" |
值可以是 "true"(使用此命名空间中的 Instrumentation)、某个 Instrumentation 的名称("my-instrumentation")、带命名空间的名称("other-ns/my-instrumentation")或 "false"。把注解放在命名空间上,可以为其中每个工作负载插桩。
你会用到的相关注解:
instrumentation.opentelemetry.io/container-names: "app,worker"选择要插桩哪些容器。默认只有第一个容器会被插桩。resource.opentelemetry.io/service.name: checkout设置资源属性,比如服务名称。其他还有service.version和deployment.environment.name。instrumentation.opentelemetry.io/inject-sdk: "true"只注入环境变量,适用于已经包含 SDK 的应用。- 单个容器不能注入多于一种语言。多容器、多语言的设置需要
enable-multi-instrumentation功能开关,以及按语言划分的容器名称注解。 - Go 需要
enable-go-instrumentation功能门、otel-go-auto-target-exe注解(或OTEL_GO_AUTO_TARGET_EXE设置),以及一个特权 sidecar,所以请先审视其中的安全影响。
应用与验证
kubectl apply -f collector.yaml -f instrumentation.yaml
kubectl apply -f checkout-deployment.yaml
kubectl get opentelemetrycollectors,instrumentations -A
kubectl get pod -n webapp -l app=checkout -o jsonpath='{.items[0].spec.initContainers[*].name}'; echo
kubectl logs -n observability deploy/demo-collector | grep -i 'service.name'
应用 pod 上出现名为 opentelemetry-auto-instrumentation 的 init 容器,意味着注入成功。生成一些流量,Collector 的 debug exporter 应当打印出带有你的服务名称的 span。
故障排查
Instrumentation资源在吗?kubectl describe otelinst -n <namespace>。- Operator 有错误吗? 阅读 Operator 命名空间中
manager容器的日志。 - 它是在应用之前创建的吗? 如果不是,请重启 Deployment,使 pod 被重新创建并被注入。检查
kubectl get events -n <namespace>中的 init 容器。 - 注解对吗? 它必须位于
spec.template.metadata.annotations上,并且语言必须与应用匹配。 - 端点对吗? 错误的协议或端口,或跨命名空间使用简短的 Service 名称,会悄无声息地什么也发不出去。
何时优先选择 Operator
当许多团队部署到集群,并且你希望遥测通过注解选择加入、设置由中央掌管时,请使用它。当你只需要一个 Collector,并在每个应用自己的清单中处理 SDK 配置时,请使用普通的 Helm chart。Operator 和 chart 可以共存,但不要用两者同时管理同一个 Collector。
热门指南
-
OpenTelemetry 详解:SDK、OTLP 与 Collector 在编写任何 YAML 之前,先了解各个活动部件以及配置所在的三个位置。 -
Collector 配置模型:组件、管线与 Provider 了解 Collector YAML 的规则:命名、管线、connector、合并文件和环境变量。 -
使用 OTEL_* 环境变量配置 SDK 使用标准变量为任何语言设置服务名称、exporter、采样和限制。 -
无需修改代码即可为应用插桩:Java、Python 和 Node.js 仅通过环境变量和命令行参数附加 OpenTelemetry agent。 -
让 Collector 达到生产就绪:内存限制、批处理与重试 配置 processor、队列和持久化存储,使遥测数据在过载和故障中存活。 -
使用 Helm 在 Kubernetes 上部署 Collector 安装官方 chart,使用 preset 处理日志和指标,并通过 values 文件覆盖配置。 -
排查 Collector 与 SDK 的问题 当遥测数据没有到达时的系统化检查清单:debug exporter、健康检查、内部指标和常见错误。