前言
微服务多了,治理需求爆炸:灰度、熔断、重试、加密、链路追踪……把这些能力从业务代码里抽出来下沉到基础设施,就是服务网格(Service Mesh)。Istio 是这个领域的事实标准。
一、为什么需要服务网格
没有网格: 有网格:
┌────────────┐ ┌────────────┐
│ 业务代码 │ │ 业务代码 │ ← 只关心业务
│ + 重试逻辑 │ ├────────────┤
│ + 熔断逻辑 │ │ Envoy代理 │ ← 重试/熔断/加密
│ + 加密代码 │ │ (sidecar) │ 全在这里
│ + 追踪埋点 │ └────────────┘
└────────────┘
框架SDK耦合: 换语言=重写治理 多语言天然统一, 业务零侵入
核心机制:Sidecar 模式——每个 Pod 注入一个 Envoy 代理容器,进出 Pod 的所有流量都被它劫持:
# 注入后看 Pod
kubectl get pods
# api-7d9f6c-x2v4x 2/2 Running ← 2 个容器 = 业务 + istio-proxy
kubectl exec -it api-xxx -c istio-proxy -- pilot-agent version
二、架构与安装
┌─ 控制面 istiod ──────────────┐
│ 配置下发(xDS) + 证书签发(CA) │──► 所有 Envoy
└──────────────────────────────┘
数据面: 每个 Pod 里的 Envoy ↔ 组成服务间通信的实际通路
# 安装(国内镜像)
curl -L https://istio.io/installIstio | ISTIO_VERSION=1.23.0 sh -
export PATH=$PATH:$(pwd)/istio-1.23.0/bin
istioctl install --set profile=demo -y
# 给 namespace 打标签, 新 Pod 自动注入 sidecar
kubectl label namespace prod istio-injection=enabled
kubectl rollout restart deploy/api -n prod # 重启生效
# 验证
istioctl proxy-status
三、流量管理:网格的看家本领
VirtualService:路由规则
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: api
spec:
hosts: [api]
http:
- match:
- headers: {x-canary: {exact: "true"}} # 按请求头路由
route:
- destination: {host: api, subset: v2}
- route:
- destination: {host: api, subset: v1}
weight: 95 # 默认流量 95% 走 v1
- destination: {host: api, subset: v2}
weight: 5 # 5% 灰度 v2
DestinationRule:定义版本与策略
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: api
spec:
host: api
subsets:
- name: v1
labels: {version: v1}
- name: v2
labels: {version: v2}
trafficPolicy:
connectionPool:
tcp: {maxConnections: 100}
outlierDetection: # 熔断: 连续5次5xx则踢出30秒
consecutive5xxErrors: 5
interval: 10s
baseEjectionTime: 30s
金丝雀发布全流程(对应 CI/CD 篇的策略):
kubectl apply -f dr.yaml # v1/v2 subset 就位
kubectl apply -f vs-5.yaml # 5% → v2
# 观察错误率/延迟 → OK
kubectl apply -f vs-50.yaml # 50%
kubectl apply -f vs-100.yaml # 全量
# 出问题? vs-0.yaml 一键回 0(秒级, 不用动 Deployment)
四、弹性能力:重试与超时
http:
- route: [{destination: {host: api}}]
timeout: 2s # 请求级超时
retries:
attempts: 3
perTryTimeout: 500ms
retryOn: "5xx,reset,connect-failure" # 只重试幂等可重试错误
治理能力完全 YAML 化——改重试策略不用改代码发版,这是网格相对 SDK 的本质优势。
五、安全:mTLS 零改造加密
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system # 全网格生效
spec:
mtls: {mode: STRICT} # 服务间通信强制双向TLS
# 验证: 抓包看到的全是 TLS
istioctl x authn check api.xxx
# 控制谁能访问谁(L7 授权)
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: api-only-from-gateway
namespace: prod
spec:
selector: {matchLabels: {app: api}}
action: ALLOW
rules:
- from: [{source: {principals: ["cluster.local/ns/istio-system/sa/istio-ingressgateway"]}}]
六、可观测性:开箱即用的黄金指标
装上 Kiali(拓扑图)+ 内置的指标上报(Prometheus 格式):
kubectl apply -f samples/addons/kiali.yaml
kubectl apply -f samples/addons/prometheus.yaml
# 访问 Kiali: 服务拓扑、流量动画、错误率一目了然
# istioctl 也能直接查
istioctl x describe pod api-xxx # 这个Pod的配置/证书状态
Envoy 自动上报请求级指标(成功率/延迟/p200…)——微服务监控从"进程级"升到"服务调用级"。
七、代价:不是免费的午餐
| 代价 | 说明 |
|---|---|
| 延迟 | 每跳多经过两层代理(客户端+服务端 sidecar),P99 增加约 1~3ms |
| 资源 | 每个 Pod 多一个容器(内存 ~100MB 起),百 Pod 规模=一台节点的开销 |
| 复杂度 | 排障链路多了一层(istioctl proxy-status/log 是新必修课) |
什么时候值得上:
- ✅ 微服务 > 20 个、多语言并存、有专职平台团队
- ✅ 强合规要求(全链路 mTLS、审计)
- ⚠️ 几个服务的中小团队:K8s 原生 + 网关层治理先够用,别为简历上网格
八、排障速查
istioctl proxy-status # 所有 sidecar 同步状态
istioctl proxy-config routes api-xxx # 查看生效的路由(vs没生效先看这!)
istioctl proxy-config cluster api-xxx
kubectl logs api-xxx -c istio-proxy --tail=50
# 常见坑
sidecar 没注入 → namespace label + 重启 Pod
503 no healthy upstream → subset label 不匹配 / 探针失败
路由规则不生效 → hosts 写错(短名/FQDN)、DR/VS 顺序
UDP/特殊协议不通 → 网格默认代理 TCP, 例外要显式配置
小结
| 概念 | 作用 |
|---|---|
| Sidecar (Envoy) | 劫持进出流量, 承载全部治理 |
| istiod | 控制面: 配置下发 + 证书 |
| VirtualService | 怎么路由(灰度/分流/匹配) |
| DestinationRule | 到哪里去(版本/连接池/熔断) |
| PeerAuthentication | mTLS 加密 |
| AuthorizationPolicy | 服务级授权 |
本文是「云原生」系列第 16 篇。