迁移可观测性堆栈
属于阶段 6。Mesh v1 自带一条 tracing pipeline——一个 OpenTelemetry v1 collector 和一个 Jaeger 1.x backend——二者都随其在阶段 5中移除。本文档将安装当前堆栈,保留迁移前收集的 traces 以便查询,并恢复应用程序的遥测行为。
从在阶段 5中删除 Mesh v1 collector,到在此处将 mesh 重新指向新的 collector 之间,spans 会被丢弃。Metrics 和访问日志不受影响。请将此部分安排在可以接受 traces 出现间断的时间窗口内。
OpenTelemetry v1 和 v2 Operators 使用相同的 custom resource definitions,因此只有在移除包含 v1 的 Mesh v1 后,才能安装 v2。
目录
开始之前接管现有索引的保留期限安装新的 tracing stack将现有索引附加到新的读取别名将 mesh 重新指向新的 collector迁移 Java auto-instrumentation将 Kiali 连接到 Jaeger v2验证开始之前
加载迁移变量 source "${BACKUP_DIR}/vars.env",并收集阶段 0记录的内容:
-
${BACKUP_DIR}/v1-jaeger.txt— Elasticsearch index 前缀以及 Mesh v1 tracing backend 的保留期限。 -
${BACKUP_DIR}/v1-jaeger-es-credentials.yaml— Mesh v1 backend 用于向 Elasticsearch 进行身份验证的 secret。新的 backend 将部署到同一个 Elasticsearch 集群,并需要相同的凭据:这些是以下安装步骤要求提供的
ES_ENDPOINT、ES_USER和ES_PASS。Mesh v1 secret 中的键名为ES_USERNAME和ES_PASSWORD。 -
${BACKUP_DIR}/instrumentations.yaml— Mesh v1 的Instrumentationresource,其中包含 exporter endpoint、sampler 以及应用程序上报的 service name pattern。 -
${BACKUP_DIR}/v1-instrumented-pods.txt— 使用 Java auto-instrumentation 的 workloads,每行一个:namespace、workload、application container、microservice name 和 reported service name。 -
${BACKUP_DIR}/v1-injected-env.txt— Mesh v1 webhooks 添加到 application containers 的变量。
准备好一条迁移前的 trace——其 trace ID、service name 和 span 数量。它是末尾验证所依据的参考。
接管现有索引的保留期限
Mesh v1 tracing backend 运行一个 cron job,在索引超过配置的保留期限后将其删除。该 job 由 Mesh v1 tracing resource 所有,并随该 resource 一同删除,因此这些索引目前不会过期。
按照 接管旧版索引的保留期限 的说明,为现有索引系列应用仅删除索引生命周期策略,并使用 ${BACKUP_DIR}/v1-jaeger.txt 中的值:
LEGACY_ES_INDEX_PREFIX— Mesh v1 tracing backend 的es.index-prefix,默认为asm-mesh-<meshID>。- 删除索引的期限 — 其 index cleaner 的
numberOfDays,默认为 7。
安装新的 tracing stack
按照使用 Service Mesh 配置分布式 tracing 平台 中的前提条件,在 jaeger-system namespace 中安装 Alauda Container Platform Distributed Tracing(此前称为 Alauda Build of Jaeger v2)集群插件、Alauda Container Platform Application Observability(此前称为 Alauda Build of OpenTelemetry v2)Operator、Jaeger v2 实例以及 v2 collector。
对于迁移后的 mesh,以下三个选择十分重要:
- 使用与 Mesh v1 backend 相同的 Elasticsearch 集群,否则新的 backend 无法提供现有 traces。
- 按 mesh 而非按集群选择 index prefix。 跨多个集群的 mesh 会写入同一个索引系列,以便从同一位置组装跨集群的 trace。作用于 Elasticsearch 的步骤——生命周期策略和索引初始化——随后属于 mesh,而不是集群:使用 mesh 的 prefix 执行一次,并在每个其他集群上跳过这些步骤。之后,任意集群的 Jaeger 实例都可以提供整个 mesh 的 traces。保留默认 prefix,且绝不要复用 Mesh v1 的 prefix:接管 Mesh v1 索引保留期限以及之后弃用这些索引的步骤会按
<prefix>-jaeger-*选择索引,因此共享 prefix 也会将这些步骤应用到新的索引系列。 - 为每个集群提供其专属的 collector。 所有集群的 collectors 共享一个 service name,而重新指向 mesh 的步骤会将该 service 声明为集群本地服务,因此每个 proxy 都会向其所属集群的 collector 导出数据,参见将 trace 上报限制在各集群内部。
完成前提条件后停止。mesh 侧的配置已在迁移过程中存在,下一步会更新该配置。
将现有索引附加到新的读取别名
将 Mesh v1 索引附加到新索引系列的读取别名后,迁移前的 traces 便可在新的 Jaeger UI 中查询。不会复制或重新建立索引,旧索引仍保持只读。
按照 Attach the legacy indices to the new read aliases 操作,将 LEGACY_ES_INDEX_PREFIX 设置为 Mesh v1 的 prefix,并将 JAEGER_ES_INDEX_PREFIX 设置为新 instance 的 prefix。在多 cluster mesh 中,只需对整个 mesh 执行一次。
Mesh v1 backend 仅写入 span 和 service 索引。附加步骤还会处理 dependency 和 sampling 索引,并针对这两类索引报告 index_not_found_exception。这是预期行为,不会影响结果。
将 mesh 重新指向新的 collector
mesh 会将 spans 发送到 Istio resource 中定义的 provider。将 Mesh v1 provider 替换为指向新 collector 的 provider,并更新 mesh-wide Telemetry resource 以使用该 provider。
- 依次运行这两个命令。在两者执行间隔期间,mesh-wide
Telemetryresource 仍然指向zipkin,而Istioresource 已不再定义该 provider。在这几秒内 spans 会被丢弃 — 这正是 mesh 自 阶段 5 以来一直处于的状态 — 其他方面不会受到影响。 serviceSettings将 collector service 声明为 cluster-local,使每个 proxy 都导出到其所在 cluster 的 collector,请参阅使用 Service Mesh 配置分布式 tracing 平台。在单 cluster mesh 中,此设置不会改变任何内容。合并补丁会整体替换两个列表,因此该命令会读取 mesh 已有的 service 设置 — 阶段 2 已从 Mesh v1 复制这些设置 — 并在追加 collector 条目后将其写回。extensionProviders列表会被替换:如果 mesh 定义了其他 provider,请改用kubectl edit istio default编辑 resource。V1_TRACE_SAMPLING是 mesh 在迁移前使用的采样百分比,记录在${BACKUP_DIR}/v1-mesh-settings.json中。此处仅更改 provider;mesh trace 的数量保持不变。
如果 Istio resource 使用 discoverySelectors 限制 discovery,请为 jaeger-system namespace 添加标签,以便控制平面能够解析 collector service。
如果 Sidecar resource 限制 egress.hosts,请向其中添加 jaeger-system/*,否则其 proxies 会在没有错误的情况下丢弃每个 span,请参阅使用 Sidecar 导入。
Mesh spans 现在已到达新的 backend。继续之前,请检查 Jaeger UI。
迁移 Java auto-instrumentation
由 OpenTelemetry Operator 进行 instrument 的应用需要恢复三项内容:注入 annotations、一个 Instrumentation resource,以及它们在迁移前报告的环境。
在 Mesh v1 中,平台 webhook 向每个 pod 添加注入 annotations 和身份变量,Instrumentation 中的 cpaas-system resource 引用了这些内容。现在两者都不存在,因此必须将 annotations 和变量值写入能够自行持久保留的位置。
每个步骤都会将属于一个 workload 的值写入该 workload 的 template。为一个 workload 设置 MESH_NAMESPACE、WORKLOAD、APP_CONTAINER、MS_NAME 和 SERVICE_NAME,为其运行相应步骤 — service name、变量、annotations、rollout — 并在为下一个 workload 设置这些值之前检查结果。agent image 在整个 cluster 中选择一次,每个 namespace 选择一次 Instrumentation resource;此后的所有操作都针对单个 workload。
设置 workload 的变量
下面的每个步骤都会作用于这些变量所命名的 workload。从 ${BACKUP_DIR}/v1-instrumented-pods.txt 中该 workload 所在的行获取变量值;该行已在阶段 0中记录为 <namespace> <workload> <application-container> <microservice> <service-name>。将 <namespace> 和 <workload> 替换为你自己的值:
任何值都不能为空或读取为 -。APP_CONTAINER 是注入 agent 的容器,也是这些变量所属的容器;MS_NAME 是该 workload 在 Mesh v1 中所属的 microservice — 它不一定是 workload 的名称;SERVICE_NAME 是应用在迁移前报告的名称。错误或空值会像其他值一样被接受并报告:应用报告的身份会发生变化,但不会有任何操作失败。
准备 Java agent image
Mesh v1 提供了自己的 Java agent image。Mesh v2 不提供,因此请选择一个 image,并按照 准备 Java agent image 中的说明,使 cluster 能够访问该 image。将 <java-auto-instrumentation-image> 替换为你自己的值。
创建 Instrumentation resource
使用 ${BACKUP_DIR}/instrumentations.yaml 中的值,按照 v2 agent 的格式重新创建 Mesh v1 配置。每个 namespace 创建一个 resource,即可为其中所有经过 instrument 的 workload 提供服务:
- Java agent 2.x 默认使用
http/protobuf导出,而 1.x 使用 gRPC。可以像上面一样将 endpoint 指向 HTTP 端口4318,也可以保留端口4317,并将OTEL_EXPORTER_OTLP_PROTOCOL: grpc添加到spec.env。 - Mesh v1 使用自己的 sampler,对每个 root span 进行采样,并在其余情况下遵循调用方的决定。使用
parentbased_traceidratio和argument: "1.0"即可使用 agent 中内置的等效配置。如果采样比例低于 100%,请降低该参数。 - Mesh v1 还会从 agent 以 Prometheus 格式导出 metrics。v2 agent 通过 OTLP 报告 metrics;请从 collector 抓取它们,而不是从 application pod 抓取。
- 2.x agent 默认导出 logs,而 Mesh v1 不会导出 logs。没有 logs pipeline 的 collector 会使用
404响应这些请求,并且 agent 会在每次导出时记录一条警告。OTEL_LOGS_EXPORTER: none可保持应用原有的行为。只有在为 collector 添加 logs pipeline 后,才将其设置为otlp。
保留应用的 service names
Mesh v1 使用 microservice name 和 namespace <microservice>.<namespace> 构建所报告的 service name,所使用的变量由 Mesh v1 webhook 注入。没有该 webhook 时,OpenTelemetry Operator 会回退到 workload name,这会改变应用在 Jaeger、dashboards 和 alerts 中的显示方式。
使用 workload 的 SERVICE_NAME,在 application container 上显式设置该名称:
这是一个 strategic merge patch:它根据名称匹配 container,并根据名称匹配变量。只会写入这一个变量;如果 container 没有 env 列表,则会创建该列表;再次运行此步骤时会更新该值,而不是追加同一变量的第二个定义。在 application container 上设置该变量,可以无论由哪个 component 注入 agent,都保持名称稳定。
恢复应用读取的变量
OTEL_SERVICE_NAME 并不是 Mesh v1 webhook 添加到 application container 的唯一变量。来自阶段 0的 ${BACKUP_DIR}/v1-injected-env.txt 列出了其余变量 — ASM_MS_NAME、ASM_POD_NAMESPACE、ASM_CLUSTER_NAME 和 ASM_CONTAINER_NAME。读取其中一个变量的应用在迁移后仍会继续运行,但读取到的是空值,因此不会报告任何内容:原本存放诸如 frontend-ms.app-all 之类名称的字段,现在存放的是 null.null。
使用 workload 的 MS_NAME,将应用所依赖的变量以字面值添加到 workload template 中:
然后检查 application container 最终保留的内容:
示例输出
每个变量都只列出一次,并且都有值。上面的补丁会就地更新变量,因此空值只表示该步骤在设置变量之前运行过:设置变量后再次运行该步骤。列为 2x 的变量在此步骤之前已经在 workload template 中定义了两次 — container 会读取最后一个定义,API server 会在之后每次更改 workload 时发出 hides previous definition of "..." 警告,而之后的 apply 可能会将其丢弃。使用 kubectl -n "${MESH_NAMESPACE}" edit deploy "${WORKLOAD}" 删除多余条目,同时保留包含所需值的定义。
只要没有应用读取这些变量,跳过此步骤就是安全的。请与应用负责人确认,而不要自行假设:cluster 中没有任何内容会报告解析为空字符串的变量。
重新启用注入
Mesh v1 将注入 annotations 添加到了 pod。请改为将它们写入 workload template:
如果某个 namespace 中的每个 workload 都是 Java 应用,请为 namespace 添加 annotation,而不是为每个 workload 添加:
如果没有 java-container-names,agent 会被注入 pod 的第一个 container — 在 mesh workload 中,该 container 可能是 proxy,而不是你的应用。请像上面一样,在每个经过 instrument 的 workload 上使用 instrumentation.opentelemetry.io/java-container-names 显式命名 container;如果 pod 中运行多种语言的应用,则使用 instrumentation.opentelemetry.io/container-names。注入到 proxy container 的 agent 不会 instrument 任何内容,并且该 workload 会从 traces 中消失。
将 Kiali 连接到 Jaeger v2
按照将分布式 tracing 平台与 Alauda Build of Kiali 集成中的说明,将 Kiali 资源的 tracing 配置设置为新的 Jaeger query service。阶段 1安装 Kiali 时未配置该服务。
在多集群 mesh 中,将 Kiali 指向其所在 cluster 的 Jaeger 实例,并将 tracing 部分的 query scope 设置为整个 mesh,即 istio.mesh_id: <mesh-id>,与 monitoring query scope 保持一致。整个 mesh 使用同一组索引,因此该实例可以为每个 cluster 提供响应。
验证
第二条命令会针对每个注入了 agent 的 pod,列出 agent 所进入的 container 以及该 container 报告的名称。
- 迁移后生成的 traces 会出现在 Jaeger v2 UI 中,包括 mesh proxy 和经过 instrument 的应用的 traces。
- 迁移前保留的 trace 仍可通过其 trace ID 找到,并且 span 数量和 service name 都保持不变。该 trace 是存储下来的,而不是重新生成的,因此不会发生变化。同一个请求的新 trace 可能比迁移前包含更少的 spans — 2.x Java agent instrument 的库集合不同于 Mesh v1 随附的 1.x agent。请将旧 trace 与旧 trace 比较,而不要将其与新 trace 比较。
- 经过 instrument 的应用的 service names 与迁移前报告的名称一致,并且 agent 所进入的 container 是应用 container,绝不会是
istio-proxy。 - Kiali 会在 service 详情页上显示 traces。
- 之前从 Java agent 收集的应用指标现已恢复可用,但现在是通过 collector 提供的。
返回完成迁移,完成迁移的最终验收。