前言

用户需求决定要做什么软件?软件架构决定需要什么样的基础设施?

2005年,PeterRodgers提出Micro-Web-Service,微服务雏形出现;

2011年,威尼斯架构师会议正式提出微服务概念;

2014年3月,MartinFowler与JamesLewis发表经典文章,微服务理念普及;

2014年6月,Google在DockerCon首次发布Kubernetes;

2015年7月,K8s发布v1.0稳定版。

基础设施层随着上层应用架构的变化而变化的,K8s就是为解决微服务架构应用运维难的问题,而诞生的容器编排平台。

在云计算时代的单体架构中,应用内部各模块之间的交互,本质上是进程内的函数调用。这种调用无需依赖网络,也不涉及序列化或反序列化,不存在网络超时或抖动,仅是方法栈的进出,逻辑同步、行为确定,通信高度可靠。

而在云原生时代,应用由单体拆分为微服务架构后,基础设施层面临根本性变化:原本在内存中高效完成的函数调用,被迫转化为依赖网络的远程通信,同时引入网络抖动、超时、服务发现、序列化开销等新的复杂性。

虽然Kubernetes在PaaS层提供了强大的基础能力,例如:

  • 应用部署与升级

  • 弹性伸缩

  • 服务自动注册与发现

  • 服务负载均衡

但在分布式环境中,网络的不可靠性仍然不可忽视,即使在使用Kubernetes之后,SaaS层的微服务应用仍面临诸多挑战,需要额外的机制来保证可靠性和可观测性,例如:

  • 客户端重试与可配置超时

  • 负载均衡与限流、熔断

  • 服务间路由、按需路由与边缘路由

  • 流量镜像与 A/B 测试

  • 内部发布与故障注入

  • 异常点检测、健康状态检查

  • 日志收集与分布式链路追踪(可观测)

  • 指标统计与度量

有了K8S和服务网格还需要微服务框架吗?

虽然在基础设施层:K8s和服务网格可以解决微服务架构中的运行环境(Kubernetes)、服务发现(CoreDNS)、流量治理(Ingress、Envoy、Istio)、通信可靠性(Envoy、Istio)等问题,

但是微服务框架仍需负责代码层:业务调用封装(Feign/gRPC)、应用级限流熔断(Resilience4j/Hystrix)、动态配置(Nacos/Apollo/Console/Go-ZeroConfig)、消息总线(SpringCloudStream、Go-MicroBroker、Go-ZeroMQ)、分布式事务(Seata/Go-ZeroTCC/Saga)等应用层开发与业务逻辑问题。

什么是微服务治理?

微服务治理:管理控制微服务不断增长产生的复杂度;

网络拓扑变动、网络延时、网络通信安全........

API网关、服务发现、服务容错、服务部署、数据调用、分布式链路追踪、数据全链路透传........

ServiceMesh概念

ServiceMesh(服务网格)是云原生、微服务架构下的基础设施层,用于统一治理服务间的网络通信。

在基础设施层构建微服务服务网格与统一网关,可以将南北向入口流量与东西向服务间通信的流量控制、安全策略、可观测性、熔断、限流、灰度发布等能力,统一从业务代码中剥离并下沉到基础设施层进行托管治理,实现与业务逻辑解耦,同时天然兼容多语言技术生态。

在基于服务网格与网关的云原生架构下,微服务开发框架中的流量治理、服务发现、配置、熔断限流等能力,可以完全由基础设施层替代,业务开发不再需要强依赖SpringCloud、Go-Zero、Go-Micro这类代码层治理框架,只需要关注业务开发能力即可。

1个Pod配套1个Sidecar代理形成一个通信节点(小方格),多个通信节点(小方格)通过代理互联,大量服务实例及其代理通过服务间通信形成相互连接的网络,这个整体称为Service Mesh

Istio

Istio是业界主流Service Mesh(服务网格)开源实现,基于Sidecar架构,无需修改业务代码,就能对Kubernetes集群内微服务实现统一流量治理、安全管控、可观测。

image

Istio采用经典的控制平面+数据平面架构:
  • 数据平面(Data Plane):以 sidecar 代理(如 Envoy)的形式和应用部署在一起,接管所有进出流量。
  • 控制平面(Control Plane):负责统一下发规则、服务发现、证书管理、策略配置。
核心价值: 
  • 无侵入:不用改业务代码,跨语言、跨框架统一治理
  • 全链路可观测:指标、日志、追踪一体化
  • 安全:自动 mTLS 加密、认证、授权
  • 流量治理:灰度、熔断、重试、超时、流量镜像

流量路径:

集群外部流量---------> NodePort类型Service四层转发---------> istio-ingressgateway Pod内Envoy---------> 
Gateway CRD监听器处理端口、TLS、域名校验---------> 绑定gateways字段的VS执行七层路由--------->
Istiod通过EDS下发目标Service关联的Pod IP列表(Envoy绕过Service ClusterIP直接服务发现PodIP)
--------->网关Envoy直连业务PodIP---------> 业务Pod的sidecar入站鉴权---------> 通过本地环回(127.0.0.1)透明转发至业务容器进程

Istio数据平面(Envoy)

Envoy是Istio服务网格的核心数据平面组件,通常以Sidecar模式运行在业务Pod内,与应用容器共享网络命名空间,透明拦截并治理应用的所有入站/出站流量,实现无侵入的流量管控、安全加密与可观测性能力。

引入Envoy之后Service提供这个服务有哪些实例的服务发现基础;

Istio将这些实例信息下发给Envoy;Envoy直接面向实际的Pod IP做负载均衡和流量治理。

 

744ff2feb3ead0604740542fe9e6d00d

如果上图所示Envoy的内部组件通过xDS协议从Istior实时热更新配置,并执行配置规则。

Service
│
│ 提供服务发现信息
▼
istiod
│
│ xDS 下发
▼
Envoy
│
├── Subset:确定 Pod 分组
├── LoadBalancer:选择 Pod
├── ConnectionPool:管理连接
└── OutlierDetection:异常 Pod 摘除
│
▼
Pod IP

XDS(LDS/RDS/CDS/EDS) 是Envoy与Istio控制平面内部通信的协议,一般不需要使用者关心,也不会直接写这些内容。

XDS是基础设施的实现细节,Envoy会自动从IstioPilot拉取配置。

真正需要关心的是Istio控制器监听的CRD资源

Envoy:真正干活的数据面代理负责:

接收业务请求

路由

客户端负载均衡

连接池

熔断/异常实例摘除

超时

重试

TLS/mTLS

访问日志、指标等可观测

Envoy监听器

image

Envoy可以被配置为2类/组Listener,不同组Linstener承担职责不同。

  • Ingress-Listener(virtualInbound:15006):接收外部访问本 Pod 的流量,执行访问鉴权。
  • Egress-Listener(virtualOutbound:15001):承接本地业务容器对外发起的请求,执行VirtualService与DestinationRule规则。

可按需启用,Istio改造为Pod独立Sidecar 模式,借助iptables实现流量透明劫持。

服务A调用服务B完整链路

  1. 服务A进程发起请求 → iptables劫持 → Sidecar-A 监听的15001端口(Egress) → 执行VS+DR规则 → Envoy直连PodIP-B
  2. 数据包抵达Pod-B网卡 → iptables劫持 → Sidecar-B监听的15006端口(Ingress) → AuthorizationPolicy鉴权 →到达服务B进程

Envoy工作流程

Envoy Sidecar容器是通过给业务Pod所在的命名空间(NS)标签,自动注入业务Pod,无代码侵入也无需修改原CD流程。

业务Pod引入Envoy sidecar后,入站与出站流量均强制经由该代理进行全链路管控(拦截、路由、策略执行与遥测采集);

Envoy基于Kubernetes Service完成服务发现,经由Istio控制平面EDS拉取后端PodIP列表,绕过kube-proxy的ClusterIP转发路径,在客户端侧直连PodIP并执行负载均衡;

既消除传统 Service 代理的性能损耗,又依托 Pod 级地址粒度实现精细化灰度、故障注入等治理特性

业务App请求ServiceName ---------》iptables劫持流量交给Envoy--------》Envoy做服务发现拿到K8s原生Service资源关联PodIP-------》Envoy执行VS/DR规则---------》Envoy直连选中的PodIP

Istio CRD资源

Istio的流量治理能力,主要依靠Gateway 、 VirtualService 、 DestinationRule这3类CRD资源协同完成,三者配合几乎可以覆盖绝大多数微服务流量管理场

1.Gateway

Gateway是进出网格流量的大门,管控端口、协议、证书、域名准入;但路由转发逻辑交给VirtualService。主要用于外部进网格,也可用于网格访问外部。

除了使用ingress-controller这种方式引入南北向流量之外,Istio的Gateway也可以,本质就是个独立部署的Envoy,只是Istio给它包装了一层,用于引入和管理南北向流量,定义进入集群的南北流量规则,相当于入口控制器。

浏览器
   │ HTTPS
   ▼
集群外 LB(TLS 卸载)
   │ HTTP
   ▼
Istio IngressGateway(Envoy)
   │ HTTP
   ▼
VirtualService
   │
   ▼
MockServer

Istio中的Gateway和Vitrtuaservice是中紧密配合、职责分离的1对资源,

Gateway负责开门:定义在哪个端口、用什么协议接收南北流量。

VirtualService负责带路:定义南北流量进门后的路由,具体该往哪个服务转发?

2.VirtualService

定义群内部东西向流量路由规则:应用内部或外部流量如何路由到不同版本的服务,实现灰度、金丝雀等。

VirtualService用于定义流量路由规则,依据gateways字段取值类型确定是作用于网关南北向流量,还是Pod之间的东西向流量;

VirtualService可以实现网关实现灰度、金丝雀、超时重试、请求改写等流量治理。

VirtualService的后端服务版本的识别依赖DestinationRule。

kubectl get vs -A
NAME                       GATEWAYS                      HOSTS                                   AGE
reviews-route-internal     ["mesh"]                      ["reviews.default.svc.cluster.local"]   10d
ai.minmetals.com.cn        ["zhanggen/global-gateway"]   ["ai-impl.minmetals.com.cn"]            13d

VirtualService根据spec.gateways的取值类型,控制路由规则是作用于网关的南北向流量,还是作用于网格内部Sidecar的东西向流量。

gateways 字段值流量类型流量路径
["ns/gateway-name"] 南北向 外部 → gateway 网关 Pod → vs → svc
["mesh"] 东西向 Pod sidecar → vs → svc(不经过 ingress 网关)
["ns/gateway","mesh"] 同时南北 + 东西 网关入口、内部 Pod 调用都生效

当前端代码内静态资源采用相对路径引入时

        import UI from "./app/ui.js";
        import * as Log from './core/util/logging.js';

浏览器解析静态资源路径地址,会以地址栏当前页面URL作为基准路径拼接资源地址。

1. 浏览器访问  /jmeter (无末尾斜杠):浏览器识别为根目录下的文件,基础路径 =  / ,相对路径资源app.js 拼接为 /app.js 

2. 浏览器访问  /jmeter/ (带末尾斜杠):浏览器识别为目录,基础路径 =  /jmeter/ ,相对路径资源app.js拼接为 /jmeter/app.js

防止用户在浏览器地址栏属于网址不以为/结束方法

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: jmeter-vs
spec:
  hosts: ["zhanggen.com"]
  gateways: ["istio-system/ingressgateway"]
  http:
  - match:
      - uri:
          exact: /jmeter
    redirect:
      uri: /jmeter/
      redirectCode: 302
  - match:
      - uri:
          prefix: /jmeter/
    rewrite:
      uri: /
    route:
    - destination:
        host: jmeter服务名
        port:
          number: 80

3.istio-gateway VirtualService(南北向流量)

VirtualService可以控制东西向流量,还可以控制南北向流量,支持将TCP、HTTP和GRPC协议流量转发到K8s的Service。

3.1.路径匹配模式

VirtualService在匹配HTTP流量路径时有以下3中匹配模式

类型规则逻辑典型场景
exact 完整严格相等 固定单点接口、健康检查
prefix 字符串以目标开头 按目录分组路由(/api、/static)
regex RE2 正则表达式 复杂可变路径(版本号、id 格式校验)

 

3.1.路径rewrite后为双杠(//test)

Istio VirtualService URI重写机制

如果match.uri.regex字段是(/pg/api),rewrite.uri字段是/,作用是重写(/pg/api)部分为(/),

用户在浏览器地址栏输入路径(/pg/api/test)浏览器自动补全为(/pg/api/test/),

istio-gateway write了(/pg/api)部分而不是(/pg/api/),所以(/pg/api/test/)最终会被重新成(//test)

小结

match.uri.regex字段一定要以为/结尾。

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: xxxxx
  namespace: ffff
spec:
  gateways:
  - possss/global-gateway
  hosts:
  - dsep-portal-xxxxx.com.cn
  http:
    - match:
        - uri:
            regex: /pg/api/
      rewrite:
        uri: /
      route:
        - destination:
            host: xxxxx.svc.cluster.local
            port:
              number: 3000

代码复盘

import re

# 前端浏览器补全
front_url = "/pg/api/test"

# 运维配置错误
w_backend_url = re.sub(r"^/pg/api", "/", front_url)
# 运维配置正确
r_backend_url = re.sub(r"^/pg/api/", "/", front_url)

# 错误重写结果
print(w_backend_url)
# 正确重写结果
print(r_backend_url)

3.2.路径match不到404

修复istio-gateway匹配不到长路径(pg/api/all_menu_url?limit=10)导致前端404故障

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: perf-lcp-vs
  namespace: perf-lcp
spec:
  gateways:
  - ssss/global-gateway
  hosts:
  - lesjdkk.com
  http:
    - match:
        - uri:
            regex: "^/pg/api(/.*)?$"
      rewrite:
        uriRegexRewrite:
          match: "^/pg/api(/.*)?$"
          rewrite: "\\1"
      route:
        - destination:
            host: xxddd.svc.cluster.local
            port:
              number: 3000

3.DestinationRule

定义目标服务的策略,比如流量分割、连接池、熔断等。

Istio控制平面

Istio是服务网格的控制平面负责监听VirtualService/DestinationRule/Gateway等CRD资源的变化转换成Envoy可以识别的配置,通过XDS协议下发到Envoy执行。

- TCP:两车道(全双工)支持同时发送和接收

- HTTP/2:单车道,1条连接,多路Stream,不乱序

- SSE:HTTP/2 单车道,服务器单向推流 → AI 聊天

- List-Watch:HTTP/1.1 单车道,服务器单向推事件 → K8s

- XDS:gRPC+HTTP/2 单车道,服务器单向推配置 → Istio

TCP虽然给了双车道,但这以上3个全是单行道,只许服务器往回推,客户端只发请求不插话,是为了保证数据不乱序。

架构

1.代理

服务之间的通信(比如这里的 Service A 访问 Service B)会通过代理(默认是 envoy)来进行;

中间的网络协议支持 HTTP/1.1,HTTP/2,gRPC 或者 TCP,可以说覆盖了主流的通信协议;

代理会和控制平面实时通信

  • 一方面可以获取需要的服务之间的信息
  • 一方面也可以汇报服务调用的 metrics 数据。

2.控制平面

控制中心做了进一步的细分,分成了 Pilot、Mixer、和 Citadel,它们的各自功能如下:

Pilot

为 envoy 提供了服务发现,流量管理和智能路由(AB测试、金丝雀发布等),以及错误处理(超时、重试、熔断)功能。用户通过 pilot 的 API 管理网络相关的资源对象,pilot 会根据用户的配置和服务的信息把网络流量管理变成 envoy 能识别的格式分发到各个 sidecar 代理中。

Mixer

为整个集群执行访问控制(哪些用户可以访问哪些服务)和 policy 管理(rate limit,quota 等),并且收集代理观察到的服务之间的流量统计数据

Citadel

为服务之间提供认证和证书管理,可以让服务自动升级成 TLS 协议

功能

知道 istio 的核心架构,再来看看它的功能描述就非常容易理解了。

  • 连接:控制中心可以从集群中获取所有服务的信息,并分发给代理,这样代理就能根据用户的期望来完成服务之间的通信(自动地服务发现、负载均衡、流量控制等)

  • 安全加固:因为所有的流量都是通过代理的,那么代理接收到不加密的网络流量之后,可以自动做一次封装,把它升级成安全的加密流量

  • 控制:用户可以配置各种规则(比如 RBAC 授权、白名单、rate limit 或者 quota 等),当代理发现服务之间的访问不符合这些规则,就直接拒绝掉

  • 观察:所有的流量都经过代理,因此代理对整个集群的访问情况知道得一清二楚,它把这些数据上报到控制中心,那么管理员就能观察到整个集群的流量情况了

 

 

Envoy参考

Istio参考

posted on 2024-03-22 13:12  运维体系建设之路  阅读(143)  评论(0)    收藏  举报