11. Jaeger v2 sobre OpenTelemetry Collector
11. Jaeger v2 sobre OpenTelemetry Collector
En 2024 Jaeger publicó la versión 2 con una reescritura arquitectónica: en lugar de ser un proyecto monolítico independiente, Jaeger v2 se construye sobre OpenTelemetry Collector como base.
Idea central: el código del collector y agente que mantenía Jaeger por años hacía lo mismo que ya hace OTel Collector. Reescribir Jaeger sobre el collector elimina duplicación, alinea el ecosistema y aprovecha el trabajo de toda la comunidad OTel.
Qué se mantiene
- La UI sigue siendo la misma (con mejoras).
- Los conceptos: trace, span, sampling, etc.
- Los storage backends (memory, badger, cassandra, ES, ClickHouse).
- Compatibilidad con SDKs de OpenTelemetry vía OTLP.
Qué cambia
El binario
| Componente | Jaeger v1 | Jaeger v2 |
|---|---|---|
| Collector | Binario propio | OTel Collector con extensiones Jaeger |
| Query | Binario propio | OTel Collector con extensiones Jaeger |
| Agent | Binario propio (deprecado) | Eliminado |
| Ingester | Binario propio | OTel Collector con extensión Kafka |
| All-in-one | Single binario | Single binario OTel Collector |
Hay un único binario jaeger en v2. Su comportamiento (collector, query, all-in-one) se decide vía configuración YAML.
La configuración
Jaeger v1 usaba flags de CLI y variables de entorno. Jaeger v2 usa YAML estilo OTel Collector:
service:
extensions: [jaeger_storage, jaeger_query]
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [jaeger_storage_exporter]
extensions:
jaeger_storage:
backends:
some_storage:
memory:
max_traces: 100000
jaeger_query:
storage:
traces: some_storage
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
exporters:
jaeger_storage_exporter:
trace_storage: some_storage
Si ya conocés la configuración de OTel Collector, esto te resulta familiar. Si venís de Jaeger v1, hay un período de adaptación.
Empezar con Jaeger v2
Imagen Docker
docker run -d --name jaeger-v2 \
-p 16686:16686 \
-p 4317:4317 \
-p 4318:4318 \
-v $PWD/jaeger-config.yaml:/etc/jaeger/config.yaml \
jaegertracing/jaeger:2.0.0 \
--config=/etc/jaeger/config.yaml
jaeger-config.yaml con storage en memoria:
service:
extensions: [jaeger_storage, jaeger_query]
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [jaeger_storage_exporter]
extensions:
jaeger_storage:
backends:
memory_store:
memory:
max_traces: 100000
jaeger_query:
storage:
traces: memory_store
receivers:
otlp:
protocols:
grpc:
http:
processors:
batch:
timeout: 1s
exporters:
jaeger_storage_exporter:
trace_storage: memory_store
UI sigue en http://localhost:16686/.
Storage en v2
Cada backend se declara en la extensión jaeger_storage:
extensions:
jaeger_storage:
backends:
es_main:
elasticsearch:
servers: ["http://elasticsearch:9200"]
index_prefix: "jaeger"
memory_archive:
memory:
max_traces: 50000
jaeger_query:
storage:
traces: es_main
traces_archive: memory_archive # opcional
Notá:
- Podés tener múltiples backends nombrados en la misma instancia.
- Hay un concepto de archive storage para retener trazas marcadas explícitamente más tiempo.
Pipelines: el verdadero superpoder
Como ahora Jaeger es un OTel Collector, podés meter cualquier processor en el pipeline:
Tail sampling integrado
processors:
tail_sampling:
decision_wait: 30s
policies:
- { name: errors, type: status_code, status_code: { status_codes: [ERROR] } }
- { name: slow, type: latency, latency: { threshold_ms: 1000 } }
- { name: prob, type: probabilistic, probabilistic: { sampling_percentage: 1 } }
service:
pipelines:
traces:
receivers: [otlp]
processors: [tail_sampling, batch]
exporters: [jaeger_storage_exporter]
En v1 necesitabas un OTel Collector externo para esto. En v2 viene incluido.
Atributos: redacción de info sensible
processors:
attributes:
actions:
- key: http.url
action: update
from_attribute: http.url
pattern: 'token=[^&]+'
replacement: 'token=REDACTED'
- key: user.email
action: hash
Filter: descartar lo que no querés guardar
processors:
filter:
error_mode: ignore
traces:
span:
- 'attributes["http.route"] == "/health"'
- 'attributes["http.route"] == "/metrics"'
Adiós a las trazas de health checks llenando tu storage.
Dual-write a múltiples backends
exporters:
jaeger_storage_exporter/main:
trace_storage: cassandra_main
otlp/tempo:
endpoint: tempo:4317
service:
pipelines:
traces:
receivers: [otlp]
exporters: [jaeger_storage_exporter/main, otlp/tempo]
Migración a otro backend sin downtime: escribís a los dos por un período, validás, cortás el viejo.
Breaking changes vs v1
Compatibilidad con SDKs
OK: SDKs de OpenTelemetry exportando vía OTLP siguen funcionando sin cambios.
No OK: clientes Jaeger deprecados (Thrift sobre UDP/HTTP) requieren receptor especial:
receivers:
jaeger:
protocols:
grpc:
endpoint: 0.0.0.0:14250
thrift_http:
endpoint: 0.0.0.0:14268
Configuración
YAML reemplaza CLI flags y env vars. Migración no es 1:1, hay que reescribir el setup.
Agent eliminado
Si tenías sidecar agents, hay que migrar las apps a OTLP directo o usar el OTel Collector como sidecar.
Cuándo migrar
Migrá ya si
- Estás empezando un proyecto nuevo. Empezá directo en v2.
- Querés pipelines con tail sampling, filtering, redacción.
- Operás OTel Collector ya y unificar tiene valor.
- Querés ClickHouse como backend (soportado oficialmente solo en v2).
Esperá si
- v1 está estable, en producción, sin necesidades nuevas.
- Cassandra existente con scripts de mantenimiento custom — verificá que el driver de v2 los respete.
- Tu equipo no tiene capacity para reescribir configs ahora.
Jaeger v1 sigue mantenido. No hay urgencia operacional de migrar inmediatamente, pero el desarrollo activo se está moviendo a v2.
Migración paso a paso
flowchart TD
P1[1. Levantar Jaeger v2 en paralelo\ncon mismo storage que v1] --> P2[2. Apuntar 5-10% del tráfico a v2\ncon dual-pipeline o LB]
P2 --> P3[3. Validar UI y queries equivalentes]
P3 --> P4[4. Migrar gradualmente al 100%]
P4 --> P5[5. Apagar v1]
Detalles operativos:
- Schema compartido: para storage como ES o Cassandra, el schema es compatible. Mismo cluster, mismos índices.
- Ports: hacé que v2 escuche en el mismo puerto que v1 cuando cambies, para que apps no necesiten reconfig.
- Smoke tests: antes de cortar v1, verificá búsquedas, lookups por trace_id, dependency graph y monitor.
Beneficios concretos que ya disfrutamos
- Una sola configuración en lugar de “configuración Jaeger” + “configuración OTel Collector si lo tenés”.
- Pipelines flexibles integrados: filter, transform, tail_sampling sin servicios extra.
- Mejor catálogo de extensiones: lo que añade la comunidad OTel a Collector, lo aprovechás en Jaeger.
- ClickHouse oficial.
¿Qué viene?
Cubrimos la teoría y la migración. En el próximo capítulo bajamos al deployment de producción real: Kubernetes, Operator, Helm, alta disponibilidad y observabilidad del propio Jaeger.