一次被 Istio 误导的连通性测试

文章目录

背景

我们要把一个服务迁移到新的负载均衡上。域名保持不变,但它的后端负载均衡 IP 会换成新的。迁移前需要先确认:从我们当前的服务器到新 IP 之间,网络是否连通。

听起来很简单:拿新 IP 发一个请求,看能不能通。但实际测下来,过程却不是那么顺利。

现象

同一个健康检查请求,在不同环境下结果不一样:

  • 在没有 sidecar 的 Pod 里,直接访问新 IP,TCP 连接超时。
  • 在有 Istio sidecar 的 Pod 里,访问新 IP,但不带业务域名的 Host 请求头,同样不通。
  • 在有 Istio sidecar 的 Pod 里,访问新 IP,并带上业务域名的 Host 请求头,返回 200。
  • 老的 IP 则在两类 Pod 里都能访问。

一开始很容易把问题归到节点路由、网段互通或防火墙差异上。但真正要回答的问题是:带 sidecar 时测到的结果,为什么会依赖 Host 请求头?

排查过程

先在没有 sidecar 的 Pod 里用 TCP mtr 和 curl 验证。Pod 能到达部分外部地址,但对新 IP 无法完成连接。这说明不是整个 Pod 网络都不能出站,问题集中在新的目标地址上。

接着在带 sidecar 的 Pod 里分别测试两种请求:

sh 复制代码
# 不指定业务 Host:连接建立,但没有 HTTP 响应
curl -v http://<new-lb-ip>/send/management/health

# 指定业务 Host:返回 200
curl -v -H 'Host: api.example.internal' \
  http://<new-lb-ip>/send/management/health

这时候需要对比两者的 istio-proxy sidecar 的日志,关键证据显示,不指定 Host 时:

text 复制代码
upstream_cluster: PassthroughCluster
route_name: allow_any

这说明 Envoy 只是把请求透明地转发到原始目标地址,也就是我们填的新 IP,没有命中任何 Istio 已知服务。

指定业务 Host 后,日志变成:

text 复制代码
authority: api.example.internal
upstream_cluster: outbound|80||api.example.internal
upstream_host: <old-lb-ip>:80
response_code: 200

问题就在这里。请求虽然发给了新 IP,但 Envoy 根据 Host 里的域名,解析出了这个域名当前的后端 IP------还是老 IP。所以这次成功的请求,实际连接的是老 IP,不是我们想测的新 IP。

到这里自然会有一个疑问:为什么 Envoy 会主动去解析这个 Host,而不是老老实实把请求转发到原始地址?

为什么 Envoy 会解析这个 Host

关键在于 Istio 的默认出站行为。sidecar 接管出站流量后,会先看请求的 Host 是否匹配某个已注册的服务。匹配上了,就按这个服务的配置走;匹配不上,才退回透明转发。

这个"已注册的服务"来自 ServiceEntry。我们的业务域名在 ServiceEntry 里声明过,并且 resolution: DNS。也就是说,Istio 明确告诉 Envoy:这个域名是一个外部服务,地址要通过 DNS 解析得到。

所以 Envoy 不是"主动"去解析,而是被配置驱动。它收到 Host: api.example.internal,发现这个域名在 ServiceEntry 里,于是按 resolution: DNS 去解析,拿到域名当前的后端 IP。域名还没切到新 IP,解析结果自然还是老 IP。

不带 Host 时,请求没有可匹配的域名,Envoy 只能走 PassthroughCluster,把请求原样转发到原始地址,也就是新 IP。这就是为什么两种请求结果完全不同。

结论

带 sidecar 时,指定 Host 并不能测到新 IP 的连通性。恰恰相反,它让 Istio 按域名解析出当前后端,而当前后端还是老 IP,于是测到的是老 IP 的连通性。

真正的差异在 HTTP 路由:

text 复制代码
应用请求新 IP
  -> sidecar 截获流量
  -> Envoy 根据 HTTP Host 匹配已注册服务
  -> DNS 解析业务域名
  -> 连接到域名当前的后端 IP(还是老 IP)

不指定 Host 时,Envoy 走 PassthroughCluster,直接连接原始地址,也就是新 IP,所以才会超时。指定 Host 后,请求被 Envoy 按服务配置重新选择上游,绕过了新 IP。

换句话说,带 sidecar 的测试结果不能用来判断新 IP 是否可达。要测新 IP,必须让请求真正落到新 IP 上,而不是被 Istio 按域名重新路由。

Istio 与 ServiceEntry 如何配合

Istio sidecar 通过 Pod 网络规则接管出站流量。对于 HTTP,它可以读取请求中的 Host,把请求路由到与该主机名对应的 Envoy cluster。

ServiceEntry 用于把集群外的服务声明给 Istio。例如:

yaml 复制代码
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
spec:
  hosts:
    - api.example.internal
  location: MESH_EXTERNAL
  resolution: DNS
  ports:
    - number: 80
      protocol: HTTP

这段配置告诉 Istio:api.example.internal 是一个 mesh 外部的 HTTP 服务,地址通过 DNS 解析。sidecar 收到 Host: api.example.internal 后,会选中该服务的 cluster,再连接 DNS 解析出的 endpoint。

这里有两个关键点,都来自 Istio 官方文档:

  • ServiceEntry 的 hosts 字段会与 HTTP 的 Host/Authority 头匹配。也就是说,sidecar 是靠请求头里的域名来识别这个服务的。
  • resolution: DNS 时,若未指定 endpoints,proxy 会解析 hosts 中的域名作为路由目标。官方文档还特别指出,使用 DNS 解析时,sidecar 会忽略原始目的 IP,改为按域名做 DNS 查询后路由。

这两点正好解释了我们的现象:请求头里的域名决定了 Envoy 去解析谁,而解析结果由 DNS 决定。域名没切到新 IP 之前,解析出来的始终是老 IP。

另外,ALLOW_ANY 是 Istio 的默认出站模式。官方文档说明,在这种模式下,对 mesh 内未注册的未知服务,Istio proxy 会透传(passthrough)。这就是不带 Host 时走 PassthroughCluster、直连原始地址的原因。

所以 ServiceEntry 不等于网络放通。它提供的是服务身份、协议和解析方式;实际网络仍需允许 sidecar 到解析结果的出站连接。

排查要点

遇到"带 sidecar 成功、没有 sidecar 失败"时,先不要假定是网络策略差异。优先检查:

  1. 成功请求的 Host 是否与 ServiceEntry、VirtualService 中的域名一致。
  2. Envoy access log 中的 upstream_cluster 和 upstream_host。
  3. 成功请求最终连接的地址,是否与 URL 中的原始地址不同。

这三项通常比继续跑 traceroute 更快找到真实的路由分叉点。尤其在做迁移前的连通性测试时,一定要确认请求最终连的是不是目标 IP,否则很容易被 Istio 的域名路由误导。

因为这个 k8s 集群环境是前人搭建的,而且缺少代码管理和文档描述,依据对 istio 缺乏理解,所以在排查过程中绕了好几道弯,才定位到这个特殊的 SE 配置。

参考

相关推荐
SelectDB12 小时前
安全评审卡了三周,我把部署形态的四种选项重新排了一遍
大数据·数据库·云原生
阿里云云原生13 小时前
完整还原已经服务千家企业的 AIOps Agent 的评测和调优实践
云原生
阿里云云原生13 小时前
让 Agent 成为企业生产力丨Alibaba Cloud AgentCore 企业智能体构建与治理沙龙·上海站精彩回顾 & PPT 下载
云原生·agent
阿里云云原生15 小时前
交付周期从 51 天缩短到 14 天,多 Agent 协作产品⾃进化背后的组织重构
云原生·agent
阿里云云原生15 小时前
从部署上线到运维优化:STAROps 与 ROS Agent 的资源运维自动化实践
云原生
xianyuCcCcCCCcc18 小时前
Kubernetes 资源调度与弹性伸缩:Schedule、Metric、HPA 与 Quota
云原生·kubernetes
分布式存储与RustFS18 小时前
在 1Panel 应用商店部署 RustFS:安装、配置与验证步骤
云原生·开源·对象存储·分布式存储·s3·rustfs·性能基准
知已难寻20 小时前
第 5 篇 · 云原生生态与实践:微服务、DevOps、可观测性与 Serverless
大数据·linux·服务器·微服务·云原生·云计算·devops
孔令飞20 小时前
AI 时代岗位调研分析:调研了近3000份AI岗位描述,分享下调研结果
云原生·go·ai编程
L02082421 小时前
Kubernetes Service 与 kube‑proxy 深度详解
运维·算法·云原生·容器·贪心算法·kubernetes