第四章:规则入微 · 服务网格

即使在天庭管辖下,服务间通信的复杂性仍需更精细的法则来约束

页面内容

楔子:通信的复杂性

掌握Kubernetes后,韩立在云上仙境中如鱼得水。他的韩门运行稳定,能够自动扩缩容、自愈、滚动更新,一切都显得那么完美。

然而,随着服务的不断增多,韩立发现了一个新的问题:服务间通信的复杂性。

在微服务架构中,服务之间的通信需要处理很多横切关注点(Cross-Cutting Concerns):

  • 服务发现:如何找到目标服务
  • 负载均衡:如何分发请求
  • 熔断降级:如何防止服务雪崩
  • 限流:如何控制流量
  • 重试:如何处理失败
  • 超时:如何设置超时时间
  • 安全:如何加密通信、认证授权
  • 监控:如何追踪请求链路
  • 日志:如何记录通信日志

这些逻辑如果都写在业务代码中,会导致:

  1. 代码耦合:业务逻辑与通信逻辑混合
  2. 重复代码:每个服务都要实现相同的逻辑
  3. 难以维护:修改通信逻辑需要修改所有服务
  4. 技术栈绑定:不同语言需要实现不同的逻辑

韩立想起了源界中流传的"服务网格"(Service Mesh)理论。这个理论说,可以将服务间通信的逻辑从业务代码中抽离出来,下沉为基础设施,由Sidecar代理来处理。

“这就是我需要的!“韩立眼中闪烁着兴奋的光芒。


第一节:本命剑灵——Sidecar模式

在服务网格中,每个服务都有一个"本命剑灵”——Sidecar代理。这个代理附着在服务身边,专职处理服务间通信,让服务本体能够专心处理业务逻辑。

Sidecar就像源界中的"护道傀儡”,它:

  • 与业务服务同生共死:Sidecar和业务服务运行在同一个Pod中
  • 代理所有通信:所有进出服务的流量都经过Sidecar
  • 透明代理:业务服务无需感知Sidecar的存在

在Istio中,Sidecar由Envoy实现。Envoy是一个高性能的代理,支持HTTP/1.1、HTTP/2、gRPC等协议。

当服务A调用服务B时:

  1. 服务A发送请求 → Envoy Sidecar A
  2. Envoy Sidecar A进行服务发现、负载均衡、熔断等处理
  3. 请求发送到 → Envoy Sidecar B
  4. Envoy Sidecar B进行认证、限流等处理
  5. 请求转发到 → 服务B
  6. 响应按原路返回

这样,所有的通信逻辑都在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

这个配置实现了:

  1. Chrome用户100%使用v2版本
  2. 其他用户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秒后仍然失败,会继续驱逐。

限流:通过connectionPoolcircuitBreaker配置

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的工作原理:

  1. 证书颁发:Citadel为每个服务颁发证书
  2. 证书分发:证书自动注入到Sidecar中
  3. 加密通信:服务间通信使用TLS加密
  4. 证书轮换:证书定期自动轮换

启用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-idx-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进入集群,并路由到相应的服务。


尾声:服务网格的真谛

经过数月的修炼,韩立终于掌握了服务网格的精髓。他意识到,服务网格的真谛是:

  1. 关注点分离:将通信逻辑从业务代码中抽离,下沉为基础设施
  2. 统一治理:通过控制平面统一管理所有服务的通信规则
  3. 透明代理:业务服务无需感知Sidecar的存在
  4. 精细化控制:可以实现流量路由、熔断、限流、安全等精细化的控制
  5. 可观测性:自动收集丰富的遥测数据,实现全面的可观测性

“服务网格,我终于掌握了!“韩立看着在Istio上运行的韩门,心中涌起一股成就感。

通过服务网格,韩立实现了:

  • 零侵入:业务代码无需修改
  • 统一治理:所有服务的通信规则统一管理
  • 精细化控制:可以实现复杂的流量管理策略
  • 安全加固:mTLS加密、访问控制
  • 全面可观测:指标、日志、追踪

但他知道,这还不是终点。在源界中,还有更高级的修炼方式——智能架构(AIOps),可以实现系统的自感知、自决策、自修复。

“下一站,智能架构!“韩立眼中闪烁着坚定的光芒。


本章要点总结

  1. Sidecar模式:将通信逻辑从业务代码中抽离,由Sidecar代理处理
  2. 控制平面:Istio控制平面统一管理所有服务的通信规则
  3. 流量路由:通过VirtualService实现精细化的流量路由
  4. 熔断限流:通过DestinationRule实现熔断和限流
  5. 超时重试:通过VirtualService配置超时和重试策略
  6. 安全通信:通过mTLS加密服务间通信
  7. 访问控制:通过AuthorizationPolicy实现精细化的访问控制
  8. 可观测性:自动收集指标、日志、追踪数据
  9. 外部服务:通过ServiceEntry访问外部服务
  10. 网关:通过Gateway管理外部流量

下一章,韩立将学习智能架构,实现系统的自感知、自决策、自修复。