第四章:规则入微 · 服务网格
即使在天庭管辖下,服务间通信的复杂性仍需更精细的法则来约束
楔子:通信的复杂性
掌握Kubernetes后,韩立在云上仙境中如鱼得水。他的韩门运行稳定,能够自动扩缩容、自愈、滚动更新,一切都显得那么完美。
然而,随着服务的不断增多,韩立发现了一个新的问题:服务间通信的复杂性。
在微服务架构中,服务之间的通信需要处理很多横切关注点(Cross-Cutting Concerns):
- 服务发现:如何找到目标服务
- 负载均衡:如何分发请求
- 熔断降级:如何防止服务雪崩
- 限流:如何控制流量
- 重试:如何处理失败
- 超时:如何设置超时时间
- 安全:如何加密通信、认证授权
- 监控:如何追踪请求链路
- 日志:如何记录通信日志
这些逻辑如果都写在业务代码中,会导致:
- 代码耦合:业务逻辑与通信逻辑混合
- 重复代码:每个服务都要实现相同的逻辑
- 难以维护:修改通信逻辑需要修改所有服务
- 技术栈绑定:不同语言需要实现不同的逻辑
韩立想起了源界中流传的"服务网格"(Service Mesh)理论。这个理论说,可以将服务间通信的逻辑从业务代码中抽离出来,下沉为基础设施,由Sidecar代理来处理。
“这就是我需要的!“韩立眼中闪烁着兴奋的光芒。
第一节:本命剑灵——Sidecar模式
在服务网格中,每个服务都有一个"本命剑灵”——Sidecar代理。这个代理附着在服务身边,专职处理服务间通信,让服务本体能够专心处理业务逻辑。
Sidecar就像源界中的"护道傀儡”,它:
- 与业务服务同生共死:Sidecar和业务服务运行在同一个Pod中
- 代理所有通信:所有进出服务的流量都经过Sidecar
- 透明代理:业务服务无需感知Sidecar的存在
在Istio中,Sidecar由Envoy实现。Envoy是一个高性能的代理,支持HTTP/1.1、HTTP/2、gRPC等协议。
当服务A调用服务B时:
- 服务A发送请求 → Envoy Sidecar A
- Envoy Sidecar A进行服务发现、负载均衡、熔断等处理
- 请求发送到 → Envoy Sidecar B
- Envoy Sidecar B进行认证、限流等处理
- 请求转发到 → 服务B
- 响应按原路返回
这样,所有的通信逻辑都在Sidecar中处理,业务服务只需要专注于业务逻辑。
第二节:天条律法司——Istio控制平面
Sidecar负责处理具体的通信,但谁来制定规则呢?
这就是Istio控制平面的作用。控制平面就像"天条律法司",负责制定所有服务间通信的规则,并下发到每个Sidecar执行。
Istio控制平面包含以下组件:
Pilot:服务发现和流量管理
- 从Kubernetes等注册中心获取服务信息
- 将路由规则、负载均衡策略等配置下发到Envoy
Citadel:安全和证书管理
- 为服务间通信提供mTLS(双向TLS)加密
- 管理证书的生成、分发和轮换
Galley:配置验证和分发
- 验证Istio配置的正确性
- 将配置转换为Envoy可理解的格式
Mixer(已废弃,功能合并到Envoy):策略和遥测
- 访问控制策略
- 指标收集和日志记录
韩立部署了Istio:
# 安装Istio
istioctl install --set profile=default
# 为命名空间启用自动注入Sidecar
kubectl label namespace default istio-injection=enabled
当在启用了自动注入的命名空间中创建Pod时,Istio会自动注入Envoy Sidecar:
apiVersion: v1
kind: Pod
metadata:
name: user-service
labels:
app: user-service
spec:
containers:
- name: user-service # 业务容器
image: user-service:1.0.0
- name: istio-proxy # Sidecar容器(自动注入)
image: istio/proxyv2:1.15.0
第三节:流量路由——VirtualService
在Istio中,流量路由通过VirtualService来定义。VirtualService定义了如何将请求路由到不同的服务版本。
韩立创建了一个VirtualService,实现A/B测试:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: user-service
spec:
hosts:
- user-service
http:
- match:
- headers:
user-agent:
regex: ".*Chrome.*"
route:
- destination:
host: user-service
subset: v2 # Chrome用户使用v2版本
weight: 100
- route:
- destination:
host: user-service
subset: v1 # 其他用户使用v1版本
weight: 90
- destination:
host: user-service
subset: v2 # 10%流量到v2版本
weight: 10
这个配置实现了:
- Chrome用户100%使用v2版本
- 其他用户90%使用v1版本,10%使用v2版本
通过DestinationRule定义服务版本:
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: user-service
spec:
host: user-service
subsets:
- name: v1
labels:
version: v1.0.0
- name: v2
labels:
version: v2.0.0
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN # 负载均衡策略
connectionPool:
tcp:
maxConnections: 100 # 最大连接数
http:
http1MaxPendingRequests: 10
http2MaxRequests: 100
maxRequestsPerConnection: 2
outlierDetection:
consecutiveErrors: 3 # 连续错误3次
interval: 30s # 检查间隔
baseEjectionTime: 30s # 基础驱逐时间
maxEjectionPercent: 50 # 最大驱逐比例
这样,韩立就可以精细地控制流量路由,实现灰度发布、A/B测试、金丝雀发布等策略。
第四节:熔断与限流——DestinationRule
在Istio中,熔断和限流通过DestinationRule来配置。
熔断:通过outlierDetection配置
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: user-service
spec:
host: user-service
trafficPolicy:
outlierDetection:
consecutiveErrors: 5 # 连续5次错误
interval: 30s # 检查间隔30秒
baseEjectionTime: 30s # 基础驱逐时间30秒
maxEjectionPercent: 50 # 最多驱逐50%的实例
minHealthPercent: 50 # 至少保留50%的健康实例
当某个服务实例连续失败5次时,Istio会将其从负载均衡池中移除30秒。如果30秒后仍然失败,会继续驱逐。
限流:通过connectionPool和circuitBreaker配置
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: user-service
spec:
host: user-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100 # 最大连接数
http:
http1MaxPendingRequests: 10 # HTTP/1.1最大等待请求数
http2MaxRequests: 100 # HTTP/2最大请求数
maxRequestsPerConnection: 2 # 每个连接最大请求数
circuitBreaker:
consecutiveErrors: 3 # 连续3次错误触发熔断
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
这样,当连接数或请求数超过限制时,Istio会自动拒绝新的请求,防止服务过载。
第五节:超时与重试——VirtualService
在Istio中,超时和重试通过VirtualService来配置。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: user-service
spec:
hosts:
- user-service
http:
- route:
- destination:
host: user-service
timeout: 5s # 超时时间5秒
retries:
attempts: 3 # 重试3次
perTryTimeout: 2s # 每次重试的超时时间
retryOn: # 在什么情况下重试
- 5xx # 5xx错误
- reset # 连接重置
- connect-failure # 连接失败
这样,当请求超时或失败时,Istio会自动重试,提高请求的成功率。
第六节:安全通信——mTLS
在微服务架构中,服务间通信的安全性至关重要。Istio提供了mTLS(双向TLS)来加密服务间通信。
mTLS的工作原理:
- 证书颁发:Citadel为每个服务颁发证书
- 证书分发:证书自动注入到Sidecar中
- 加密通信:服务间通信使用TLS加密
- 证书轮换:证书定期自动轮换
启用mTLS:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT # 强制mTLS
或者为特定服务启用:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: user-service
spec:
selector:
matchLabels:
app: user-service
mtls:
mode: STRICT
这样,所有服务间通信都会被加密,防止中间人攻击和数据泄露。
第七节:访问控制——AuthorizationPolicy
在Istio中,访问控制通过AuthorizationPolicy来配置。
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: user-service-policy
spec:
selector:
matchLabels:
app: user-service
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/order-service"]
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/users/*"]
这个策略表示:
- 只允许来自
order-service的请求 - 只允许GET和POST方法
- 只允许访问
/api/users/*路径
更复杂的策略:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: user-service-policy
spec:
selector:
matchLabels:
app: user-service
action: DENY
rules:
- from:
- source:
notRequestPrincipals: ["*"] # 拒绝未认证的请求
- to:
- operation:
methods: ["DELETE"] # 拒绝DELETE方法
这样,韩立就可以精细地控制哪些服务可以访问哪些接口,实现零信任安全模型。
第八节:可观测性——遥测数据
Istio自动收集丰富的遥测数据,包括:
- 指标:请求数、延迟、错误率等
- 日志:访问日志、错误日志等
- 追踪:分布式链路追踪
这些数据可以集成到Prometheus、Grafana、Jaeger等工具中。
指标收集:
Istio自动收集以下指标:
istio_requests_total:请求总数istio_request_duration_seconds:请求延迟istio_request_bytes:请求大小istio_response_bytes:响应大小
在Grafana中可视化:
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-dashboard
data:
istio-dashboard.json: |
{
"dashboard": {
"panels": [
{
"title": "Request Rate",
"targets": [
{
"expr": "sum(rate(istio_requests_total[5m]))"
}
]
}
]
}
}
链路追踪:
Istio自动注入追踪头(如x-request-id、x-trace-id),可以在Jaeger中查看完整的请求链路。
第九节:外部服务访问——ServiceEntry
在Istio中,默认情况下只能访问集群内部的服务。如果要访问外部服务,需要使用ServiceEntry。
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: external-api
spec:
hosts:
- api.external.com
ports:
- number: 443
name: https
protocol: HTTPS
location: MESH_EXTERNAL
resolution: DNS
这样,服务就可以访问外部API了,而且所有的Istio功能(如mTLS、限流、监控等)都会应用到外部服务上。
第十节:网关——Gateway
在Istio中,外部流量通过Gateway进入集群。
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: ingress-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*.example.com"
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: example-com-tls
hosts:
- "*.example.com"
然后通过VirtualService路由到内部服务:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: ingress-routing
spec:
hosts:
- "*.example.com"
gateways:
- ingress-gateway
http:
- match:
- uri:
prefix: "/api/users"
route:
- destination:
host: user-service
port:
number: 8080
这样,外部流量就可以通过Istio Gateway进入集群,并路由到相应的服务。
尾声:服务网格的真谛
经过数月的修炼,韩立终于掌握了服务网格的精髓。他意识到,服务网格的真谛是:
- 关注点分离:将通信逻辑从业务代码中抽离,下沉为基础设施
- 统一治理:通过控制平面统一管理所有服务的通信规则
- 透明代理:业务服务无需感知Sidecar的存在
- 精细化控制:可以实现流量路由、熔断、限流、安全等精细化的控制
- 可观测性:自动收集丰富的遥测数据,实现全面的可观测性
“服务网格,我终于掌握了!“韩立看着在Istio上运行的韩门,心中涌起一股成就感。
通过服务网格,韩立实现了:
- 零侵入:业务代码无需修改
- 统一治理:所有服务的通信规则统一管理
- 精细化控制:可以实现复杂的流量管理策略
- 安全加固:mTLS加密、访问控制
- 全面可观测:指标、日志、追踪
但他知道,这还不是终点。在源界中,还有更高级的修炼方式——智能架构(AIOps),可以实现系统的自感知、自决策、自修复。
“下一站,智能架构!“韩立眼中闪烁着坚定的光芒。
本章要点总结
- Sidecar模式:将通信逻辑从业务代码中抽离,由Sidecar代理处理
- 控制平面:Istio控制平面统一管理所有服务的通信规则
- 流量路由:通过VirtualService实现精细化的流量路由
- 熔断限流:通过DestinationRule实现熔断和限流
- 超时重试:通过VirtualService配置超时和重试策略
- 安全通信:通过mTLS加密服务间通信
- 访问控制:通过AuthorizationPolicy实现精细化的访问控制
- 可观测性:自动收集指标、日志、追踪数据
- 外部服务:通过ServiceEntry访问外部服务
- 网关:通过Gateway管理外部流量
下一章,韩立将学习智能架构,实现系统的自感知、自决策、自修复。
