站在 2023 年的明天,Service Mesh 早已不是一个新兴的概念,回顾过去 6 年多的倒退历程,Service Mesh 从一经推出就受到来自全世界的支流技术公司关注和追捧。
- 2016 年作为 Service Mesh 的元年,Buoyant 公司 CEO William Morgan 率先公布 Linkerd [ 1],成为业界首个 Service Mesh 我的项目,同年 Lyft 公布Envoy [ 2],成为第二个 Service Mesh 我的项目。
- 2017 年,Google、IBM、Lyft 联手公布了 Istio [ 3],它与 Linkerd / Envoy 等我的项目相比,它首次给大家减少了管制立体的概念,提供了弱小的流量控制能力。通过多年的倒退 Istio,曾经逐渐成为服务网格畛域管制立体的事实标准。
- 2018 年 7 月,Istio 1.0 版本 公布 [ 4],标记着其进入了能够生产可用的时代,逐步也有越来越多的企业开始思考和尝试将服务网格利用于生产中。
Istio 作为以后最风行的开源服务网格技术,它由管制立体和数据立体两局部形成。
在 Istio Mesh 架构中,其管制立体是一个名为 Istiod 的过程,网络代理是 Envoy。Istiod 作为管制面的对立组件,负责对接服务注册发现、路由规定治理、证书治理等能力,Envoy 则是作为数据面通过 Sidecar 形式代理业务流量,Istio 和 Envoy 之间通过 xDS 协定接口实现服务发现、路由规定等数据的传递。Istiod 通过监听 K8s 资源例如 Service、Endpoint 等,获取服务信息,并将这些资源对立通过 xDS 协定下发给位于数据立体的网络代理。Envoy 则是独立于利用之外的一个过程,以 Sidecar 的形式(个别是以 Container 形式)随同业务利用 Pod 运行,它与利用过程共用同一个主机网络,通过批改路由表的形式劫持业务利用的网络流量从而达到为利用无侵入地提供如服务鉴权、标签路由等能力。
Proxyless Mesh
Proxyless Mesh 全称是 Proxyless Service Mesh,其是近几年在 Service Mesh 根底上倒退而来的一种新型软件架构。Service Mesh 现实很饱满,但事实很骨感!通过一层代理尽管做到了对利用无侵入,但减少的网络代理开销对很多性能要求很高的互联网业务落地造成不少挑战。因而 Proxyless Mesh 作为一种在传统侵入式微服务框架与 Service Mesh 之间的折中计划,通过取众家之所长,为大量的非 Service Mesh 利用在云原生时代,拥抱云原生基础设施,解决流量治理等痛点提供了一种无效的解决方案。Service Mesh 和 Proxyless Mesh 架构区别如下图所示:
过来几年,国内外的出名软件开源社区也都在相干畛域进行了大量摸索,例如在 2021 年 10 月,gRPC 社区为用户提供 架构模式 [ 5],通过对接 Istio 管制立体,遵循 VirtualService & DestinationRule CRD 标准为 gRPC 利用提供流量治理能力。
Spring Cloud Alibaba Mesh 化计划
Spring Cloud Alibaba 作为一种侵入式的微服务解决方案,通过基于 Spring Cloud 微服务规范为用户提供了微服务利用构建过程中的如服务注册与发现、限流降级、分布式事务与分布式音讯等在内的一站式微服务解决方案。过来几年被国内大量中小企业所采纳,帮忙大量企业更加不便地拥抱微服务。
但随着企业应用微服化的不断深入,微服务给利用带来零碎解耦、高可扩展性等诸多劣势的同时,也让利用变得更加简单。如何治理好微服务?成为了很多企业逐步开始关注和器重的一个新的问题。Spring Cloud Alibaba 社区也留神到很多用户有微服务治理方面的诉求,于是从 2022 年初,就开始了在该方面的摸索,社区感觉相比于 Service Mesh,Proxyless Mesh 是一种对宽广中小企业更适合的技术计划,其不仅不会有额定 Sidecar 代理所带来的较大性能损耗,而且更重要的是对企业来说,其落地老本很低!
要通过 Mesh 化计划解决微服务治理需要,一个能给利用动静下发规定的管制面不可或缺,社区本着不反复造轮子,拥抱业界支流解决方案的准则,通过反对 xDS 协定不仅为用户提供通过支流的 Istio 管制面来对 Spring Cloud Alibaba 利用进行服务治理以外,用户也能够应用阿里巴巴开源的 OpenSergo 微服务治理管制面所提供的差异化治理能力进行利用治理。相干提供 Mesh 技术计划社区在最近公布的 2.2.10-RC 版本 [ 6] 中进行了提供。作为提供微服治理能力的第一个版本,社区以后曾经局部兼容了 Istio VirtualService & DestinationRule 的标签路由和服务鉴权能力,用户能够通过 Istio 管制面给利用下发相干规定,对利用进行流量治理。
筹备工作
Proxyless Mesh 的计划首先须要筹备好一个能给利用动静下发规定的管制面,本次 Spring Cloud Alibaba 2.2.10-RC1 版本反对了 2 种以后市面上的支流管制面来更好的满足各类用户诉求:
1. Istio 管制面
为了应用 Istio 管制面下发治理规定,首先须要在 K8s 环境中装置 Istio 管制面,您能够应用 Spring Cloud Alibaba 社区提供的测试用的 Istio 环境,也能够抉择本人尝试装置一套 Istio 管制面,装置 Istio 管制面的流程如下:
- 装置 K8s 环境,请参考 K8s 的 装置工具 *[ 7] * 大节
- 在 K8s 上装置并启用 Istio,请参考 Istio 官网文档的 装置大节 [ 8]
2. OpenSergo 管制面
OpenSergo 是凋谢通用的,笼罩微服务及上下游关联组件的微服务治理我的项目。OpenSergo 从微服务的角度登程,涵盖流量治理、服务容错、服务元信息治理、平安治理等要害治理畛域,提供一系列的治理能力与规范、生态适配与最佳实际,反对 Java, Go, Rust 等多语言生态。
OpenSergo 管制立体 (Control Plane) 作为 OpenSergo CRD 的对立管控组件,承载服务治理配置转换与下发的职责。
- 装置 K8s 环境,请参考 K8s 的装置工具大节
- 在 K8s 上装置并启用 OpenSergo Control Plane,请参考 OpenSergo 官网提供的 OpenSergo 管制面装置文档 [ 9]
标签路由
利用背景
在当初的微服务架构中,服务的数量非常宏大,为了更好的治理这些微服务利用,可能须要给这些利用打上标签,并且将一个或多个服务的提供者划分到同一个分组,从而束缚流量只在指定分组中流转,实现流量隔离的目标。标签路由能够作为蓝绿公布、灰度公布等场景的能力根底,它能够被利用在以下场景中:
- 多版本开发测试
多个版本并行开发时,须要为每个版本筹备一套开发环境。如果版本较多,开发环境老本会十分大。流量隔离计划能够在多版本开发测试时大幅度降低资源老本。应用基于标签路由的全链路流量隔离机制,能够将特定的流量路由到指定的开发环境。例如在开发环境 1 中只批改利用 B 和利用 D,则为这两个利用在开发环境 1 中的版本创立 Tag1 标签,并配置对应的路由规定。入口利用 A 调用 B 时,会判断流量是否满足路由规定。如果满足,路由到开发环境 1 中利用 B 的 V1.1 版本;如果不满足,路由到基线环境中的利用 B 的 V1 版本。利用 C 调用 D 的时候同样依据流量决定路由到 D 的 V1 版本或 V1.1 版本。
- 利用流量隔离
如果一个利用有多个版本在线上同时运行,部署在不同环境中,如日常环境和非凡环境,则能够应用标签路由对不同环境中的不同版本进行流量隔离,将秒杀订单流量或不同渠道订单流量路由到非凡环境,将失常的流量路由到日常环境。即便非凡环境异常,本应进入非凡环境的流量也不会进入日常环境,不影响日常环境的应用。
- A/B Testing
线上有多个利用版本同时运行,冀望对不同版本的利用进行 A/B Testing,则能够应用标签路由的全链路流量管制将地区 A(如杭州)的客户流量路由到 V1 版本,地区 B(如上海)的客户流量路由到 V1.1 版本,对不同版本进行验证,从而升高新产品或新个性的公布危险,为产品翻新提供保障。
目前,Spring Cloud Alibaba Mesh 提供的标签路由能力反对依据申请门路、申请头和 HTTP 申请参数等申请元信息对申请做标签路由,让利用收回的申请依据 Istio 管制面下发的规定发送至指定版本的上游服务。
应用形式
1. 导入依赖并配置利用
首先,创立服务消费者利用,举荐通过云原生利用脚手架进行我的项目构建,批改完配置即可便捷试用:
云原生利用脚手架:
https://start.aliyun.com/
如果手动创立我的项目,请批改服务消费者的 pom.xml 文件,导入 Spring Cloud Alibaba 2.2.10-RC1 版本下的标签路由以及 Istio 资源转换模块的相干依赖:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.10-RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-governance-routing</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-xds-adapter</artifactId>
</dependency>
</dependencies>
在 application.yml 配置文件给消费者配置 Istio 管制面以及 Nacos 注册核心的相干信息:
server:
port: 18084
spring:
main:
allow-bean-definition-overriding: true
application:
name: service-consumer
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
fail-fast: true
username: nacos
password: nacos
istio:
config:
# 是否开启 Istio 配置转换
enabled: ${ISTIO_CONFIG_ENABLE:true}
# Istiod IP
host: ${ISTIOD_ADDR:127.0.0.1}
# Istiod 端口
port: ${ISTIOD_PORT:15010}
# 轮询 Istio 线程池大小
polling-pool-size: ${POLLING_POOL_SIZE:10}
# 轮询 Istio 工夫距离
polling-time: ${POLLING_TIME:10}
# Istiod 鉴权 token(拜访 Istiod 15012 端口时可用)
istiod-token: ${ISTIOD_TOKEN:}
# 是否打印 xds 相干日志
log-xds: ${LOG_XDS:true}
在 application.yml 配置文件给生产者利用配置元信息:
# 第一个生产者,版本为 v1
spring.cloud.nacos.discovery.metadata.version=v1
# 第二个生产者,版本为 v2
spring.cloud.nacos.discovery.metadata.version=v2
如果是须要对接 OpenSergo 管制面的,则须要给消费者利用加上 spring-cloud-starter-alibaba-governance-routing 跟 spring-cloud-starter-opensergo-adapter 相干依赖,并配置 OpenSergo 所需的配置即可。
2. 运行应用程序
启动两个生产者利用和一个消费者利用,并将这些利用都注册到本地的 Nacos 注册中心里,消费者在调用生产者时,会依据管制面下发的标签路由规定来调用不同的生产者实例。启动消费者和两个生产者后,能够在 Nacos 注册中心里看到这几个已注册的服务:
管制台上会打印出以下信息,阐明此利用正在监听 Istio 管制面下发的配置:
3. 通过 Istio 管制面下发标签路由规定
通过 Istio 管制面下发标签路由规定,首先下发 DestinationRule 规定:
kubectl apply -f - << EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: my-destination-rule
spec:
host: sca-virtual-service
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
EOF
此规定将后端服务拆分为两个版本,label 为 v1 的 pod 被分到 v1 版本,label 为 v2 的 pod 被分到 v2 版本。
之后,下发 VirtualService 规定:
kubectl apply -f - << EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: sca-virtual-service
spec:
hosts:
- service-provider
http:
- match:
- headers:
tag:
exact: gray
uri:
exact: /istio-label-routing
route:
- destination:
host: service-provider
subset: v2
- route:
- destination:
host: service-provider
subset: v1
EOF
这条 VirtualService 指定了一条最简略的标签路由规定,将申请头 tag 为 gray,申请门路为 /istio-label-routing 的 HTTP 申请路由到 v2 版本,其余的流量都路由到 v1 版本。
发送若干条不带申请头的 HTTP 申请至 IstioConsumerApplication
while true;
do curl localhost:18084/istio-label-routing;
sleep 0.1;
echo "";
done;
因为申请头不为 gray,所以申请将会被路由到 v1 版本,返回如下
之后发送一条申请头 tag 为 gray,且申请门路为 /istio-label-routing 的 HTTP 申请
while true;
do curl localhost:18084/istio-label-routing -H "tag: gray";
sleep 0.1;
echo "";
done;
因为满足路由规定,所以申请会被路由至 v2 版本
4. 通过 OpenSergo 管制面下发标签路由规定
通过 OpenSergo 管制面也定义了特定的流量路由规定 TrafficRouter,如下是一个 OpenSergo 管制面对应的流量路由规定:
kubectl apply -f - << EOF
apiVersion: traffic.opensergo.io/v1alpha1
kind: TrafficRouter
metadata:
name: service-provider
namespace: default
labels:
app: service-provider
spec:
hosts:
- service-provider
http:
- match:
- headers:
tag:
exact: v2
route:
- destination:
host: service-provider
subset: v2
fallback:
host: service-provider
subset: v1
- route:
- destination:
host: service-provider
subset: v1
EOF
这条 TrafficRouter 指定了一条最简略的流量路由规定,将申请头 tag 为 v2 的 HTTP 申请路由到 v2 版本,其余的流量都路由到 v1 版本。如果 v2 版本没有对应的节点,则将流量 fallback 至 v1 版本。
进行 v2 版本的 ProviderApplication 后,持续发送一条申请头 tag 为 v2 的 HTTP 申请
curl --location --request GET '127.0.0.1:18083/router-test' --header 'tag: v2'
因为 v2 版本没有服务提供者,因而流量被 fallback 至 v1 版本。
Route in 30.221.132.228: 18081,version is v1.
上述具体示例代码能够在社区 Github 上 示例代码 *[ 10] * 中获取。
服务鉴权
失常生产场景,微服务利用都具备平安要求,不会让任意的服务都可间接调用。因而须要对调用该利用的上游利用进行服务鉴权,保障利用本身的平安。
未配置服务鉴权 Consumer 1、2、3 和 Provider 在同一个命名空间内,Consumer 1、2、3 默认能够调用 Provider 的所有 Path(Path 1、2 和 3)。
配置服务鉴权规定后,利用间非法的调用关系如下图所示:
设置所有 Path 的鉴权能够对 Provider 的所有 Path 设置鉴权规定,例如 Provider 所有 Path 的鉴权规定设置为回绝 Consumer 1 调用(黑名单),则容许 Consumer 2、3 调用(白名单)。
设置指定 Path 的鉴权在设置所有 Path 的鉴权根底上,还能够设置 Consumer 指定 Path 的鉴权规定,例如按所有 Path 的鉴权形式,Consumer 2、3 能够拜访 Provider 的所有 Path,但 Provider 的 Path2 波及一些外围业务或数据,不心愿 Consumer 2 调用,能够将 Path 2 对 Consumer 2 的鉴权形式设置为黑名单(回绝调用),则 Consumer 2 只能拜访 Provider 的 Path 1 和 Path 3。
目前,Spring Cloud Alibaba Mesh 反对了除需 mTLS 反对以外 Istio 的大部分鉴权规定,并且反对了多种字符串匹配模式以及规定的逻辑运算。
应用形式
1. 导入依赖并配置利用
首先,创立利用,举荐通过云原生利用脚手架进行我的项目构建,批改完配置即可便捷试用:
云原生利用脚手架:
https://start.aliyun.com/
如果手动创立我的项目,请批改服务消费者的 pom.xml 文件,导入 Spring Cloud Alibaba 2.2.10-RC1 版本下的标签路由以及 Istio 资源转换模块的相干依赖:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.10-RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-governance-auth</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-xds-adapter</artifactId>
</dependency>
</dependencies>
在利用的 application.yml 配置文件中配置 Istio 相干元数据:
server:
port: ${SERVER_PORT:80}
spring:
cloud:
governance:
auth:
# 是否开启鉴权
enabled: ${ISTIO_AUTH_ENABLE:true}
istio:
config:
# 是否开启 Istio 配置转换
enabled: ${ISTIO_CONFIG_ENABLE:true}
# Istiod IP
host: ${ISTIOD_ADDR:127.0.0.1}
# Istiod 端口
port: ${ISTIOD_PORT:15010}
# 轮询 Istio 线程池大小
polling-pool-size: ${POLLING_POOL_SIZE:10}
# 轮询 Istio 工夫距离
polling-time: ${POLLING_TIMEOUT:10}
# Istiod 鉴权 token(拜访 Istiod 15012 端口时可用)
istiod-token: ${ISTIOD_TOKEN:}
# 是否打印 xds 相干日志
log-xds: ${LOG_XDS:true}
2. 运行应用程序
在导入好以上的依赖并且在 application.yml 文件中配置了相干配置之后,能够将此利用程序运行起来,启动一个简略的 Spring Boot 利用,其中只含有一个简略的接口,此接口将会把本次申请的详细信息返回给客户端。
启动利用后,管制台上会打印出以下信息,阐明此利用正在监听 Istio 管制面下发的配置:
3. 通过 Istio 管制面下发鉴权配置
在应用如下命令通过 Istio 下发一条鉴权规定至 demo 利用,这条规定的限度了拜访该利用的申请 header:
kubectl apply -f - << EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: http-headers-allow
namespace: ${namespace_name}
spec:
selector:
matchLabels:
app: ${app_name}
action: ALLOW
rules:
- when:
- key: request.headers[User-Agent]
values: ["PostmanRuntime/*"]
EOF
之后发送带 User-Agent 头部的 HTTP 申请来验证规定是否失效:
while true;
do curl localhost/auth -H "User-Agent: PostmanRuntime/7.29.2";
sleep 0.1;
echo "";
done;
因为此申请因为携带了正确的 HTTP Header 信息,将会返回:
之后发送一个不带 User-Agent 头部的 HTTP 申请来验证规定是否失效:
while true;
do curl localhost/auth;
sleep 0.1;
echo "";
done;
因为此申请没有携带正确的 HTTP Header 信息,将会返回:
上述具体示例代码能够在社区 Github 上 示例代码 *[ 11] * 中获取。
社区动静
新 Committer 介绍
Spring Cloud Alibaba 社区近几个月涌现了一些积极参与社区保护迭代的内部贡献者,在此,向他们表示感谢!另外,对于其中始终参加社区活动,做出重要奉献 feature 的阮胜同学,社区依照新 Committer 提名与投票制度正式提名其为社区 Committer 并投票通过,胜利入选,在此也向其表示祝贺!欢送更多内部同学关注 Spring Cloud Alibaba 开源社区和奉献开源社区。
将来布局
通过过来几年倒退迭代,Spring Cloud Alibaba 以后在微服务利用的构建的如服务注册与发现、分布式配置、限流降级等能力方面曾经做得日趋完善,社区的工作重心会投入到构建 Spring Cloud 生态的微服务治理能力上。欢送感兴趣的同学扫描下方钉钉二维码退出社区交换群,一起参加社区将来建设!
相干链接
[1] Linkerd
https://linkerd.io/
[2] Envoy
https://www.envoyproxy.io/
[3] Istio
https://github.com/istio/istio
[4] Istio 1.0 版本
https://istio.io/latest/news/…
[5] 架构模式
https://istio.io/v1.12/blog/2…
[6] 2.2.10-RC 版本
https://github.com/alibaba/sp…
[7] 装置工具
https://kubernetes.io/zh-cn/docs/tasks/tools/
[8] 装置大节
https://istio.io/latest/zh/docs/setup/install/
[9] OpenSergo 管制面装置文档
https://opensergo.io/zh-cn/do…
[10] 示例代码
https://github.com/alibaba/spring-cloud-alibaba/tree/2.2.x/spring-cloud-alibaba-examples/governance-example/label-routing-example
[11] 示例代码
https://github.com/alibaba/spring-cloud-alibaba/tree/2.2.x/spring-cloud-alibaba-examples/governance-example/authentication-example