Istio Egress配置外部HTTPS代理无效,流量未走代理问题求助
Kubernetes中的Node.js应用支持HTTPS_PROXY环境变量,但不支持NO_PROXY,需仅让特定站点的流量通过外部代理转发。用户部署Istio Egress的命令如下:
istioctl install --set profile=minimal \ --set values.pilot.env.PILOT_ENABLE_ALPHA_GATEWAY_API=true \ --set meshConfig.accessLogFile=/dev/stdout \ --set "components.egressGateways[0].name=istio-egressgateway" \ --set "components.egressGateways[0].enabled=true" \ --set meshConfig.outboundTrafficPolicy.mode=ALLOW_ANY
随后应用了测试流量路由至维基百科的清单:
--- apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: external-proxy spec: hosts: - proxyext.external.site.local ports: - number: 3128 name: http protocol: HTTP location: MESH_EXTERNAL --- apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: route-to-proxy spec: hosts: - api.google.com - api.usa.com - someother.site.com - en.wikipedia.org http: - match: - port: 443 route: - destination: host: proxyext.external.site.local port: number: 3128 apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: route-to-proxy spec: gateways: - external-proxy-gw hosts: - \"*\" tls: - match: - gateways: - external-proxy-gw port: 443 sniHosts: - en.wikipedia.org route: - destination: host: proxyext.external.site.local port: number: 3128 weight: 100 --- apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: external-proxy-gw spec: selector: istio: egressgateway servers: - port: number: 443 name: tls protocol: TLS hosts: - en.wikipedia.org tls: mode: PASSTHROUGH
测试时从容器内使用curl访问en.wikipedia.org,流量未经过配置的外部代理而是直接转发,istio-proxy侧容器日志如下:
[2024-04-16T07:29:51.116Z] "- - -" 0 - - - "-" 813 110483 535 - "-" "-" "-" "-" "185.15.59.224:443" outbound|443||en.wikipedia.org 10.233.103.2:32854 185.15.59.224:443 10.233.103.2:32838 en.wikipedia.org -
1. 重复定义同名VirtualService
清单里存在两个metadata.name=route-to-proxy的VirtualService资源,Kubernetes会自动覆盖后创建的实例,导致第一个针对HTTP流量的路由配置完全失效,同时打乱了TLS路由的规则逻辑。
修正:给两个VirtualService设置不同的名称,比如分别命名为route-to-proxy-http和route-to-proxy-tls,避免资源冲突。
2. HTTP类型VirtualService的匹配逻辑无效
第一个VirtualService试图匹配443端口的HTTP流量并转发到代理,但实际访问en.wikipedia.org:443是TLS加密流量,Istio会将其识别为TLS类型而非HTTP,因此这个匹配规则永远不会触发。
修正:针对HTTPS站点的代理转发,应使用TLS类型的路由配置,无需保留这个无效的HTTP类型VirtualService。
3. TLS类型VirtualService未覆盖网格内流量
当前TLS类型VirtualService的gateways字段仅指定了external-proxy-gw,没有包含mesh网关(代表网格内Pod发起的流量),导致网格内应用的出站流量不会被这个路由规则匹配,直接走ALLOW_ANY策略直接出站。
修正:调整TLS类型VirtualService的配置,添加mesh网关并明确目标主机:
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: route-to-proxy-tls spec: gateways: - mesh - external-proxy-gw hosts: - en.wikipedia.org tls: - match: - gateways: - mesh port: 443 sniHosts: - en.wikipedia.org route: - destination: host: proxyext.external.site.local port: number: 3128 weight: 100
4. 代理ServiceEntry的协议适配(补充说明)
当前ServiceEntry为代理配置了HTTP协议的3128端口,这符合常见HTTP代理的配置(支持CONNECT方法中转TLS流量),但需要确认你的外部代理确实支持通过3128端口处理HTTPS流量的中转。如果代理要求使用HTTPS连接,需要补充TLS端口的配置,但这不是当前流量未走代理的直接原因。
5. 日志验证依据
从istio-proxy的日志可以看到,流量直接转发到了en.wikipedia.org的真实IP185.15.59.224:443,说明Istio没有触发到代理的路由规则,核心原因就是上述VirtualService的配置错误导致规则未生效。
内容的提问来源于stack exchange,提问作者yoshi kakbudto

