服务Mesh和流量策略
1)为什么需要Service Mesh
Service Mesh是用于东西方流量(服务间通信)的基础架构层,可在不重写代码的情况下提供统一的功能:- 默认安全性:mTLS,自动签发/轮换证书,服务标识。
- 流量策略:L7路由,金丝雀/AV测试,退化和可持续性。
- 可观察性:度量,逻辑,跟踪,每个呼叫中的黄金信号。
- 操作:所有语言/框架的统一策略。
与API网关的区别:网关是南北外围;mesh是集群/组织内的东西方。经常一起工作。
2)体系结构: 平面和模式
Data Plane: sidecar代理(Envoy/Linkerd-proxy/haproxy),拦截poda/VM流量。
控制平面:分配配置(路由、策略、证书)、存储状态、发布服务折扣。
身份:通常是SPIFFE ID和自动X.509证书(SPIRE/嵌入式 CA)。
入口/出口点:ingress/egress-gateway用于边界流控制。
实施模式:每个下方的sidecar;新实现中的节点/环境模式。
3)安全政策与零信任
1.mTLS by default:加密和相互验证servis↔servis。
2.AuthN/AuthZ:
AuthN:我们只信任CA mesh'a(SPIFFE)签发的身份。
AuthZ:声明规则"谁可以成为谁"(RBAC/ABAC)。
3.隔离和egress控制:
允许的域/子网;通过egress-gateway强制退出。
阻止pod的直接结果。
4.秘密轮换:短寿命证书,自动代理重新配置。
Istio(示例:全局mTLS严格):yaml apiVersion: security. istio. io/v1beta1 kind: PeerAuthentication metadata: { name: default, namespace: istio-system }
spec:
mtls: { mode: STRICT }
Istio(示例:仅允许gRPC上的inventory→billing):
yaml apiVersion: security. istio. io/v1beta1 kind: AuthorizationPolicy metadata: { name: billing-allow, namespace: prod }
spec:
selector: { matchLabels: { app: billing } }
rules:
- from:
- source: { principals: ["spiffe://corp. local/ns/prod/sa/inventory"] }
to:
- operation: { ports: ["8080"], methods: ["POST"], paths: ["/proto. Billing/"] }
4)流量策略: 可持续性和路由
4.1 Taymauts和retrai
Timeouts:一定要调用(connect/read/overall)。
Retries:仅用于等效操作;backoff+jitter;超时限制。
Istio (VirtualService):
yaml apiVersion: networking. istio. io/v1beta1 kind: VirtualService metadata: { name: orders }
spec:
hosts: ["orders"]
http:
- route:
- destination: { host: orders, subset: v1, port: { number: 8080 } }
timeout: 5s retries:
attempts: 2 perTryTimeout: 2s retryOn: "5xx,connect-failure,reset"
4.2 Circuit Breaker и outlier detection
CB:通过保护apstrims来限制同时查询/连接。
Outlier:推翻错误/潜伏的"坏"实例。
Istio (DestinationRule):
yaml apiVersion: networking. istio. io/v1beta1 kind: DestinationRule metadata: { name: orders }
spec:
host: orders trafficPolicy:
connectionPool:
http: { http1MaxPendingRequests: 1024, maxRequestsPerConnection: 100 }
outlierDetection:
consecutive5xxErrors: 5 interval: 5s baseEjectionTime: 30s maxEjectionPercent: 50
4.3金丝雀和按条件
重量:按权重v1/v2划分流量。
基于头部:标志/cookie/tenant →滚动到新版本。
Session affinity:按键哈希(整齐缩放)。
yaml http:
- match: [{ headers: { "x-experiment": { exact: "new" } } }]
route: [{ destination: { host: orders, subset: v2 } }]
- route:
- destination: { host: orders, subset: v1, weight: 90 }
- destination: { host: orders, subset: v2, weight: 10 }
4.4 Fault Injection和退化
为稳定性测试和SLO注入延迟/错误。
yaml fault:
delay: { fixedDelay: 300ms, percentage: { value: 10 } }
abort: { httpStatus: 503, percentage: { value: 1 } }
5)网络边界: ingress/egress和外部服务
Ingress-gateway:mesh中外部客户的唯一切入点;与WAF/OIDC/ratelimits集成。
Egress-gateway:带有允许主机列表的中央出口,TLS检查,遥测记录。
ServiceEntry:将外部SNI/主机声明为 mesh的一部分(策略和mTLS起源适用)。
yaml apiVersion: networking. istio. io/v1beta1 kind: ServiceEntry metadata: { name: payments-external }
spec:
hosts: ["api. payments. com"]
ports: [{ number: 443, name: https, protocol: TLS }]
resolution: DNS location: MESH_EXTERNAL
6)多群集,多网络和混合体
通用PKI/托管域:群集之间的单个SPIFFE身份。
端点发现:区域之间的服务球;本地优先级和failover。
区域隔离:区域政策、限制和优先事项。
Mesh中的VM:将传统/静态系统连接到代理和相同的策略。
7)可观察性,SLO和操作
Метрики: `requests_total`, `request_duration_ms{p50,p95,p99}`, `5xx_rate`, `retry_attempts`, `cb_state`, `mTLS_authz_denied`.
访问日志:结构性,带有"traceparent"、"user/tenant"、"response_flags"。
Tracing:自动标头注入(W3C Trace Context), sampling,在hop级别上演唱。
SLO:p99目标/路线错误(service→service)。
Alerts: "5xx"激增、"reset"增长、"outlier_ejections"、mTLS降解(handshake failures)。
8)生产力和成本
Sidecar添加开销(CPU/RAM/latency)。我们优化:- 颗粒性:在需要的地方纳入政策;不包括任何地方的重型过滤器。
- 池:将路径(临界/背景)分为不同的路线和限制。
- 剖析:"冷"路线上的p99,遥测量(rate-limit log/trays)。
- 如果支持并且符合要求,请考虑环境/无障碍模式。
9)安全和合规性
最起码的访问:明确允许方向和方法。
Neimspace/tenant策略:网络/授权边界。
钥匙轮换/SA:计划和紧急情况;TTL证书短。
PII/秘密:在日志/预告片中掩盖;电线/静止加密。
审计:谁改变了政策,何时改变了政策;两步的启示。
10)与K8S级集成
Mesh策略是对NetworkPolicy的补充而不是替代。
在ingress/egress-gateway中,可以将PodSecurity/PSA挂在下面的级别。
NRA/自动滑行:考虑回程/SV-它们改变负载。
发布计划:通过VirtualService+自动升级到SLO的金丝雀权重。
11)实施支票
- 已定义信任边界并启用STRICT mTLS。
- 包括AuthZ策略:谁在谁,在哪个端口/方法上。
- 定制timeouts/retries和outlier检测,定义了偶数路径。
- 规定了金丝雀路线和滚回计划;fault injection-仅在非程序中。
- 通过egress-gateway和ServiceEntry进行外部依赖。
- 设置指标,标志,路线;dashbords和alertes在p99/5xx/CB。
- 规定了per-tenant/namespace配额/限额。
- 准备运行手册:证书泄漏,CA故障,apstrim降解,质量503/RESET。
- 多类计划(通用PKI,本地优先级,DR脚本)。
- 测试日(游戏日):控制平面下降,中途停止,网络破裂,"有毒"消失。
12)反模式
Mesh"无处不在",没有路线清单,SLO →昂贵的复杂性。
默认情况下,retrai用于→效果和流量雪崩。
断开连接的mTLS"暂时"→永远存在。
没有网关的Egress →数据泄漏/未报告的依赖关系。
所有服务的一个全球政策→假安全和假阳性。
零观察力:打开了mesh,但我们没有收集指标/步伐-我们失去了意义。
13)快速食谱
Linkerd: 启用mTLS和跨服务器的策略
yaml apiVersion: policy. linkerd. io/v1beta1 kind: Server metadata: { name: billing, namespace: prod }
spec:
podSelector: { matchLabels: { app: billing } }
port: 8080 apiVersion: policy. linkerd. io/v1beta1 kind: ServerAuthorization metadata: { name: billing-allow-inventory, namespace: prod }
spec:
server: { name: billing }
client:
meshTLS:
identities: ["inventory. prod. serviceaccount. identity. linkerd. cluster. local"]
Consul (L7 intent + splitter)
hcl
Kind = "service-router"
Name = "orders"
Routes = [{
Match { HTTP { PathPrefix = "/v1" } }
Destination { Service = "orders" }
}]
Kind = "service-splitter"
Name = "orders"
Splits = [
{ Weight = 90, ServiceSubset = "v1" },
{ Weight = 10, ServiceSubset = "v2" }
]
14) FAQ
需要一个小团队吗?
如果3-5服务-更常见的是没有。从良好的ingress和可持续性库开始。当需要默认的mTLS、单一策略和跟踪时,无需更改代码,即可连接mesh。
如何控制成本?
在关键路径上测量开销(CPU/RAM/latency),禁用多余的过滤器,减少登录量/跟踪量,在安全的情况下使用无侧面模式。
mesh和手动配置的代理是否可能受到干扰?
是的,但避免双重路由/重复转发。一个地方是真实的-控制飞机。
更重要的是: 安全性或性能?
默认情况下为安全性(mTLS、AuthZ)。通过调整连接池,outlier检测和目标路由来实现性能。
15)结果
Service Mesh将服务之间的网络转换为具有统一策略的可编程层:加密和身份,精细路由和可持续性,遥测和配额。从关键路径开始,包括STRICT mTLS和显式AuthZ,设置计时器/retrai/SV,控制egress,测量p99和5xx,进行游戏日。然后,mesh将成为可靠性和发行速度的放大器,而不是意外的来源。