Service Mesh 服务网格
服务网格(Service Mesh)把服务间通信的治理能力(路由、熔断、限流、鉴权、观测)从业务代码下沉到基础设施层。本文深入 Istio 的架构、Sidecar 注入原理、流量管理、安全与可观测能力,并给出从 Spring Cloud 平滑过渡的方案。
什么是 Service Mesh
演进脉络
服务治理能力的下沉:
单体时代:框架内置(Spring 全家桶)
↓
微服务时代:SDK 嵌入(Spring Cloud 组件)
↓ 痛点:SDK 升级要改业务代码、多语言难统一
服务网格时代:Sidecar 代理(治理能力独立成代理进程)
Service Mesh 的定义:
由专用基础设施层负责服务间通信
可靠、快速、安全的传输交给网格
业务代码不再关心通信治理控制面与数据面
服务网格两大平面:
├─ 数据面(Data Plane):
│ ├─ Sidecar 代理(Envoy)
│ ├─ 部署在业务 Pod 旁边
│ ├─ 处理所有进出流量(转发、策略执行)
│ └─ 高性能:C++ 实现
└─ 控制面(Control Plane):
├─ Istiod(Istio 控制面)
├─ 下发配置(路由、安全、观测规则)
└─ 汇聚数据面指标
数据面负责"执行",控制面负责"决策"一、Sidecar 注入原理
什么是 Sidecar
Sidecar 模式:
├─ 业务容器 + 代理容器共处一个 Pod
├─ 共享网络命名空间(通过 localhost 互通)
├─ iptables 劫持进出流量 → 强制走代理
└─ 业务无感:代码不知道代理存在注入方式
Istio 注入 Sidecar 的两种方式:
├─ 手动注入:
│ istioctl kube-inject -f deployment.yaml > injected.yaml
├─ 自动注入:
│ kubectl label namespace default istio-injection=enabled
│ 命名空间内新建 Pod 时自动注入
└─ 原理:Admission Webhook(MutatingWebhookConfiguration)
在 Pod 创建时修改 Pod 定义,加入 Sidecar 容器流量劫持原理
流量劫持链路:
1. 业务容器请求 order-service:8080
2. iptables 规则(REDIRECT)劫持流量
3. 流量进入 Envoy Sidecar(127.0.0.1:15001)
4. Envoy 按路由规则转发到目标实例
5. 响应原路返回
劫持范围:
├─ 入站流量(Inbound):外部到业务容器的请求
└─ 出站流量(Outbound):业务容器发出的请求Pod 内容器布局
Pod 内多容器(共享网络):
├─ container 1:业务容器(order-service,端口 8080)
├─ container 2:istio-proxy(Envoy,15001/15090)
└─ container 3:istio-init(iptables 初始化,启动即退)
服务发现:
├─ 业务仍注册到 Nacos / 或直接走网格
├─ Sidecar 间通过 mTLS 加密通信
└─ Envoy 通过控制面获得服务端点列表二、流量管理
核心资源
Istio 流量管理资源:
├─ VirtualService:路由规则(权重、条件、重试、超时)
├─ DestinationRule:子集定义、负载均衡、连接池、TLS
├─ Gateway:入口网关(边界代理)
└─ ServiceEntry:网格外服务接入路由与负载均衡
yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: order-service
spec:
hosts:
- order-service
http:
- match: # 条件路由
- headers:
x-env: test
route:
- destination:
host: order-service
subset: canary # 特定子集
- route: # 默认按权重
- destination:
host: order-service
subset: stable
weight: 95
- destination:
host: order-service
subset: canary
weight: 5
timeout: 3s # 超时
retries: # 重试
attempts: 2
perTryTimeout: 1s流量管理能力:
├─ 权重路由(灰度)
├─ 条件路由(Header/Cookie/URI)
├─ 超时与重试(集中配置,无需改代码)
├─ 熔断与连接池(异常实例摘除)
├─ 故障注入(延迟/错误模拟,测试容错)
└─ 镜像流量(复制流量到新版本观察)熔断与连接池
yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: order-service
spec:
host: order-service
trafficPolicy:
connectionPool: # 连接池
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 50
http2MaxRequests: 500
outlierDetection: # 熔断:异常实例摘除
consecutive5xxErrors: 3
interval: 10s
baseEjectionTime: 30s三、安全策略
身份与加密
Istio 安全体系:
├─ 身份:每个服务有 SPIFFE 身份(Service Identity)
├─ 加密:服务间通信默认 mTLS(双向 TLS)
├─ 证书:Istiod 签发并自动轮换(每 24h)
└─ 效果:链路加密 + 身份验证,防中间人
对比:
├─ 传统:应用间明文 HTTP,靠内网隔离
├─ 网格:应用间自动 mTLS,无需改代码
└─ 业务代码完全无感授权策略
yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: order-policy
spec:
selector:
matchLabels:
app: order-service
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/gateway"]
to:
- operation:
methods: ["POST", "GET"]
paths: ["/order/*"]授权能力:
├─ 来源限制:只允许特定服务调用
├─ 操作限制:方法、路径白名单
├─ 条件:时间、Header 等
└─ 拒绝默认(白名单模式)与 Spring Security 的关系
分层安全:
├─ 网格层(Istio):服务间认证与授权(东西向)
├─ 网关层(Gateway):外部入口鉴权
└─ 应用层(Spring Security):业务级 RBAC
分工:
├─ 服务间互信 → Istio mTLS + AuthorizationPolicy
├─ 用户级权限 → Spring Security(业务语义)
└─ 两者互补,不冲突四、可观测性
三大支柱
Istio 可观测性:
├─ 指标(Metrics):
│ ├─ 请求数、错误率、延迟(P50/P90/P99)
│ ├─ 由 Envoy 自动采集(Prometheus)
│ └─ 无需代码埋点
├─ 分布式追踪(Tracing):
│ ├─ 自动生成 Trace(Envoy 注入请求头)
│ ├─ 接入 Jaeger / Zipkin
│ └─ 全链路 Span 无需 SDK
└─ 访问日志(Access Log):
├─ Envoy 记录每次请求的详细日志
└─ 时间、来源、目标、状态、耗时拓扑可视化(Kiali)
Kiali:
├─ 服务拓扑图:实时流量关系
├─ 健康状态:错误率、延迟
├─ 流量详情:请求数、流向
└─ 控制面集成:查看/调试 VirtualService 等
价值:
├─ 一眼看到服务依赖与瓶颈
├─ 灰度过程可视化
└─ 故障定位提速五、与 Spring Cloud 的关系与过渡
能力重叠
Spring Cloud 组件 vs Service Mesh:
├─ Nacos 注册发现 ↔ Istio 服务发现(K8s)
├─ LoadBalancer 负载均衡 ↔ Envoy 负载均衡
├─ Sentinel 熔断限流 ↔ Envoy 熔断连接池
├─ Gateway 网关 ↔ Istio Ingress Gateway
├─ OpenFeign 调用 ↔ Envoy 转发
└─ Spring Security 鉴权 ↔ Istio mTLS + 授权策略
重叠意味着:
├─ 两者可并存(过渡期)
├─ 但能力重复,职责要划清
└─ 最终把通信治理交给网格,SDK 逐步瘦身过渡方案
渐进式过渡路径:
阶段一:并存
├─ 保留 Spring Cloud(Nacos/Feign/Sentinel)
├─ 引入 Istio 只做可观测性与安全(mTLS)
├─ 不动业务代码
└─ 风险最低
阶段二:流量治理下沉
├─ 灰度/熔断/超时改由 Istio 配置
├─ 逐步关闭 SDK 对应能力
└─ 观察业务指标
阶段三:服务发现迁移
├─ 服务发现切到 K8s Service + Istio
├─ Feign 改造为普通 HTTP 客户端
└─ 网关换成 Istio Ingress Gateway
阶段四:全面网格化
├─ 移除 Spring Cloud 通信组件
└─ 仅保留业务代码与配置中心选型判断
何时引入 Service Mesh:
├─ 多语言服务多(网格统一治理)
├─ SDK 升级成本高、版本混乱
├─ 团队有 K8s 基础与运维能力
└─ 需要网格级安全(mTLS)与流量可视化
何时暂缓:
├─ 纯 Java 单一技术栈、Spring Cloud 已够用
├─ 团队无 K8s/网格运维经验
├─ 服务规模小(< 20 个)
└─ 引入成本 > 收益总结
Service Mesh 用 Sidecar 代理 + 集中控制面 把服务治理从 SDK 中解放出来:Envoy 数据面执行流量策略,Istiod 控制面下发规则,mTLS 保障链路安全,指标/追踪/日志自动采集。从 Spring Cloud 过渡的关键是渐进式——先加观测与安全,再下沉流量治理,最后迁移服务发现,每一步都可回退。网格不是银弹,是否引入取决于多语言程度、团队能力与服务规模。