Istio DestinationRule未生效 寻求故障排查方案
Istio DestinationRule 外部服务故障转移不生效问题
问题背景
现有Pod需访问多端点外部服务,已通过Istio实现负载均衡,但配置的DestinationRule故障转移(异常实例驱逐)功能始终不生效。停止其中一个外部实例后,Istio仍持续将请求路由至该失效实例。
相关配置
Kubernetes Service
apiVersion: v1 kind: Service metadata: name: wcf-service namespace: wcf-proxy spec: ports: - name: http port: 80
VirtualService
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: wcf-virtual-service namespace: wcf-proxy spec: hosts: - wcf-service http: - route: - destination: host: 95af-2a02-etc.ngrok-free.app port: number: 80 headers: request: set: Host: 95af-2a02-etc.ngrok-free.app weight: 50 - destination: host: ff25-2a02-etc.ngrok-free.app port: number: 80 headers: request: set: Host: ff25-2a02-etc.ngrok-free.app weight: 50
注:必须设置Host请求头,否则NGrok会因Host头不一致拒绝请求;已通过调整权重验证VirtualService可正常被识别。
ServiceEntry
apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: wcf-service namespace: wcf-proxy spec: hosts: - 95af-2a02-etc.ngrok-free.app - ff25-2a02-etc.ngrok-free.app exportTo: - "*" ports: - number: 80 name: http protocol: HTTP location: MESH_EXTERNAL resolution: DNS
DestinationRule(原无效配置)
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: wcf-destination-rule namespace: wcf-proxy spec: host: wcf-service trafficPolicy: outlierDetection: consecutiveGatewayErrors: 2 consecutive5xxErrors: 2 interval: 10s baseEjectionTime: 2m maxEjectionPercent: 100
测试步骤
- 创建测试Pod(跨命名空间及同命名空间均测试,且两个命名空间均启用Istio注入):
kubectl run my-shell -n blah --rm -i --tty --image curlimages/curl:latest -- sh
- 在Pod内执行请求:
curl -v wcf-service.wcf-proxy.svc.cluster.local
已尝试操作
- 将DestinationRule的
host改为外部服务域名(分别为两个端点创建对应规则),仍未生效 - 执行
istioctl proxy-config route my-shell.blah -o json查看配置,输出中无outlierDetection相关内容
问题原因
- DestinationRule与VirtualService路由目标不匹配:原DestinationRule绑定的是内部K8s Service
wcf-service,但VirtualService直接将流量路由到外部服务域名,而非该K8s Service,导致Istio无法将故障转移策略关联到实际的流量目标。 - 故障策略未绑定到实际外部服务:Istio的DestinationRule需要与VirtualService中
destination.host的目标完全匹配,才能对该目标服务应用故障转移规则。
解决方法
方案1:为每个外部服务域名配置独立DestinationRule
修改VirtualService(优化Host头设置),并为每个外部服务创建对应的DestinationRule:
修改后的VirtualService
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: wcf-virtual-service namespace: wcf-proxy spec: hosts: - wcf-service http: - route: - destination: host: 95af-2a02-etc.ngrok-free.app port: number: 80 weight: 50 - destination: host: ff25-2a02-etc.ngrok-free.app port: number: 80 weight: 50 headers: request: set: Host: "%UPSTREAM_HOST%" # 自动填充目标服务域名,无需手动配置
针对第一个外部服务的DestinationRule
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: wcf-outlier-95af namespace: wcf-proxy spec: host: 95af-2a02-etc.ngrok-free.app trafficPolicy: outlierDetection: consecutiveGatewayErrors: 2 consecutive5xxErrors: 2 interval: 10s baseEjectionTime: 2m maxEjectionPercent: 100
针对第二个外部服务的DestinationRule
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: wcf-outlier-ff25 namespace: wcf-proxy spec: host: ff25-2a02-etc.ngrok-free.app trafficPolicy: outlierDetection: consecutiveGatewayErrors: 2 consecutive5xxErrors: 2 interval: 10s baseEjectionTime: 2m maxEjectionPercent: 100
方案2:通过ServiceEntry统一管理外部服务并绑定策略
如果需要统一管理外部服务,可将VirtualService路由指向ServiceEntry的服务,再为ServiceEntry配置DestinationRule:
修改后的VirtualService
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: wcf-virtual-service namespace: wcf-proxy spec: hosts: - wcf-service http: - route: - destination: host: wcf-service # 匹配ServiceEntry的host字段 port: number: 80
对应DestinationRule
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: wcf-service-entry-dr namespace: wcf-proxy spec: host: wcf-service # 匹配ServiceEntry的host字段 trafficPolicy: outlierDetection: consecutiveGatewayErrors: 2 consecutive5xxErrors: 2 interval: 10s baseEjectionTime: 2m maxEjectionPercent: 100
验证操作
- 重新部署所有配置:
kubectl apply -f <配置文件路径> -n wcf-proxy
- 刷新Sidecar配置:
istioctl proxy-config refresh my-shell.blah
- 再次执行测试,停止其中一个外部实例,观察是否在2次错误后停止路由至失效实例。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

