ExternalName Service 劫持了其他服务流量
故障现象
如果网格内存在一个 ExternalName 类型 Service, 网格内访问其他外部服务的的某一端口,如果这个端口刚好和该 ExternalName Service 重叠,那么流量会被路由到这个 ExternalName Service 对应的 CDS。
故障重现
正常情况
在 namespace sample 安装 sleep Pod:
kubectl create ns sample
kubectl label ns sample istio-injection=enabled
kubectl -nsample apply -f https://raw.githubusercontent.com/istio/istio/1.11.4/samples/sleep/sleep.yaml
通过 sleep 访问外部服务 https://httpbin.org:443, 请求成功:
kubectl -nsample exec sleep-74b7c4c84c-22zkq -- curl -I https://httpbin.org
HTTP/2 200
......
从 access log 确认流量是从 PassthroughCluster 出去,符合预期:
"- - -" 0 - - - "-" 938 5606 1169 - "-" "-" "-" "-" "18.232.227.86:443" PassthroughCluster 172.24.0.10:42434 18.232.227.86:443 172.24.0.10:42432 - -
异常情况
现在 在 default 下创建一个 ExternalName 类型的 Service, 端口也是 443:
kind: Service
apiVersion: v1
metadata:
name: my-externalname
spec:
type: ExternalName
externalName: bing.com
ports:
- port: 443
targetPort: 443
通过 sleep 访问外部服务 https://httpbin.org:443, 请求失败:
kubectl -nsample exec sleep-74b7c4c84c-22zkq -- curl -I https://httpbin.org
curl: (60) SSL: no alternative certificate subject name matches target host name 'httpbin.org'
More details here: https://curl.se/docs/sslcerts.html
......
查看 access log, 发现请求外部服务,被错误路由到了 my-externalname 的 ExternalName Service:
"- - -" 0 - - - "-" 706 5398 67 - "-" "-" "-" "-" "204.79.197.200:443" outbound|443||my-externalname.default.svc.cluster.local 172.24.0.10:56806 34.192.79.103:443 172.24.0.10:36214 httpbin.org -
故障原因
通过对比 sleep Pod 前后两次的 xDS, 发现增加了 ExternalName Service 后,xDS 里会多一个 LDS 0.0.0.0_443
, 该 LDS 包括一个default_filter_chain
会把该 LDS 中其他 filter chain 没有 match 到的流量,都路由到这个 default_filter_chain
中的 Cluster,也就是 my-externalname
对应的 CDS:
解决方案
该问题属于 Istio 实现缺陷,相关 issue: https://github.com/istio/istio/issues/20703
目前的解决方案是避免 ExternalName Service 和其他服务端口冲突。