Istio 服务网格流量管理

FreeGuideOnline 最新 2026-07-01

yaml apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews spec: hosts:

  • reviews http:
  • match:
    • uri: prefix: "/" route:
    • destination: host: reviews subset: v1 weight: 80
    • destination: host: reviews subset: v2 weight: 20

在这个例子中,需要配合 DestinationRule 来定义 `v1` 和 `v2` 子集。

### DestinationRule(目标规则)

DestinationRule 定义了流量到达某个服务后,针对不同版本的子集(subset)的策略,比如负载均衡算法、连接池大小、熔断阈值、TLS 模式等。

**关键字段:**

- `host`:目标服务,通常与 VirtualService 中的 host 相同。
- `subsets`:基于标签(labels)定义的版本分组。每一个 subset 对应一组具有相同标签的 Pod。
- `trafficPolicy`:全局或针对特定子集的流量策略(负载均衡、连接池、异常检测等)。

**示例:定义 reviews 服务的两个子集,并指定负载均衡策略**

```yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        http1MaxPendingRequests: 10
        http2MaxRequests: 100
        maxRequestsPerConnection: 2
    outlierDetection:
      consecutiveErrors: 5
      interval: 30s
      baseEjectionTime: 60s

当 VirtualService 中引用了 subset: v1 时,请求会被转发到携带 version: v1 标签的 Pod 上。

Gateway(网关)

Gateway 用于管理进出服务网格的边界流量,通常对应 Ingress 流量(从外部访问网格内部),但也可用于 Egress。

它运行在网格边缘的 Envoy 代理上,用于配置暴露的端口、协议和 TLS 设置。真正的流量路由规则仍然写在 VirtualService 中,并通过 gateways 字段绑定。

Gateway + VirtualService 结合实现外部入口:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: my-gateway
spec:
  selector:
    istio: ingressgateway # 使用默认 Ingress Gateway 的 Pod 标签
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "example.com"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: my-app-external
spec:
  hosts:
  - "example.com"
  gateways:
  - my-gateway
  http:
  - route:
    - destination:
        host: my-service.default.svc.cluster.local
        port:
          number: 8080

ServiceEntry(服务入口)

Istio 通过内部服务注册表感知网格内部服务,如果需要访问网格外部服务(如外部 API、数据库),可以使用 ServiceEntry 将外部服务注册进来,以便对出流量进行治理。

这在使用 External API 并需要为其配置超时、重试规则时非常有用,也是很多初学者容易忽略的地方。

高级流量管理场景

基于请求内容的路由(内容路由)

你可以根据 HTTP Header、URI、Query Params 等匹配规则将请求路由到不同版本。最常见的场景是 A/B 测试或基于用户类型的分流。

http:
- match:
  - headers:
      end-user:
        exact: "internal"
  route:
  - destination:
      host: reviews
      subset: v3
- route:
  - destination:
      host: reviews
      subset: v1

上述规则表示:如果请求头 end-user 的值为 internal,则将流量发送到 v3 版本,否则全部默认进入 v1。

流量镜像(Traffic Mirroring)

流量镜像(又称流量影子)能够把实时请求复制一份发送到另一个服务版本,但不影响主请求的响应。常用于将生产流量导入测试版本来验证新功能。

在 VirtualService 中使用 mirror 字段:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 100
    mirror:
      host: reviews
      subset: v2

这里所有请求 100% 发往 v1,同时会镜像一份到 v2(v2 的响应会被丢弃)。

故障注入(Fault Injection)

Istio 可以主动注入延迟(delay)或中断(abort)来测试服务的弹性。无需修改代码,只在 VirtualService 中配置即可。

注入 5 秒延迟给 10% 的请求:

http:
- fault:
    delay:
      percentage:
        value: 10
      fixedDelay: 5s
  route:
  - destination:
      host: reviews
      subset: v1

注入 HTTP 503 错误:

- fault:
    abort:
      percentage:
        value: 20
      httpStatus: 503

超时、重试与熔断

请求超时(Timeout)

在 VirtualService 的路由规则中指定 HTTP 请求的超时时间(默认 15 秒)。超时发生后,Envoy 会返回 504 Gateway Timeout,可以用来防止下游服务慢响应耗尽资源。

http:
- timeout: 2s
  route:
  - destination:
      host: reviews
      subset: v1

重试(Retries)

当目标服务返回特定错误时,Envoy 可以自动发起重试。配置重试次数、重试条件以及每次重试的超时时间。

http:
- retries:
    attempts: 3
    perTryTimeout: 1s
    retryOn: "connect-failure,refused-stream,503"
  route:
  - destination:
      host: reviews
      subset: v1

retryOn 可以使用 Istio 支持的策略条件组合。

熔断(Circuit Breaking)

熔断在 DestinationRule 中配置,通过连接池和异常检测参数来限制并发连接或请求数,并在一段时间内将不健康的主机剔除。

上面 DestinationRule 示例中的 connectionPooloutlierDetection 就是典型的熔断配置。异常检测(outlier detection)会根据连续错误数触发暂时移出主机池,类似于 Hystrix 的断路器模式。

常用异常检测参数:

  • consecutive5xxErrors:连续 5xx 错误次数
  • interval:扫描间隔
  • baseEjectionTime:最小驱逐时间
  • maxEjectionPercent:最大可驱逐主机百分比

实际场景演示:金丝雀发布

假设我们有一个 productpage 服务的新版本 v2 需要逐步上线,流程如下:

  1. productpage 创建 DestinationRule,定义 v1v2 两个 subset。
  2. 首先通过 VirtualService 将所有流量指向 v1。
  3. 修改 VirtualService,将 5% 流量转移到 v2,观察指标。
  4. 逐步增加权重直至 100%,完成发布。
  5. 如果发现问题,立即将权重恢复至 v1,完成回滚。

对应的 VirtualService 逐步修改:

# 仅 v1
http:
- route:
  - destination:
      host: productpage
      subset: v1
    weight: 100

# 5% 灰度
http:
- route:
  - destination:
      host: productpage
      subset: v1
    weight: 95
  - destination:
      host: productpage
      subset: v2
    weight: 5