OpenTelemetry Operator Instrumentation編
こんにちは、@sugar235711です。
この記事は「ひとりで気になるOSSのソースコード全部読んで何かする Advent Calendar 2025」24日目の記事です。
前回の記事: OpenTelemetry Operator CRD編
Instrumentation は、アプリケーションへの OpenTelemetry自動計装を設定するためのカスタムリソースです。アプリケーションコードを変更することなく、Webhook経由でPodにSDK/Agentを注入し、テレメトリデータを自動収集します。
code:yaml
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: my-instrumentation
spec:
exporter:
endpoint: http://otel-collector:4317
propagators:
- tracecontext
- baggage
sampler:
type: parentbased_traceidratio
argument: "0.25"
アーキテクチャ
code:_
┌─────────────────────────────────────────────────────────────────────────────┐
│ Instrumentation CRD Flow │
└─────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────┐ ┌──────────────────────┐
│ Instrumentation CR │ │ Namespace/Pod │
│ (設定の定義) │ │ (アノテーション) │
└──────────┬───────────┘ └──────────┬───────────┘
│ │
│ │ inject-java: "true"
│ │ inject-python: "my-inst"
│ ▼
│ ┌─────────────────────────────────────┐
└─────────────▶│ Mutating Webhook (/mutate-v1-pod) │
│ internal/webhook/podmutation/ │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────┐
│ instPodMutator.Mutate() │
│ internal/instrumentation/│
└──────────────┬──────────────┘
│
┌─────────────────────────────┼─────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Java │ │ Node.js │ │ Python │
│ InitContainer│ │ InitContainer│ │ InitContainer│
│ + EnvVars │ │ + EnvVars │ │ + EnvVars │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
└─────────────────────────────┼─────────────────────────────┘
▼
┌─────────────────────────────────┐
│ Modified Pod │
│ - InitContainers追加 │
│ - Volumes追加 │
│ - VolumeMounts追加 │
│ - Environment Variables追加 │
└─────────────────────────────────┘
Spec構造
code:go
type InstrumentationSpec struct {
// OTLPエクスポーター設定
Exporter Exporter json:"exporter,omitempty"
// リソース属性
Resource Resource json:"resource,omitempty"
// コンテキスト伝播設定
Propagators []Propagator json:"propagators,omitempty"
// サンプリング設定
Sampler Sampler json:"sampler,omitempty"
// デフォルト動作設定
Defaults Defaults json:"defaults,omitempty"
// 共通環境変数
Env []corev1.EnvVar json:"env,omitempty"
// 言語別設定
Java Java json:"java,omitempty"
NodeJS NodeJS json:"nodejs,omitempty"
Python Python json:"python,omitempty"
DotNet DotNet json:"dotnet,omitempty"
Go Go json:"go,omitempty"
ApacheHttpd ApacheHttpd json:"apacheHttpd,omitempty"
Nginx Nginx json:"nginx,omitempty"
// イメージプルポリシー
ImagePullPolicy corev1.PullPolicy json:"imagePullPolicy,omitempty"
}
サポート言語・ランタイム
table:_
言語/ランタイム 計装方式 主な環境変数 InitContainer
Java javaagent JAR JAVA_TOOL_OPTIONS ✅
Node.js SDK注入 NODE_OPTIONS ✅
Python SDK注入 PYTHONPATH ✅
.NET Profiler CORECLR_ENABLE_PROFILING ✅
Go eBPF Sidecar OTEL_GO_AUTO_TARGET_EXE ❌ (Sidecar)
Apache HTTPD Module注入 設定ファイル ✅
Nginx Module注入 設定ファイル ✅
SDK Only 環境変数のみ OTEL_* ❌
アノテーション一覧
注入制御
table:_
アノテーション 値 説明
instrumentation.opentelemetry.io/inject-java true/false/name/ns/name Java計装
instrumentation.opentelemetry.io/inject-nodejs 同上 Node.js計装
instrumentation.opentelemetry.io/inject-python 同上 Python計装
instrumentation.opentelemetry.io/inject-dotnet 同上 .NET計装
instrumentation.opentelemetry.io/inject-go 同上 Go計装
instrumentation.opentelemetry.io/inject-apache-httpd 同上 Apache HTTPD計装
instrumentation.opentelemetry.io/inject-nginx 同上 Nginx計装
instrumentation.opentelemetry.io/inject-sdk 同上 SDK環境変数のみ
値の解釈:
"true": 同一Namespace内の唯一のInstrumentationを使用
"false": 計装しない
"name": 同一Namespace内の指定名Instrumentationを使用
"ns/name": 別Namespaceのインストルメンテーションを使用
コンテナ指定
table:_
アノテーション 説明
instrumentation.opentelemetry.io/container-names 全言語共通のコンテナ指定(カンマ区切り)
instrumentation.opentelemetry.io/java-container-names Java専用コンテナ指定
instrumentation.opentelemetry.io/nodejs-container-names Node.js専用コンテナ指定
instrumentation.opentelemetry.io/python-container-names Python専用コンテナ指定
instrumentation.opentelemetry.io/dotnet-container-names .NET専用コンテナ指定
instrumentation.opentelemetry.io/go-container-names Go専用コンテナ指定
instrumentation.opentelemetry.io/apache-httpd-container-names Apache HTTPD専用
instrumentation.opentelemetry.io/inject-nginx-container-names Nginx専用
instrumentation.opentelemetry.io/sdk-container-names SDK Only専用
追加設定
table:_
アノテーション 説明
instrumentation.opentelemetry.io/otel-go-auto-target-exe Go: ターゲット実行ファイルパス
instrumentation.opentelemetry.io/otel-dotnet-auto-runtime .NET: ランタイム指定
instrumentation.opentelemetry.io/otel-python-platform Python: プラットフォーム指定
言語別詳細設定
共通構造
code:go
type Java struct {
Image string json:"image,omitempty"
VolumeClaimTemplate PersistentVolumeClaimTemplate json:"volumeClaimTemplate,omitempty"
VolumeSizeLimit *resource.Quantity json:"volumeLimitSize,omitempty" // Deprecated
Env []corev1.EnvVar json:"env,omitempty"
Resources corev1.ResourceRequirements json:"resources,omitempty"
}
言語別固有フィールド
table:_
言語 固有フィールド
Java Extensions (追加JAR)
Apache HTTPD Version, ConfigPath, Attrs
Nginx ConfigFile, Attrs
計装方式詳細
InitContainer方式 (Java/Node.js/Python/.NET/Apache/Nginx)
code:_
┌──────────────────────────────────────────────────────────────────┐
│ Pod起動時 │
│ │
│ 1. InitContainer実行 │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ cp /javaagent.jar /otel-auto-instrumentation-java/ │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 2. Volume経由でSDK/Agent共有 │
│ ┌─────────────────┐ │
│ │ emptyDir: │ │
│ │ /otel-auto-... │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ 3. App Container起動 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ JAVA_TOOL_OPTIONS="-javaagent:/otel.../javaagent.jar" │ │
│ │ OTEL_SERVICE_NAME=myapp │ │
│ │ OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317 │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
Sidecar方式 (Go)
code:_
┌──────────────────────────────────────────────────────────────────┐
│ Pod (ShareProcessNamespace: true) │
│ │
│ ┌─────────────────────┐ ┌─────────────────────────────────┐ │
│ │ App Container │ │ Go Agent Sidecar │ │
│ │ │ │ │ │
│ │ /app/main ◄────────┼────│ eBPFでプロセスをフック │ │
│ │ │ │ │ │
│ │ │ │ privileged: true │ │
│ │ │ │ /sys/kernel/debug (HostPath) │ │
│ └─────────────────────┘ └─────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
注入される環境変数
共通 (injectCommonSDKConfig)
table:_
環境変数 説明 ソース
OTEL_SERVICE_NAME サービス名 K8sラベル or Deployment名
OTEL_EXPORTER_OTLP_ENDPOINT OTLPエンドポイント spec.exporter.endpoint
OTEL_RESOURCE_ATTRIBUTES リソース属性 K8sメタデータ + spec.resource
OTEL_PROPAGATORS コンテキスト伝播 spec.propagators
OTEL_TRACES_SAMPLER サンプラータイプ spec.sampler.type
OTEL_TRACES_SAMPLER_ARG サンプラー引数 spec.sampler.argument
OTEL_POD_IP Pod IP Downward API
OTEL_NODE_IP Node IP Downward API
OTEL_RESOURCE_ATTRIBUTES_POD_NAME Pod名 Downward API
OTEL_RESOURCE_ATTRIBUTES_NODE_NAME Node名 Downward API
言語別
table:_
言語 主要環境変数
Java JAVA_TOOL_OPTIONS="-javaagent:..."
Node.js NODE_OPTIONS="--require /otel.../autoinstrumentation.js"
Python PYTHONPATH="/otel...", OTEL_PYTHON_DISTRO, OTEL_PYTHON_CONFIGURATOR
.NET CORECLR_ENABLE_PROFILING=1, CORECLR_PROFILER_PATH, etc.
Go OTEL_GO_AUTO_TARGET_EXE="/app/main"
環境変数の優先順位
code:_
1. original container env vars ← 最優先(ユーザー定義)
2. language specific env vars ← 言語別設定 (spec.java.env など)
3. common env vars ← 共通設定 (spec.env)
4. instrument spec configs ← Spec由来の自動設定
リソース属性の自動設定
table:_
属性キー ソース
service.name app.kubernetes.io/name ラベル or Deployment名
service.version app.kubernetes.io/version ラベル or イメージタグ
service.namespace K8s Namespace名
service.instance.id {namespace}.{pod}.{container}
k8s.namespace.name Namespace
k8s.pod.name Pod名 (Downward API)
k8s.pod.uid Pod UID (オプション)
k8s.node.name Node名 (Downward API)
k8s.deployment.name OwnerReferenceから取得
k8s.replicaset.name OwnerReferenceから取得
k8s.statefulset.name OwnerReferenceから取得
k8s.daemonset.name OwnerReferenceから取得
k8s.job.name OwnerReferenceから取得
k8s.cronjob.name OwnerReferenceから取得
サンプラータイプ
code:go
const (
AlwaysOn SamplerType = "always_on"
AlwaysOff SamplerType = "always_off"
TraceIDRatio SamplerType = "traceidratio"
ParentBasedAlwaysOn SamplerType = "parentbased_always_on"
ParentBasedAlwaysOff SamplerType = "parentbased_always_off"
ParentBasedTraceIDRatio SamplerType = "parentbased_traceidratio"
JaegerRemote SamplerType = "jaeger_remote"
ParentBasedJaegerRemote SamplerType = "parentbased_jaeger_remote"
XRaySampler SamplerType = "xray"
)
Propagator (コンテキスト伝播)
code:go
const (
TraceContext Propagator = "tracecontext" // W3C Trace Context
Baggage Propagator = "baggage" // W3C Baggage
B3 Propagator = "b3" // Zipkin B3 single-header
B3Multi Propagator = "b3multi" // Zipkin B3 multi-header
Jaeger Propagator = "jaeger" // Jaeger
XRay Propagator = "xray" // AWS X-Ray
OTTrace Propagator = "ottrace" // OT Trace
None Propagator = "none" // 伝播なし
)
Webhookの動作
Mutating Webhook
code:go
// +kubebuilder:webhook:path=/mutate-v1-pod,mutating=true,failurePolicy=ignore
func (p *podMutationWebhook) Handle(ctx context.Context, req admission.Request) admission.Response {
// 1. Podデコード
pod := corev1.Pod{}
p.decoder.Decode(req, &pod)
// 2. Namespace取得
ns := corev1.Namespace{}
p.client.Get(ctx, types.NamespacedName{Name: req.Namespace}, &ns)
// 3. 各Mutatorを実行
for _, m := range p.podMutators {
pod, err = m.Mutate(ctx, ns, pod)
}
// 4. パッチ生成
return admission.PatchResponseFromRaw(req.Object.Raw, marshaledPod)
}
Instrumentation Webhook (デフォルト値設定)
code:go
func (w InstrumentationWebhook) Default(ctx context.Context, obj runtime.Object) error {
// 各言語のデフォルトイメージ設定
if r.Spec.Java.Image == "" {
r.Spec.Java.Image = w.cfg.AutoInstrumentationJavaImage
}
// リソース制限のデフォルト設定
if r.Spec.Java.Resources.Limits == nil {
r.Spec.Java.Resources.Limits = corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("500m"),
corev1.ResourceMemory: resource.MustParse("256Mi"),
}
}
// ...
}
使用例
基本的な使用
code:yaml
# 1. Instrumentation CR作成
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: my-instrumentation
namespace: default
spec:
exporter:
endpoint: http://otel-collector.observability:4317
propagators:
- tracecontext
- baggage
sampler:
type: parentbased_traceidratio
argument: "0.25"
---
# 2. Deploymentにアノテーション追加
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
metadata:
annotations:
instrumentation.opentelemetry.io/inject-java: "true"
spec:
containers:
- name: myapp
image: myapp:latest
複数言語の計装 (Multi-Instrumentation)
code:yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: polyglot-app
spec:
template:
metadata:
annotations:
# 各コンテナに別々の言語を計装
instrumentation.opentelemetry.io/inject-java: "true"
instrumentation.opentelemetry.io/java-container-names: "backend"
instrumentation.opentelemetry.io/inject-nodejs: "true"
instrumentation.opentelemetry.io/nodejs-container-names: "frontend"
spec:
containers:
- name: backend
image: backend-java:latest
- name: frontend
image: frontend-nodejs:latest
TLS設定
code:yaml
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: secure-instrumentation
spec:
exporter:
endpoint: https://otel-collector.observability:4317
tls:
secretName: otel-client-certs
ca_file: ca.crt
cert_file: tls.crt
key_file: tls.key
言語別比較表
table:_
項目 Java Node.js Python .NET Go
注入方式 InitContainer InitContainer InitContainer InitContainer Sidecar
技術 javaagent require hook sitecustomize CLR Profiler eBPF
権限 通常 通常 通常 通常 特権
複数コンテナ ✅ ✅ ✅ ✅ ❌
ShareProcessNS 不要 不要 不要 不要 必須
主要EnvVar JAVA_TOOL_OPTIONS NODE_OPTIONS PYTHONPATH CORECLR_* OTEL_GO_AUTO_TARGET_EXE
ディレクトリ構造
code:_
internal/instrumentation/
├── podmutator.go # Pod Mutator(Webhookから呼ばれる)
├── sdk.go # SDK注入ロジック・共通設定
├── annotation.go # アノテーション解析
├── exporter.go # Exporter設定(TLS含む)
├── helper.go # ユーティリティ関数
├── javaagent.go # Java固有ロジック
├── nodejs.go # Node.js固有ロジック
├── python.go # Python固有ロジック
├── dotnet.go # .NET固有ロジック
├── golang.go # Go固有ロジック(eBPF/Sidecar)
├── apachehttpd.go # Apache HTTPD固有ロジック
├── nginx.go # Nginx固有ロジック
└── upgrade/ # Instrumentationアップグレード
└── upgrade.go
Feature Gates
Instrumentation関連のフィーチャーゲート:
table:_
フラグ 説明
--enable-java-auto-instrumentation Java計装の有効化
--enable-nodejs-auto-instrumentation Node.js計装の有効化
--enable-python-auto-instrumentation Python計装の有効化
--enable-dotnet-auto-instrumentation .NET計装の有効化
--enable-go-auto-instrumentation Go計装の有効化
--enable-apache-httpd-auto-instrumentation Apache HTTPD計装の有効化
--enable-nginx-auto-instrumentation Nginx計装の有効化
--enable-multi-instrumentation 複数言語計装の有効化
まとめ
明日はOpAMPBridgeを見ます。