在GKE中使用Istio按客户端IP分流应用版本的问题求助
基于Istio的按客户端IP分流方案修复
核心问题排查
- 真实客户端IP获取
Istio IngressGateway本身支持获取真实客户端IP,但需注意:
- 若使用云厂商LoadBalancer,必须开启客户端IP透传(如AWS NLB开启
preserve_client_ip,阿里云SLB开启“获取真实IP”) x-forwarded-for头部可能包含多层代理IP,格式为客户端IP, 代理1IP, 代理2IP,需提取第一个值作为真实IP
- Lua脚本缺陷
原脚本存在两个关键问题:
- 未处理
x-forwarded-for的多IP场景,直接取值可能拿到错误的IP - 使用
add方法会重复添加x-destination-version头部,导致匹配异常
修正后的配置
EnvoyFilter(修复IP识别与Header设置)
apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: filter-by-ip namespace: sn-backend spec: workloadSelector: labels: istio: ingressgateway configPatches: - applyTo: HTTP_FILTER match: context: GATEWAY listener: filterChain: filter: name: "envoy.filters.network.http_connection_manager" patch: operation: INSERT_BEFORE value: name: envoy.lua typed_config: "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua" inlineCode: | function envoy_on_request(request_handle) -- 优先从x-forwarded-for取真实IP,处理多代理场景 local xff = request_handle:headers():get("x-forwarded-for") local client_ip = xff and xff:match("^[^,%s]+") or request_handle:connection():remoteAddress():ip() request_handle:logInfo("Processing request from IP: " .. client_ip) -- 白名单IP集合,可添加多个测试IP local whitelist = { "<REDUCTED_IP>" } for _, allowed_ip in ipairs(whitelist) do if client_ip == allowed_ip then request_handle:headers():replace("x-destination-version", "v2") request_handle:logInfo("Matched whitelist, routing to v2") return end end -- 默认设置为v1,确保header存在 request_handle:headers():replace("x-destination-version", "v1") end
VirtualService(保持原有逻辑,优化权重配置)
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: nginx-router namespace: sn-backend spec: hosts: - "domain.example.com" gateways: - httpbin-gateway http: - match: - headers: x-destination-version: exact: "v2" route: - destination: host: httpbin1.sn-backend.svc.cluster.local port: number: 8000 weight: 100 - route: - destination: host: httpbin.sn-backend.svc.cluster.local port: number: 8000 weight: 100
Gateway(无需修改,保持原配置)
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: httpbin-gateway namespace: sn-backend spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "domain.example.com"
验证步骤
- 查看IngressGateway日志确认IP识别:
kubectl logs -n istio-system $(kubectl get pods -n istio-system -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -c istio-proxy | grep "Processing request from IP" - 用非白名单IP测试:
curl -H "Host: domain.example.com" <你的LoadBalancerIP>,确认路由到V1 - 用白名单IP测试:
curl -H "Host: domain.example.com" <你的LoadBalancerIP>,确认路由到V2
内容的提问来源于stack exchange,提问作者Semen Kolesnikov
相关产品推荐
相关产品推荐

