排查迁移问题

Mesh v1 到 Mesh v2 迁移期间报告的症状、原因及处理方法。

Mesh v2 istiod pod 一直处于 Pending 状态

症状。创建 Istio 资源后,其 istiod pod 始终无法调度。其事件中提到了 pod 反亲和性。

原因。Mesh v1 istiod 对其他 istiod pod 设置了必需的反亲和性规则,而集群中没有其他节点可用于放置 Mesh v2 pod。

解决方法。放宽 Mesh v1 控制平面上的规则,参见安装 Mesh v2 控制平面。

对 Mesh v1 资源的请求失败并显示内部错误

症状。修补或删除 Mesh v1 资源时,kubectl 报告 Internal error occurred: failed calling webhook ...: connect: connection refused。

原因。为 webhook 提供支持的 Mesh v1 controller 未运行,而 webhook 使用了 failurePolicy: Fail。

解决方法。在缩减 controller 规模之前删除 webhook 配置。停用 Mesh v1采用的就是这一顺序。不要为了解除已在进行中的删除操作而再次启动 controller。

mesh 命名空间中的新 pod 被拒绝

症状。Deployment 无法创建 pod。错误信息中指出了 Mesh v1 controller 的 webhook。

原因。asm-controller 在其 pod webhook 仍处于安装状态时被缩减了规模。该 webhook 会匹配标记为 cpaas.io/serviceMesh=enabled 的命名空间中的每个 pod,并在失败时拒绝请求。

解决方法。将 asm-controller 恢复为原始副本数。在阶段 5之前,不要停止 Mesh v1 controller。

重启后的工作负载没有 sidecar

症状。在阶段 5之后,原本带有 sidecar 的工作负载重启,但其 pod 没有 istio-proxy 容器。

原因。注入设置位于 pod 上,由 Mesh v1 webhook 添加,并且从未写入工作负载模板。在继承自 Mesh v1 的注入策略(autoInject: disabled)下,不带 sidecar.istio.io/inject: "true" 的 pod 不会被注入。

解决方法。将注解和其他 Mesh v1 pod 设置添加到工作负载模板中,参见迁移工作负载。在停用 Mesh v1 之前,对其他每个工作负载执行相同的检查。

从未加入 mesh 的工作负载现在却被注入

症状。在 Mesh v1 下无需 sidecar 即可运行的工作负载,在其命名空间迁移后却获得了 sidecar。

原因。Mesh v2 的 Istio 资源不使用 Mesh v1 的注入策略。使用默认策略时,带有标签的命名空间中的每个 pod 都会被注入。

解决方法。将 spec.values.global.proxy.autoInject 设置为 Mesh v1 中的值,参见安装 Mesh v2 控制平面。若要使单个工作负载留在原本会进行注入的命名空间中但不被注入,请为其 pod 模板添加标签 sidecar.istio.io/inject: "false"。

Mesh v1 和 Mesh v2 工作负载之间的调用失败

症状。迁移第一个命名空间后,已迁移和尚未迁移的工作负载之间的调用超时,而每个版本内部的调用正常。

原因。两个控制平面的 network 值不同。代理会将另一个网络中的端点视为只能通过东西向网关访问,而单集群 mesh 中不存在该网关。

解决方法。将 Istio 资源的 spec.values.global.network 设置为从 Mesh v1 记录的值,同时检查 spec.values.global.meshID 和 spec.values.global.multiCluster.clusterName。使用 istioctl proxy-config endpoints <pod> -n <namespace> 进行验证:远程端点必须是 pod 地址。

无法解析 ServiceEntry 主机

症状。工作负载迁移后,对仅作为 ServiceEntry 存在的主机发出的请求因 DNS 错误而失败,而相同的调用在迁移前可以正常工作。

原因。Mesh v1 mesh 配置在代理中启用了 DNS 捕获(ISTIO_META_DNS_CAPTURE),但该设置未复制到 Mesh v2。

解决方法。将 Mesh v1 的 mesh 配置复制到 Istio 资源中,参见安装 Mesh v2 控制平面。

新网关对每个请求都返回 404

症状。Mesh v2 网关 pod 正在运行并接收请求,但每个请求都返回 404。

原因。pod 标签与 Gateway 资源的选择器不匹配,因此控制平面不会为其配置任何监听器。仅匹配网关 Service 的选择器足以接收流量,但不足以提供服务。

解决方法。为 pod 模板设置两个选择器的并集,参见迁移网关。使用 istioctl proxy-config listener <pod> -n <namespace> 进行检查。

通过新网关的 HTTPS 失败,而 HTTP 正常

症状。Mesh v2 网关可以响应其 HTTP 路由,但其 HTTPS 端口上的 TLS 握手会被重置。istioctl proxy-config secret 显示证书处于 WARMING 状态。

原因。证书 secret 不在网关命名空间中,或者网关的服务账户无权读取其中的 secret。Mesh v1 可以回退到存储在 istio-system 中的证书;Mesh v2 无法执行此操作。

解决方法。将 secret 复制到网关命名空间中,并创建允许网关读取该 secret 的角色,参见迁移网关。

无法创建 Mesh v1 网关 pod

症状。扩容或重启 Mesh v1 网关不会生成任何 pod,网关最终变为零副本。副本集报告注入模板 asm-gateway 不存在。

原因。网关命名空间现在指向 Mesh v2 revision,而该模板仅存在于 Mesh v1 中。与 mesh 工作负载共享命名空间的网关,在阶段 3切换该命名空间的标签后重启,便会进入此状态。

解决方法。在扩容前将命名空间标签切换回 Mesh v1 revision,或者改为部署 Mesh v2 网关,参见迁移网关。切勿在阶段 3 重启 Mesh v1 网关。另请参见回滚迁移。

网关服务消失

症状。在阶段 5期间,网关停止接收流量,其 Service 不再存在。

原因。该服务由 Mesh v1 资源所拥有,Kubernetes 将其与所有者一同删除。

解决方法。使用准备迁移中的方法,从 ${BACKUP_DIR}/gateway-svc-<namespace>-<name>.yaml 重新创建该服务。备份仍包含所有者引用,而保持不变直接应用的服务会因相同原因在数秒内再次被删除。由于 Mesh v2 网关 pod 带有所需的选择器标签,端点会立即重新填充。在删除 Mesh v1 资源之前,从所有要保留的资源中移除所有者引用,参见停用 Mesh v1。

不再生成访问日志

症状。在阶段 5之后,或工作负载重启后,不再写入访问日志。

原因。Mesh v1 的 Telemetry 资源通过 webhook 添加的标签选择 pod。这些标签已消失,资源本身也随其所有者一同被删除。

解决方法。创建 Telemetry 资源,其选择器与工作负载模板中存在的标签匹配;或者为每个命名空间创建一个不带选择器的资源,参见迁移工作负载。

EnvoyFilter 不再生效

症状。在 Mesh v1 中有效的过滤器对已迁移的工作负载不起作用。

原因。该过滤器限定了代理版本(proxyVersion: ^1\.22.*),而已迁移的代理运行 Istio 1.30。

解决方法。针对新版本重新构建过滤器;如果该过滤器属于即将停用的 Mesh v1 功能,则将其删除。准备迁移中的审计列出了所有受影响的过滤器。

无法删除 Mesh v1 安装资源

症状。kubectl delete asms.operator.alauda.io asm 始终无法完成,operator 日志反复报告代理仍指向控制平面。

原因。卸载前检查会统计带有 sidecar 的 pod,而不考虑注入这些 sidecar 的控制平面。迁移后,这些 pod 已属于 Mesh v2,因此计数始终无法归零。

解决方法。移除 finalizer,参见停用 Mesh v1。

default revision tag 报告 Helm 所有权错误

症状。名为 default 的 IstioRevisionTag 一直处于错误状态,并提到一个不受 Helm 管理的现有资源。

原因。istio-reader-service-account service account 由 Mesh v1 创建,未包含 Helm 元数据。

解决方法。添加 Helm 标签和注解,参见安装 Mesh v2 控制平面。

阶段 5 后应用程序不生成 trace

症状。缺少 mesh span,插桩应用程序也没有报告任何内容。

原因。在可观测性堆栈完成迁移之前,这是预期现象:Mesh v1 collector 和后端已随 Mesh v1 一同移除,注入注解则由已不存在的 Mesh v1 webhook 添加。

解决方法。完成迁移可观测性堆栈。如果之后仍缺少 trace,请检查注入注解是否位于工作负载模板中、是否可以访问 agent 镜像,以及 exporter 协议是否与端口匹配:2.x agent 默认使用 http/protobuf 和端口 4318。

应用程序在 Jaeger 中显示为其他名称

症状。迁移后,服务显示为工作负载名称,而不是之前使用的名称。

原因。Mesh v1 根据其 webhook 注入的变量构建服务名称。

解决方法。在应用程序容器上显式设置 OTEL_SERVICE_NAME,参见迁移可观测性堆栈。

IstioCNI 报告 NetworkAttachmentDefinition 不是已知 kind

症状。IstioCNI 资源始终未就绪,其状态报告为 no matches for kind "NetworkAttachmentDefinition" in version "k8s.cni.cncf.io/v1",尽管集群中已安装 Multus。

原因。Mesh v2 operator 启动时会缓存集群的 API 类型。在 operator 安装后才安装 Multus 的集群中,该类型不会存在于缓存中。

解决方法。重启 operator,然后再次协调:

kubectl -n sail-operator delete pod -l control-plane=servicemesh-operator2
kubectl wait --for condition=Ready istiocni/default --timeout=5m

部分跨集群请求失败并返回 503

症状。在多网络 mesh 中,到达另一集群中工作负载的请求会不时失败,失败率约为百分之几。网关日志记录 503 UC upstream_reset_before_response_started{connection_termination},上游主机是另一集群的东西向网关地址。

原因。Mesh v2 东西向网关没有网络视图。因此,它会获得每个网络的端点,包括发起请求的集群的东西向网关,并将部分流量发回该网关。

解决方法。在网关容器上将 ISTIO_META_REQUESTED_NETWORK_VIEW 设置为其所在集群的网络,参见迁移多网络 mesh。在网关 pod 上检查结果:

kubectl -n istio-system exec "${POD}" -c istio-proxy -- \
  pilot-agent request GET clusters | grep "${TARGET_SERVICE}" | grep cx_total

每个端点都必须是本地集群中 pod 的地址。

多集群 mesh 的 trace 不完整

症状。迁移可观测性堆栈后,trace 仅包含一个集群的 span,或者 span 会随机缺失。每个集群都运行自己的 collector,且两者均运行正常。

原因。该集群的 Istio 资源没有 serviceSettings 条目来声明 collector service 为集群本地服务,因此控制平面会将所有集群的 collector 合并为一组端点,代理会向所有这些端点导出数据。发送到另一个网络的 collector 的 span 永远无法到达。该条目既容易丢失,也容易被设置:serviceSettings 是一个列表,对 meshConfig 应用合并补丁时会整体替换该列表。

解决方法。在每个集群上检查该条目和端点:

kubectl --context "${CTX}" get istio default -o jsonpath='{.spec.values.meshConfig.serviceSettings}{"\n"}'
istioctl --context "${CTX}" proxy-config endpoint "deploy/${WORKLOAD}.${MESH_NAMESPACE}" \
  --cluster "outbound|4317||otel-collector.jaeger-system.svc.cluster.local"

必须为代理提供一个端点,即其所在集群的 collector。将 mesh 重新指向新的 collector 会写回该条目,使用 Service Mesh 配置分布式 tracing 平台 介绍了该配置的适用时机。

Kiali 无数据

症状。尽管流量正在传输,Kiali 图表为空。

原因。Kiali 资源的监控数据源错误、缺少指标资源,或者在多集群 mesh 中,指标未按 mesh 标识符进行过滤。

解决方法。根据使用 Kiali 配置监控检查数据源,并确认每个 mesh 命名空间中都存在 ServiceMonitor 和 PodMonitor 资源。

istioctl 报告没有正在运行的 Istio pod

症状。istioctl proxy-status 返回 no running Istio pods。

原因。Mesh v2 使用 RevisionBased 策略,因此不存在不带 revision 后缀的控制平面。

解决方法。将 --revision "${V2_REVISION}" 添加到命令中。

常见问题

在迁移工作负载之前,是否必须停止 Mesh v1 controller? 不必。它们不会更改已有值的 revision 标签。过早停止它们会中断 mesh 命名空间中的 pod 创建。

何时从命名空间中移除 cpaas.io/serviceMesh 标签? 在阶段 5中,与其他 Mesh v1 残留项一同移除。在此之前保留该标签,可以让 Mesh v1 webhook 继续配置尚未迁移的 pod。

将 Istio custom resource definitions 升级到 1.30 是否会影响 Mesh v1? 不会。这些定义会继续提供 Istio 1.22 使用的 API 版本。

trace 会中断多长时间? 从阶段 5中删除 Mesh v1 collector 的时刻起,直到在阶段 6中将 mesh 重新指向新的 collector 为止。指标和访问日志不会中断。

只有一个副本的工作负载会发生什么? 在滚动重启期间,它们将不可用。如果无法接受这一点,请在迁移前将其扩展为两个副本,并添加 PodDisruptionBudget。