前置知识: 云计算

服务网格

6 min高级

服务网格原理与选型:Sidecar 与 ambient 两种数据面、Istio 流量管理/安全/可观测、Linkerd 对比。

前置知识与学习目标

微服务数量一多,三类问题会在每个服务里重复出现:重试/超时/熔断怎么 写、服务间调用怎么加密、调用链怎么追踪。传统做法是把这些逻辑塞进各语言 的 SDK(如 Spring Cloud)——多语言团队要维护 N 份实现,库升级要推动 N 个 应用重发版。

服务网格(Service Mesh)把这三类逻辑从应用代码里抽出来,下沉为基础 设施层:应用只管业务,流量治理由网络旁的代理完成。类比:SDK 方案是 「每家自己雇保安」,网格是「小区统一安保」。

完成本文后,你应当能够:说清 Sidecar 与 ambient 两种数据面的取舍; 读懂 Istio 的 VirtualService/DestinationRule/安全策略;判断自己的系统 是否真的需要网格。

1. 服务网格概述

1.1 架构模式

flowchart TD
    CP[控制平面<br/>配置分发、证书管理、策略编译]
    S1[数据面代理<br/>Service A 旁]
    S2[数据面代理<br/>Service B 旁]
    CP -->|配置/证书| S1
    CP -->|配置/证书| S2
    S1 <-->|业务流量| S2

关键原则:流量永远经过代理,代理由控制平面统一编程。应用无感知 (代码零改动),治理策略集中在 YAML 里声明。

1.2 核心功能

功能描述
流量管理路由、按权重分流、重试、超时
安全mTLS 自动加密、服务级认证授权
可观测性每个 hop 的指标、日志、追踪
弹性熔断、限流、故障注入

2. Istio

Istio 是事实上的主流方案(撰写时最新为 1.3x 系列,约每季度一个次版本)。

2.1 两种数据面:Sidecar 与 ambient

Sidecar 模式(经典):每个 Pod 注入一个 Envoy 代理容器,接管全部 进出流量。优点是隔离好、策略细;代价是资源翻倍(每 Pod 多 0.1-0.5 核 量级内存开销)、升级网格要重启全部业务 Pod、注入顺序引发启动竞态。

ambient 模式(Istio 1.24 起 GA,现行主推):代理下沉到节点级:

  • ztunnel:每节点一个的 Rust 隧道,负责 L4 的 mTLS 加密与 TCP 路由;
  • waypoint:按需部署的 L7 代理,只有需要七层策略(HTTP 路由、鉴权) 的命名空间才部署。
维度Sidecarambient
资源开销每 Pod 一份节点级共享,显著更低
应用侵入性需注入/重启命名空间打标签即接入
L7 能力默认全量按需(waypoint)
成熟度长期生产验证GA 后快速增长期

新集群建议默认评估 ambient;已有大规模 Sidecar 部署不必为迁移而迁移。

2.2 控制平面与流量管理

控制平面 istiod(合并了早期的 Pilot/Citadel/Galley):配置分发 + 证书签发(每个工作负载一个短生命周期 SPIFFE 身份)。

流量管理的核心是两个 CRD 的分工:VirtualService 管「怎么路由」, DestinationRule 管「目标长什么样」(子集、负载均衡、熔断);南北向 入口流量再叠加 Gateway CRD:

# VirtualService:按头匹配走 v2,其余按 90/10 分流
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts: [reviews]
  http:
    - match:
        - headers:
            x-user-type:
              exact: premium
      route:
        - destination: {host: reviews, subset: v2}
    - route:
        - destination: {host: reviews, subset: v1}
          weight: 90
        - destination: {host: reviews, subset: v2}
          weight: 10
# DestinationRule:定义 v1/v2 子集(对应 Pod 标签)与熔断
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  trafficPolicy:
    connectionPool:
      tcp: {maxConnections: 100}
    outlierDetection:            # 连续 5xx 熔断摘除
      consecutive5xxErrors: 5
      interval: 30s
      baseEjectionTime: 30s
  subsets:
    - name: v1
      labels: {version: v1}
    - name: v2
      labels: {version: v2}

2.3 安全策略

# PeerAuthentication:命名空间级强制 mTLS(明文流量被拒)
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
  namespace: istio-system
spec:
  mtls: {mode: STRICT}
# AuthorizationPolicy:L7 级授权——只有 web 服务账号能 GET/POST /api/*
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: api-access
spec:
  selector:
    matchLabels: {app: api}
  rules:
    - from:
        - source:
            principals: ['cluster.local/ns/default/sa/web']
      to:
        - operation:
            methods: ['GET', 'POST']
            paths: ['/api/*']

mTLS 的真正价值:证书签发与轮换全自动(应用零配置),身份绑定到服务 账号而非网络位置——这是零信任网络在 K8s 里的落地形态。

2.4 可观测性

网格代理在每个 hop 自动产出 RED 指标(速率/错误/延迟)与追踪 span:

组件功能
Prometheus指标收集
Grafana指标可视化
Jaeger分布式追踪
Kiali服务拓扑图

无需应用改代码即可获得全链路指标——这是网格最「回本」的能力。

3. Linkerd

特点描述
轻量级Rust 实现的 linkerd2-proxy
简单最小化配置、默认可用
自动 mTLS默认启用
对比项IstioLinkerd
代理Envoy (C++)linkerd2-proxy (Rust)
复杂度高(功能面广)低(克制)
L7 扩展故障注入/复杂匹配等核心路由功能
资源消耗ambient 后差距缩小Sidecar 模式下更低
适用大规模、复杂策略快速落地、运维有限

选型本质:Linkerd 是「把 80% 的网格价值(mTLS/重试/指标)用 20% 的复杂度 给你」;Istio 是「全功能但要先养一个平台团队」。

4. 流量管理三场景

4.1 金丝雀发布

# 90% v1 / 10% v2,观测错误率后逐步调整 weight
apiVersion: networking.istio.io/v1
kind: VirtualService
spec:
  http:
    - route:
        - destination: {host: myapp, subset: v1}
          weight: 90
        - destination: {host: myapp, subset: v2}
          weight: 10

配合自动化(Argo Rollouts/Flagger)可将「调权重」变成指标驱动的 自动推进/自动回滚。

4.2 故障注入(混沌工程)

# 10% 的请求注入 500ms 延迟,验证上游的超时与降级
apiVersion: networking.istio.io/v1
kind: VirtualService
spec:
  http:
    - fault:
        delay:
          percentage: {value: 10}
          fixedDelay: 500ms
      route:
        - destination: {host: myapp}

4.3 重试与超时

apiVersion: networking.istio.io/v1
kind: VirtualService
spec:
  http:
    - route:
        - destination: {host: myapp}
      retries:
        attempts: 3
        perTryTimeout: 2s
        retryOn: 5xx,reset,connect-failure
      timeout: 10s        # 整体预算,避免重试放大

陷阱:重试会放大流量(3 次重试 = 最坏 4 倍请求)。必须同时设置 perTryTimeout 与整体 timeout,且只对幂等操作或幂等化后的接口 启用重试,否则会产生重复写入。

5. 何时不要上服务网格

网格的收益必须大于其成本(复杂度 + 排错成本 + 资源开销)。以下情况 建议缓行:

信号更轻的替代
服务数 < 10、单体为主K8s 原生 Service + Ingress
只想要 mTLSCilium eBPF 透明加密 / ambient ztunnel
只想要金丝雀Ingress 权重 / Argo Rollouts
团队无专职平台人员Linkerd 而非 Istio 全家桶

务实的演进路径:先用 K8s 原生能力,等服务间治理需求(统一 mTLS、 精细化灰度、全链路策略)真实出现时,再以 ambient 或 Linkerd 低成本接入。

小结

  • 初学者要点:网格 = 把流量治理从 SDK 下沉到代理基础设施;三大能力是 流量管理、mTLS、可观测;Istio 由 istiod(控制面)+ Envoy/ztunnel (数据面)组成;VirtualService 管路由、DestinationRule 管目标策略。
  • 进阶注意:Sidecar 模式有真实的每 Pod 资源税与升级重启成本;ambient 自 1.24 GA,以节点级 ztunnel + 按需 waypoint 重构了成本模型;重试 必须配超时预算并保证幂等;要不要上网格先问「现有需求能否用 Ingress + Argo Rollouts 解决」;微服务规模超过约 20-50 个时,网格的投资回报 才开始清晰。