作者:来自 Elastic Jack Shirazi
OpenTelemetry Java 代理有多种方式将代理安装到 Java 应用程序中。如果你在 Kubernetes pod 中运行 Java 应用程序,则有一个单独的机制(其底层使用 JAVA_TOOL_OPTIONS 和其他环境变量)来自动检测 Java 应用程序。此自动检测可以通过对应用程序和 pod 进行零配置来实现!
在 Kubernetes 中实现 Java 应用程序零配置自动检测的机制是通过 Kubernetes 的 OpenTelemetry Operator。此运算符具有许多功能,完整文档(当然还有源代码)可在项目本身中找到。在这篇博客中,我将介绍如何使用 OpenTelemetry Operator 在 Kubernetes 中安装、设置和运行 Java 应用程序的零配置自动检测。
安装 OpenTelemetry Operator
在撰写本博客时,OpenTelemetry Operator 需要安装认证管理器,然后才能安装该操作员。从 Web 安装非常简单。首先安装 cert-manager(要安装的版本将在 OpenTelemetry Operator for Kubernetes 文档中指定):
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.4/cert-manager.yaml
然后,当证书管理器准备就绪时(kubectl get pods -n cert-manager)...
NAMESPACE NAME READY
cert-manager cert-manager-67c98b89c8-rnr5s 1/1
cert-manager cert-manager-cainjector-5c5695d979-q9hxz 1/1
cert-manager cert-manager-webhook-7f9f8648b9-8gxgs 1/1
... 你可以安装 OpenTelemetry Operator:
kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/latest/download/opentelemetry-operator.yaml
当然,你可以使用特定版本的运算符来代替最新版本。但在这里我使用的是最新版本。
检测资源
现在,你只需添加另一个 Kubernetes 资源即可启用自动检测: Instrumentation resource。我将使用 banana 命名空间作为示例,因此我首先创建了该命名空间 (kubectl create namespace banana)。自动检测由这些检测资源指定和配置。这是一个基本的检测资源,它将允许 banana 命名空间中的每个 Java pod 使用 OpenTelemetry Java 代理 2.5.0 版进行自动仪表:

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: banana-instr
namespace: banana
spec:
exporter:
endpoint: "https://my.endpoint"
propagators:
- tracecontext
- baggage
- b3
sampler:
type: parentbased_traceidratio
argument: "1.0"
java:
image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:2.5.0
env:
- name: OTEL_EXPORTER_OTLP_HEADERS
value: "Authorization=Bearer MyAuth"
创建此资源(例如使用 kubectl apply -f banana-instr.yaml,假设上述 yaml 保存在文件 banana-instr.yaml 中)使 banana-instr Instrumentation 资源可供使用。(请注意,你需要将 my.endpoint 和 MyAuth 更改为适合你的收集器的值。)你可以通过在 banana 命名空间中的任何部署中添加注释来立即使用此检测:
metadata:
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
banana-instr Instrumentation 资源尚未设置为默认应用于 banana 命名空间中的所有 pod。目前,就应用程序而言,它是零配置的,但它需要在 pod 或 deployment 中添加注释。为了使它对 banana 命名空间中的所有 pod 完全零配置,我们需要将该 annotation 添加到命名空间本身,即编辑命名空间(kubectl edit namespace banana),这样它就会具有类似于以下内容的内容
apiVersion: v1
kind: Namespace
metadata:
name: banana
annotations:
instrumentation.opentelemetry.io/inject-java: "banana-instr"
...
现在我们有一个命名空间,它将使用 2.5.0 OpenTelemetry Java 代理自动检测部署在 banana 命名空间中的每个 Java 应用程序!
尝试一下
docker.elastic.co/demos/apm/k8s-webhook-test上有一个简单的 Java 应用程序示例,它只是重复调用链 main->methodA->methodB->methodC->methodD,并在调用中有一些 sleeps。使用非常基本的 pod 定义运行此程序(kubectl apply -f banana-app.yaml):
apiVersion: v1
kind: Pod
metadata:
name: banana-app
namespace: banana
labels:
app: banana-app
spec:
containers:
- image: docker.elastic.co/demos/apm/k8s-webhook-test
imagePullPolicy: Always
name: banana-app
env:
- name: OTEL_INSTRUMENTATION_METHODS_INCLUDE
value: "test.Testing[methodB]"
结果是应用程序自动检测,无需更改配置!生成的应用程序会显示在任何 APM UI 中,例如 Elastic APM:
如你所见,对于此示例,我还将这个环境变量添加到 pod yaml,OTEL_INSTRUMENTATION_METHODS_INCLUDE="test.Testing[methodB]",以便显示来自 methodB 的跟踪。
自动检测背后的技术
要使用自动检测,无需特别了解底层机制,但对于感兴趣的人,这里有一个快速概述。
- Kubernetes 的 OpenTelemetry Operator 安装了一个 mutating webhook,这是一个标准的 Kubernetes 组件。
- 在部署时,Kubernetes 首先将所有定义发送到 mutating webhook。
- 如果 mutating webhook 发现应应用自动检测的条件(即
- 该命名空间有一个 Instrumentation 资源,并且
- 该 Instrumentation 的正确注释以某种方式应用于定义,无论是从定义本身还是从命名空间),
- 然后 mutating webhook “mutates” 定义以包含 Instrumentation 资源定义的环境。
- 环境包括在 env 中定义的显式值,以及一些隐式 OpenTelemetry 值(有关完整详细信息,请参阅 Kubernetes 的 OpenTelemetry Operator 文档)。
- 最重要的是,operator
- 拉取 Instrumentation 资源中定义的映像,
- 从该映像中提取路径 /javaagent.jar 处的文件(使用 shell 命令 cp)
- 将其插入路径 /otel-auto-instrumentation-java/javaagent.jar 处的 pod
- 并添加环境变量 JAVA_TOOL_OPTIONS=-javaagent:/otel-auto-instrumentation-java/javaagent.jar。
- JVM 会在启动时自动获取该 JAVA_TOOL_OPTIONS 环境变量并将其应用于 JVM 命令行。
接下来
此演练可以在任何 Kubernetes 集群中重复进行,以演示和试验自动检测(你需要先创建 banana 命名空间)。在本系列的第二部分中,使用 OpenTelemetry Operator for Kubernetes 的自定义代理,我将展示如何通过 OpenTelemetry 运算符安装任何 Java 代理,并使用 Elastic Java 代理作为示例。