从 Alauda Container Platform Tracing 迁移

本文档介绍如何将基于旧版 Alauda Container Platform (ACP) Tracing 栈的现有 tracing 部署迁移到 Alauda Distributed Tracing:从 Alauda Build of Jaeger(Jaeger 1.60.0)加 Alauda Build of OpenTelemetry,迁移到基于 Jaeger v2(2.16.0)加 Alauda Build of OpenTelemetry v2 的方案。

迁移分两个阶段进行:

  1. OpenTelemetry 栈迁移。 将旧版 Alauda Build of OpenTelemetry Operator 和 Collector 替换为 Alauda Build of OpenTelemetry v2。对应用 Pod 进行滚动发布,以注入 v2 Java agent。完成此阶段后,telemetry 由 v2 Collector 收集,但仍写入旧版 Jaeger 后端。此阶段请参照 从 Alauda Build of OpenTelemetry 迁移到 Alauda Build of OpenTelemetry v2

  2. Jaeger 后端迁移。 在旧版 Jaeger 旁边部署一个新的 Jaeger v2 实例,将 v2 Collector 的 trace exporter 切换到新的后端,并在旧版保留期结束后卸载旧版 Jaeger。

切换完成后,新 trace 数据会流入新的 Jaeger v2 后端,而旧版 Jaeger 继续提供已存储的历史 trace。等旧版保留期到期后(默认 7 天),再卸载旧版栈。

概览

ACP Tracing 与 Alauda Distributed Tracing 的变化

项目Alauda Container Platform Tracing(旧版)Alauda Distributed Tracing(目标)
Jaeger 版本1.60.02.16.0
Jaeger OperatorAlauda Build of Jaeger Operator(CRD:jaegertracing.io/v1.JaegerAlauda Build of OpenTelemetry v2 Operator(Jaeger v2 作为 opentelemetry.io/v1beta1.OpenTelemetryCollector 部署)
默认 Elasticsearch 索引前缀acp-tracing-<cluster>(按天生成带日期标记的索引)acp-<cluster>(rollover 写/读别名)
Elasticsearch 保留策略jaeger-es-index-cleaner CronJob 删除早于 numberOfDays 的日索引(默认 7索引生命周期管理(ILM)策略 jaeger-ilm-policy 自动滚动并删除索引(默认 7d 后删除)
Tracing UI 入口点平台定制的 Observability → Tracing 视图,由 acp-tracing-ui 功能开关控制通过带有 OAuth2 Proxy sidecar 的 Ingress 暴露原生 Jaeger UI

有关 OpenTelemetry Operator、Collector 和 Instrumentation 资源的变化(包括现在必需的 spec.java.image 字段、Service Mesh v1 不兼容性,以及 Collector 配置 schema 迁移),请参阅 OpenTelemetry v2 迁移指南中的 v1 和 v2 之间的变化

NOTE

旧版 Alauda Build of Jaeger Operator 管理着一个独立的 CRD(jaegertracing.io/v1.Jaeger),并且不会与 v2 OpenTelemetry Operator 冲突。因此,在迁移期间会保持其运行,以便旧版 Jaeger 继续提供历史 trace 数据。

迁移中断窗口

trace ingestion 会在两个位置中断:

  1. 在 OpenTelemetry v1 → v2 迁移期间,从旧版 OpenTelemetryCollector 被删除到 v2 OpenTelemetryCollector 变为 ready 之间。请参阅 OpenTelemetry v2 迁移指南中的 迁移中断窗口

  2. 在 Jaeger 切换期间,当 v2 Collector 被打补丁,将 trace exporter 从旧版 Jaeger 重定向到新的 Jaeger v2 后端时。Collector 会进行滚动,因此在滚动过程中可能出现短暂的 ingestion 间隙。

在这两个窗口期间,应用 Pod 会继续正常运行,但在间隙期间生成的 telemetry 可能会被临时缓冲;如果无法及时导出,则可能会被丢弃。请在低流量窗口执行每个阶段,并提前通知 telemetry 消费方(开发人员、SRE、Kiali 用户)。

在整个迁移过程中,旧版 Jaeger query 路径始终可用,因此在新流水线启动期间,之前存储的 trace 仍可在旧版 Jaeger UI 中检索。

迁移流程概览

[Stage 1] Migrate Alauda Build of OpenTelemetry to v2 (per external guide)
              ↓ v2 Collector keeps writing traces to the legacy Jaeger
[Step 1]  Deploy the new Jaeger v2 instance (jaeger-system)
[Step 2]  Switch the v2 OpenTelemetry Collector to write to the new Jaeger
              ↓ trace ingestion cutover; new traces go to the new Jaeger
[Step 3]  Verify the migration

[Observation] ≤ 7 days — legacy Jaeger remains queryable for historical traces

[Step 4]  Uninstall the legacy Jaeger instance and Operator
[Step 5]  Disable the legacy feature switch and clean up legacy ES indices

trace 数据连续性策略

在 OpenTelemetry v2 迁移期间,按照 重新创建 OpenTelemetryCollector 资源 的指导,v2 OpenTelemetry Collector 会部署在与旧版 Collector 相同的 namespace 中,并使用相同的 Service 名称(cpaas-system 中的 otel-collector)。向 otel-collector.cpaas-system 导出 OTLP 的应用无需更改任何配置即可继续工作。

在 Jaeger 切换之后,trace 数据会按时间清晰分区:

  • 切换前摄入的 traces 仍只保留在旧版 Jaeger 中。只要旧版 jaeger-es-index-cleaner 仍在保留它们,就可以通过旧版 Jaeger UI <platform-url>/clusters/<cluster>/acp/jaeger 进行查询——默认情况下为索引创建日期起 7 天。
  • 切换后摄入的 traces 只会写入新的 Jaeger v2 后端。它们可以通过新的 Jaeger UI <platform-url>/clusters/<cluster>/jaeger 进行查询。

在观察期内,旧版 Jaeger 实例及其 Operator 会刻意 保持运行,以便用户仍可通过旧版 UI 查询最近的历史 trace。等旧版保留数据完全过期后(≥ 7 天),即可在 清理 中卸载旧版栈。

NOTE

请提前向用户说明这一分界:新的 Jaeger UI 不包含切换前的 traces。 在观察期内,如果用户查找的是切换前开始的 trace,应改用旧版 Jaeger UI。

TIP

有些团队更倾向于在观察期内将每个 span 同时双写到新旧两个 Jaeger 中,这样切换后的 traces 会同时出现在 两个 UI 里。这对于并行验证、跨团队逐步切换 UI,或更快的原地回滚路径都很有帮助。这样会使观察期内的 Elasticsearch 写入负载和存储量大约增加一倍,并带来额外的清理步骤。请参阅 (可选) 启用向旧版 Jaeger 的双重导出

双重导出不会将切换前的 traces 回填到新 Jaeger 中;切换前的 traces 仍然只能通过旧版 Jaeger UI 查询。

前提条件

  • 由拥有 cluster-admin 角色的集群管理员建立的有效 ACP CLI (kubectl) 会话。
  • 当前已安装旧版 ACP Tracing 栈(Alauda Build of Jaeger Operator 与一个 Jaeger 实例,以及 Alauda Build of OpenTelemetry 与一个 OpenTelemetryCollector 和一个或多个 Instrumentation 资源)。
  • 集群可访问 Elasticsearch 8.x,并且你拥有有权限创建 ILM 策略、index template 和 index alias 的 Elasticsearch 用户。
  • 执行迁移命令的工作站上已安装 jqenvsubst 命令行工具。
  • 已通知 telemetry 消费方(开发人员、Kiali 用户、SRE 仪表板)和应用所有者计划中的中断窗口。

迁移前任务

将 Alauda Build of OpenTelemetry 迁移到 v2

在迁移 Jaeger 后端之前,请先按照 从 Alauda Build of OpenTelemetry 迁移到 Alauda Build of OpenTelemetry v2 完成从 Alauda Build of OpenTelemetryAlauda Build of OpenTelemetry v2 的迁移。该指南涵盖以下内容:

  • 备份并卸载旧版 Alauda Build of OpenTelemetry Operator 及其 OpenTelemetryCollectorInstrumentation 资源。
  • 安装 v2 Operator。
  • 准备 Java auto-instrumentation image,并重新创建 OpenTelemetryCollectorInstrumentation 资源,包括设置现在必需的 spec.java.image 字段。
  • 对应用 Pod 进行滚动发布,以注入新的 Java agent。

在此阶段结束时:

  • v2 Alauda Build of OpenTelemetry Operator 已安装,旧版 Operator 已卸载。
  • cpaas-system 中的 v2 OpenTelemetryCollector 正在运行,并且其 trace exporter 仍指向旧版 Jaeger(这是从 v1 备份重新创建 Collector 的自然结果)。
  • 所有 Instrumentation 资源都已设置 spec.java.image,并且应用 Pod 已使用 v2 Java agent 完成滚动发布。

在本指南的 将 v2 OpenTelemetry Collector 切换到新的 Jaeger 之前,trace ingestion 会继续流入旧版 Jaeger。

清点旧版 Jaeger 部署

记录旧版 Jaeger 的当前状态,以便了解迁移范围并生成回滚所需的备份。

  1. 列出旧版 Alauda Build of Jaeger Operator 和 Jaeger 实例:

    kubectl get csv -A | grep -i jaeger
    kubectl get jaeger -A
  2. 记录旧版 Jaeger 资源中引用的旧版 Elasticsearch endpoint、凭据以及索引前缀。它们也会在新的 Jaeger v2 实例中复用。

备份旧版 Jaeger 资源

导出旧版 Jaeger 资源,以便后续重建它们(以及在需要时回滚):

mkdir -p ./acp-tracing-backup

# Jaeger CR (covers the jaeger-prod instance in cpaas-system).
kubectl get jaeger -A -o yaml \
  > ./acp-tracing-backup/jaegers.yaml

# Alauda Build of Jaeger Operator Subscription and CSV.
kubectl get subscription -n jaeger-operator jaeger-operator -o yaml \
  > ./acp-tracing-backup/jaeger-v1-subscription.yaml || true
kubectl -n jaeger-operator get csv -o yaml \
  > ./acp-tracing-backup/jaeger-v1-csv.yaml || true

# Supporting resources for jaeger-prod in cpaas-system. Each is removed in
# Cleanup, so back them up here so rollback can restore them. Skip silently
# (|| true) if a resource is not present in this environment.
kubectl -n cpaas-system get ingress     jaeger-prod-query         -o yaml \
  > ./acp-tracing-backup/jaeger-prod-ingress.yaml             || true
kubectl -n cpaas-system get podmonitor  jaeger-prod-monitor       -o yaml \
  > ./acp-tracing-backup/jaeger-prod-podmonitor.yaml          || true
kubectl -n cpaas-system get rolebinding jaeger-prod-rb            -o yaml \
  > ./acp-tracing-backup/jaeger-prod-rolebinding.yaml         || true
kubectl -n cpaas-system get role        jaeger-prod-role          -o yaml \
  > ./acp-tracing-backup/jaeger-prod-role.yaml                || true
kubectl -n cpaas-system get sa          jaeger-prod-sa            -o yaml \
  > ./acp-tracing-backup/jaeger-prod-sa.yaml                  || true
kubectl -n cpaas-system get secret      jaeger-prod-oauth2-proxy  -o yaml \
  > ./acp-tracing-backup/jaeger-prod-oauth2-proxy-secret.yaml || true
kubectl -n cpaas-system get secret      jaeger-prod-es-basic-auth -o yaml \
  > ./acp-tracing-backup/jaeger-prod-es-basic-auth-secret.yaml || true
kubectl -n cpaas-system get configmap   jaeger-prod-oauth2-proxy  -o yaml \
  > ./acp-tracing-backup/jaeger-prod-oauth2-proxy-configmap.yaml || true
NOTE

这些备份文件仅用于配置参考和回滚工件。使用 v2 重建 Jaeger 时,请遵循 安装 Alauda Distributed Tracing 中描述的 v2 约定。

验证 Elasticsearch 容量

新的 Jaeger 会写入一个独立的索引族(acp-<cluster>-jaeger-*),而旧版索引(acp-tracing-<cluster>-jaeger-*)会在旧版保留期内逐步过期。请在 Elasticsearch 中预留至少额外一个完整保留周期所需的 trace 存储空间。如果你选择 (可选) 启用向旧版 Jaeger 的双重导出,则在观察期内应预留大约两倍的稳态存储空间。

迁移操作步骤

部署新的 Jaeger v2 实例

按照 Alauda Distributed Tracing 安装指南中的 部署 Alauda Build of Jaeger v2 进行操作。新的 Jaeger v2 实例会部署在一个专用 namespace 中(默认 jaeger-system),以避免与 cpaas-system 中旧版的 jaeger-prod 实例冲突。

WARNING

只需执行上面链接中的 部署 Alauda Build of Jaeger v2 部分。不要执行同一安装指南中的 部署 OpenTelemetry Collector 部分——面向应用的 v2 OpenTelemetry Collector 已在 阶段 1(OpenTelemetry v2 迁移) 中部署到了 cpaas-system。执行该部分会在 jaeger-system 中创建一个没有任何应用使用的重复 otel Collector。

当你进入变量设置步骤时,请保留 默认索引前缀,以便新的 Jaeger 写入到与旧版索引清晰分离的索引中:

export JAEGER_NS="jaeger-system"
export JAEGER_INSTANCE_NAME="jaeger"
export JAEGER_ES_INDEX_PREFIX="acp-${CLUSTER_NAME}"      # different from the legacy "acp-tracing-${CLUSTER_NAME}"
export JAEGER_BASEPATH="/clusters/${CLUSTER_NAME}/jaeger"  # different from the legacy "/clusters/${CLUSTER_NAME}/acp/jaeger"

完成安装步骤后,请验证以下内容:

  • jaeger-system 中的 Jaeger Pod 处于 Ready 状态。
  • Jaeger UI 可通过 <platform-url>/clusters/<cluster>/jaeger 访问。此时它应为空,因为还没有 exporter 向其写入数据。
  • Service jaeger-collector.jaeger-system.svc.cluster.local 在端口 4317 上接受 OTLP gRPC——这就是下一步中 v2 OpenTelemetry Collector 将导出的 endpoint。

将 v2 OpenTelemetry Collector 切换到新的 Jaeger

OpenTelemetry v1 → v2 迁移 之后,cpaas-system 中重新创建的 otel OpenTelemetryCollector 仍然会把 traces 写入旧版 Jaeger,因为其 trace exporter 是从 v1 备份继承而来的。其 spec.config 中与 trace 相关的部分通常如下所示(其他字段与此步骤无关,已省略):

otel collector — post-OpenTelemetry-migration state
spec:
  config:
    exporters:
      debug: {}
      otlp:
        balancer_name: round_robin
        endpoint: dns:///jaeger-prod-collector-headless.cpaas-system:4317
        tls:
          insecure: true
    service:
      pipelines:
        traces:
          receivers:  [otlp]
          processors: [memory_limiter, batch]
          exporters:  [debug, otlp] 
  1. 继承自 v1 备份的旧版 Jaeger exporter 名称为 otlp,目标指向 cpaas-system 中旧版 Jaeger collector 的 headless Service。balancer_name: round_robin 会将 spans 分发到该 headless Service 的各个 endpoint。
  2. trace pipeline 会将 spans 发送到 debug(日志)和 otlp(旧版 Jaeger)。

对 Collector 打补丁,以便:(1) 添加一个新的 otlp/jaeger-v2 exporter,指向 jaeger-system 中新的 Jaeger v2 collector Service;(2) 通过将旧版 otlp exporter 设为 null 来移除它;(3) 将 trace pipeline 的 exporter 列表替换为 [debug, otlp/jaeger-v2]

kubectl -n cpaas-system patch opentelemetrycollector otel --type=merge -p '
spec:
  config:
    exporters:
      otlp/jaeger-v2:
        endpoint: jaeger-collector.jaeger-system.svc.cluster.local:4317
        tls:
          insecure: true
      otlp: null
    service:
      pipelines:
        traces:
          exporters: [debug, otlp/jaeger-v2]
'
kubectl rollout status deployment/otel-collector -n cpaas-system --timeout=180s
WARNING

service.pipelines.traces.exporters 是一个数组,而 merge patch 会整体替换数组,而不是追加。上面的 patch 列出了 trace pipeline 中必须保留的所有 exporter(debugotlp/jaeger-v2)。如果你的 trace pipeline 还包含其他自定义 exporter,请在应用补丁之前将它们加入此列表。

如果你 Collector 上继承的旧版 Jaeger exporter 不叫 otlp(例如,你的 v1 备份使用的是 jaeger 或其他 OTLP 变体),请在 null 移除步骤中相应替换该名称。

TIP

新 exporter 命名为 otlp/jaeger-v2,而不是复用 otlp 这个名称,这样如果你之后在观察期内还想同时写入旧版 Jaeger,便可以对称地把额外的 exporter 补回为 otlp/jaeger-v1。请参阅 (可选) 启用向旧版 Jaeger 的双重导出

此时 trace ingestion 已恢复。新的 traces 会写入新的 Jaeger v2 后端,并可在新的 Jaeger UI 中检索。

验证迁移

  1. 确认两个 OpenTelemetryCollector 资源都处于健康状态:

    kubectl get opentelemetrycollector -A

    示例输出:

    NAMESPACE       NAME     MODE         VERSION   READY   AGE   IMAGE                                                           MANAGEMENT
    cpaas-system    otel     deployment   0.147.0   1/1     5h    build-harbor.alauda.cn/asm/opentelemetry-collector:0.147.0-r0   managed
    jaeger-system   jaeger   deployment   0.147.0   1/1     33m   build-harbor.alauda.cn/asm/jaeger:2.16.0-r2                     managed

    cpaas-system/otel(面向应用的 Collector,由 OpenTelemetry v1 → v2 迁移 重新部署)和 jaeger-system/jaeger(在 部署新的 Jaeger v2 实例 中部署的新 Jaeger v2 后端)都必须报告 READY<ready>/<desired>,且 <ready> 等于 <desired>(通常为 1/1),MANAGEMENTmanaged。如果 READY 列显示 0/1 或为空,请先检查对应 namespace 中的 Collector Pod 日志,再继续操作。

  2. 使用 telemetrygen 生成示例 traces,并验证它们出现在新的 Jaeger UI 中:

    kubectl apply -n cpaas-system -f - <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: jaeger-migration-check
    spec:
      restartPolicy: Never
      containers:
        - name: telemetrygen
          image: ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest
          args:
            - traces
            - --otlp-endpoint=otel-collector.cpaas-system.svc.cluster.local:4317
            - --otlp-insecure
            - --duration=120s
            - --service=jaeger-migration-check
            - --rate=2
    EOF
    
    kubectl wait -n cpaas-system --for=jsonpath='{.status.phase}'=Succeeded \
      pod/jaeger-migration-check --timeout=10m
    kubectl delete -n cpaas-system pod/jaeger-migration-check

    位于 <platform-url>/clusters/<cluster>/jaeger 的新 Jaeger UI 应显示 jaeger-migration-check 服务及其 traces。

  3. 确认 Elasticsearch 中已创建新的索引族,并且旧版索引族仍然完整:

    curl -k -sS -u "${ES_USER}:${ES_PASS}" "${ES_ENDPOINT}/_cat/indices?v" \
      | grep -E 'acp-tracing-|acp-' | sort

    你应该能看到匹配 acp-tracing-<cluster>-jaeger-* 的旧版索引(按日期标记,不再增长)以及匹配 acp-<cluster>-jaeger-*-000001 的新索引(rollover,仍在增长)。

  4. 抽查一次真实业务请求是否会在新的 Jaeger UI 中产生 trace。挑选一个或两个已经完成埋点的应用,触发一个代表性请求,并在新的 Jaeger UI 中查找其 traceID。

观察期

在切换后,请将旧版 Jaeger 继续运行 至少 7 天,与旧版 esIndexCleaner.numberOfDays 保留策略保持一致。在此窗口内:

  • 旧版 Jaeger UI 会继续提供所有尚未被旧版 jaeger-es-index-cleaner 删除的切换前 traces。该 cleaner 会在每个索引创建后约 7 天将其删除;一旦所有切换前索引都被清理完,旧版 Jaeger 就不再保留任何有用数据,可以卸载。
  • 新的 Jaeger 会累积切换后产生的 traces。请在新的 Jaeger UI 和 v2 Java agent 指标名称上验证仪表板、告警以及 Kiali 集成。
  • 清晰地传达这一分界:告诉用户新的 Jaeger UI 只显示从切换点开始的 traces,而更早的 traces 仍保留在旧版 Jaeger UI 中。

如果切换前的 traces 没有业务价值,你可以缩短或跳过观察期,直接进入 清理;代价是,一旦旧版栈被移除,切换前的任何 traces 都将不再可访问。

WARNING

一旦在 卸载旧版 Jaeger 实例 中删除了旧版 Jaeger 实例,切换前的 traces 将无法恢复。请在继续之前确认没有人仍然依赖它们。

清理

卸载旧版 Jaeger 实例

TIP

如果你启用了 (可选) 启用向旧版 Jaeger 的双重导出,请先按照 停止双重导出 的说明,从 v2 Collector pipeline 中移除旧版 exporter。只要 v2 Collector 还在引用旧版 Jaeger collector Service,该 Service 就必须保留;否则 OTLP exporter 会持续累积连接错误,直到 Collector 被打补丁。

删除旧版 Jaeger 实例及其配套资源:

kubectl -n cpaas-system delete ingress      jaeger-prod-query         --ignore-not-found
kubectl -n cpaas-system delete podmonitor   jaeger-prod-monitor       --ignore-not-found
kubectl -n cpaas-system delete jaeger       jaeger-prod               --ignore-not-found
kubectl -n cpaas-system delete rolebinding  jaeger-prod-rb            --ignore-not-found
kubectl -n cpaas-system delete role         jaeger-prod-role          --ignore-not-found
kubectl -n cpaas-system delete sa           jaeger-prod-sa            --ignore-not-found
kubectl -n cpaas-system delete secret       jaeger-prod-oauth2-proxy  --ignore-not-found
kubectl -n cpaas-system delete secret       jaeger-prod-es-basic-auth --ignore-not-found
kubectl -n cpaas-system delete configmap    jaeger-prod-oauth2-proxy  --ignore-not-found

卸载 Alauda Build of Jaeger Operator:

kubectl -n jaeger-operator delete subscription jaeger-operator --ignore-not-found
TIP

如果集群中不再存在其他 Jaeger 资源,也可以删除 jaegers.jaegertracing.io CRD:

kubectl get jaeger -A
kubectl delete crd jaegers.jaegertracing.io

禁用旧版功能开关并清理旧版索引

  1. 在 ACP Web 控制台中,打开 Feature Switch 并禁用 acp-tracing-ui。旧版 Alauda Build of OpenTelemetry v1 Operator 卸载后,平台定制的 Observability → Tracing 视图将不再可用。请更新内部文档和 runbook,将其指向 Jaeger UI URL <platform-url>/clusters/<cluster>/jaeger

  2. 旧版 jaeger-es-index-cleaner CronJob 会随着旧版 Jaeger 实例一起被删除,因此 Elasticsearch 中剩余的任何 acp-tracing-<cluster>-jaeger-* 索引都不会再自动轮转。请手动删除它们:

    # The legacy index prefix is "acp-tracing-${CLUSTER_NAME}" by default, 
    # but if your legacy Jaeger used a custom prefix, substitute it in the pattern below.
    JAEGER_ES_INDEX_PREFIX="acp-tracing-${CLUSTER_NAME}"
    # Inspect first. _cat/indices/<pattern>?v restricts the table to indices
    # matching the legacy prefix.
    curl -k -sS -u "${ES_USER}:${ES_PASS}" \
      "${ES_ENDPOINT}/_cat/indices/${JAEGER_ES_INDEX_PREFIX}-jaeger-*?v"
    # Delete after confirming. ?h=index returns just the index-name column
    # (no table header), which the for-loop iterates over.
    for idx in $(curl -k -sS -u "${ES_USER}:${ES_PASS}" \
                   "${ES_ENDPOINT}/_cat/indices/${JAEGER_ES_INDEX_PREFIX}-jaeger-*?h=index"); do
      curl -k -sS -u "${ES_USER}:${ES_PASS}" -X DELETE "${ES_ENDPOINT}/${idx}"
      echo
    done

(可选)启用向旧版 Jaeger 的双重导出

将 v2 OpenTelemetry Collector 配置为把每个 span 同时写入 新 Jaeger旧版 Jaeger,是默认单一导出流水线之外的一种可选方案。当出现以下任一情况时,可考虑使用:

  • 并行验证。 你希望在完全依赖新后端之前,在观察期内使用生产流量对比新旧 Jaeger。
  • 更快的原地回滚。 如果新 Jaeger 在观察期内出现问题,只需通过一次补丁将 otlp/jaeger-v2 从 trace pipeline 中移除,旧版 Jaeger 就会持续、不中断地接收 traces。
  • 逐步切换 UI。 不同团队计划按各自节奏从旧版 UI 切换到新 UI,你希望在过渡期间两个 UI 都能显示切换后的数据。

权衡如下:

  • 由于每个 span 都会被索引到两个索引族中,Elasticsearch 的写入负载和存储占用在观察期内会大约 翻倍
  • 在卸载旧版 Jaeger 之前,trace pipeline 必须通过 停止双重导出 额外打一个补丁才能恢复。
  • 需要监控两个导出流水线的失败情况(otelcol_exporter_send_failed_spans_total,分别针对 otlp/jaeger-v2otlp/jaeger-v1)。

双重导出不会将切换前的 traces 回填到新 Jaeger;切换前的 traces 仍然只能通过旧版 Jaeger UI 查询。

启用双重导出

将 v2 OpenTelemetry Collector 切换到新的 Jaeger 收敛之后,otel Collector 只有一个向 Jaeger 后端写入的 trace exporter,即 otlp/jaeger-v2(trace pipeline 为 [debug, otlp/jaeger-v2])。请对 Collector 打补丁,将旧版 Jaeger 作为第二个 exporter otlp/jaeger-v1 加回去,并复制被切换步骤移除的原始 otlp exporter 的旧版 Jaeger endpoint、headless-Service 负载均衡和 TLS 设置:

kubectl -n cpaas-system patch opentelemetrycollector otel --type=merge -p '
spec:
  config:
    exporters:
      otlp/jaeger-v1:
        endpoint: dns:///jaeger-prod-collector-headless.cpaas-system:4317
        balancer_name: round_robin
        tls:
          insecure: true
    service:
      pipelines:
        traces:
          exporters: [debug, otlp/jaeger-v2, otlp/jaeger-v1]
'
kubectl rollout status deployment/otel-collector -n cpaas-system --timeout=180s
WARNING

service.pipelines.traces.exporters 是一个数组,而 merge patch 会整体替换数组,而不是追加。上面的 patch 列出了 trace pipeline 中必须保留的所有 exporter(debugotlp/jaeger-v2otlp/jaeger-v1)。如果你的 trace pipeline 还包含其他自定义 exporter,请在应用补丁之前将它们加入此列表。

补丁应用后,每个 span 都会同时写入两个 Jaeger 后端。

停止双重导出

在观察期结束后、且在 卸载旧版 Jaeger 实例 之前,请从 trace pipeline 中移除旧版 exporter:

kubectl -n cpaas-system patch opentelemetrycollector otel --type=merge -p '
spec:
  config:
    exporters:
      otlp/jaeger-v1: null
    service:
      pipelines:
        traces:
          exporters: [debug, otlp/jaeger-v2]
'
kubectl rollout status deployment/otel-collector -n cpaas-system --timeout=180s

应用该补丁后,v2 Collector 只会向新的 Jaeger 写入 traces。现在可以继续执行 卸载旧版 Jaeger 实例

回滚

关于 OpenTelemetry v1 → v2 阶段的回滚,请参阅 OpenTelemetry v2 迁移指南中的 回滚。对于本文档中执行的 Jaeger 迁移阶段,请根据当前所处阶段选择相应的回滚路径:

已到达阶段推荐回滚方式
部署新的 Jaeger v2 实例 之前Jaeger 阶段无需任何操作——旧版 Jaeger 仍在接收 traces,而新 Jaeger 尚未部署。
部署新的 Jaeger v2 实例 之后、但在 将 v2 OpenTelemetry Collector 切换到新的 Jaeger 之前删除新的 Jaeger 实例(kubectl -n jaeger-system delete opentelemetrycollector jaeger)。旧版 Jaeger 保持完整,并继续接收 traces。
新 Jaeger 在观察期内出现问题(默认单一导出)对 v2 Collector 打补丁,使其 trace pipeline 重新指向旧版 Jaeger collector(将 otlp/jaeger-v2 替换为指向 jaeger-prod-collector-headless.cpaas-system:4317 的 exporter)。旧版 Jaeger 会立即再次接收 traces。最快的预置路径是先通过 启用双重导出 切换到双重导出;如果那条路径已经在使用,则只需移除 otlp/jaeger-v2 即可。
新 Jaeger 在观察期内出现问题(已启用双重导出)对 v2 Collector 打补丁,从 trace pipeline 中移除 otlp/jaeger-v2。在你排查问题期间,旧版 Jaeger 会继续接收 traces。
旧版 Jaeger 在观察期内出现问题(已启用双重导出)对 v2 Collector 打补丁,从 trace pipeline 中移除 otlp/jaeger-v1。这等同于提前结束双重导出;切换前、且早于旧版保留期的 traces 将无法在新 Jaeger 中访问。
观察期结束后——完全回滚到旧版栈首先,将 v2 Collector 的 trace pipeline 重新指向旧版 Jaeger。然后按照 OpenTelemetry v2 迁移指南中的 回滚 执行,并再次滚动发布应用 Pod,以便重新注入旧版 Java agent。在重新安装旧版 Operator 之前,必须先卸载新的 Jaeger v2 实例和 OpenTelemetry v2 Operator。

FAQ

应用是否需要更新它们的 OTLP endpoint?

不需要。按照 OpenTelemetry v2 迁移指南中的 重新创建 OpenTelemetryCollector 资源 指导,v2 OpenTelemetry Collector 会部署在相同的 namespace(cpaas-system)、使用相同的 Service 名称(otel-collector)和相同的端口(4317/4318)。向 otel-collector.cpaas-system:4317 导出的工作负载无需任何更改即可继续工作。

新的 Jaeger UI 会显示切换前的 traces 吗?

不会。切换前的 traces 只存储在旧版 Jaeger 中,并且在旧版保留窗口内(默认 7 天)仍可通过旧版 Jaeger UI 查询。新的 Jaeger UI 从切换点开始显示 traces。请提前告知用户,并在观察期内引导他们通过旧版 UI 查询更早的 traces。

应该在什么时候启用双重导出?

默认的单一导出路径足以满足大多数迁移场景。只有在以下情况之一成立时,才启用双重导出((可选) 启用向旧版 Jaeger 的双重导出):

  • 你需要在正式依赖新 Jaeger 之前,使用生产流量验证它与旧版 Jaeger 的一致性。
  • 不同团队会按各自计划从旧版 UI 切换到新 UI,并且你希望在过渡期间两个 UI 都显示切换后的数据。
  • 你希望在观察期内获得尽可能快的原地回滚路径。

请注意,双重导出会使观察期内 Elasticsearch 的写入负载和存储量大约翻倍,并且在卸载旧版 Jaeger 之前需要额外执行一个补丁步骤。

旧版和新的 Jaeger 可以共享同一个 Elasticsearch 索引吗?

不可以。旧版 Jaeger 使用按日生成、带日期标记的索引(acp-tracing-<cluster>-jaeger-span-YYYY-MM-DD),而 Jaeger v2 使用 rollover 别名(以 *-000001*-000002 等为后端的 acp-<cluster>-jaeger-span-write / -read)。二者的 schema 和生命周期管理方式不同,因此两个索引族必须保持分离。请保留 部署新的 Jaeger v2 实例 中显示的默认前缀,以避免冲突。

观察期内需要多少额外的 Elasticsearch 存储空间?

在默认单一导出路径下,新索引族会从零开始增长,而旧索引族会在旧版保留期内逐步过期;请预留一个完整保留周期的 trace 存储作为稳态缓冲。启用双重导出时,请在整个观察期内预留大约等于旧索引族稳态大小两倍的空间,并额外留出重试和 ingestion 突发所需的余量。

迁移过程中可以启用 Service Performance Monitoring (SPM) 吗?

SPM 是可选的,并且可以在 验证迁移 之后的任何时间启用。请按照 (可选) 启用 Service Performance Monitoring (SPM) 的说明,添加 spanmetrics connector 并在新的 Jaeger 中配置 metrics 后端。