01 ServiceMesh概述
微服务架构已然成为目前人们最关注的技术热点,而以Spring Cloud为代表的传统微服务框架已经非常普及。然而基于诸如Spring Cloud或者Dubbo这些传统的微服务框架在进行微服务应用系统的构建的过程中,虽然可以使用框架里一些开箱即用的组件,但是也存在着如下这些问题和痛点:
侵入性强。对于这些传统微服务框架而言,想要使用某些功能,就需要集成相关的SDK,这不仅需要在项目中添加相关的依赖,可能还需要对业务代码进行一些改造,在其中增加治理相关的代码或者配置等,那么这样业务层就与治理层耦合严重。
升级成本高。如果需要对治理功能进行升级,那么就需要业务系统修改相应依赖或SDK的版本,然后再进行功能回归测试保证软件质量,但这对于业务系统来说并不是必要的,为了配合治理,不得不停下脚步配合,对于业务系统的迭代影响比较大。
版本碎片化严重。各个微服务治理架构中的各个中间件也不停的升级迭代,在微服务架构中,每个微服务的开发和维护工作分为了不通的团队进行,如果企业内部不制定相关的版本使用规范,久而久之,很容易导致各个不同服务使用的中间价或治理组件的版本不统一、能力参差不齐,很难统一治理。
内容多、门槛高。Spring Cloud被称为微服务治理框架的“全家桶”,包含大大小小几十个组件,内容相当多,往往需要用户花费几年时间去熟悉其中的关键组件。如果将Spring Cloud作为一个完整的治理框架,则需要深入了解其中的原理与实现,否则遇到问题会很难定位。
这些传统微服务框架的局限性促使着技术不断发展。而Service Mesh的出现,正是为了解决现阶段传统微服务架构所遇到的这些问题。
ServiceMesh架构
Service Mesh是一个专门处理服务通信的基础设施层。它的职责是在由云原生应用组成服务的复杂拓扑结构下进行可靠的请求传送。在实践中,它是一组和应用服务部署在一起的轻量级的网络代理,且对应用服务透明。
服务网格的总体架构设计并不复杂,主要由一堆微服务和各个微服务身边的网络代理,加一个负责统一管理这些代理的服务组成。在服务网格中,代理被称为数据层或数据平面(Data Plane),负责管理的服务被称为控制层或控制平面(Control Plane)。数据层在服务身边拦截并处理服务间的网络调用,而控制层对内主要负责管理和协调代理的行为,对外为运维人员提供API,来对网格内的服务和网络进行管理和测量。
控制平面的特点:
不直接解析数据包。
与控制平面中的代理通信、下发策略和配置。
负责网络行为的可视化。
通常提供API或命令行工具,可用于配置版本化管理,便于持续集成和部署。
数据平面的特点:
通常是按照无状态目标设计的,但实际上为了提高流量转发效率,需要缓存一些数据,因此无状态也是有争议的。
直接处理入站和出站数据包,如转发、路由、健康检查、负载均衡、认证、鉴权、监控数据等。
对应用来说透明,可以做到无感知部署。
服务网格带来的变革
#1 为下沉到基础设施提供可能,实现微服务治理与业务逻辑的解耦。将微服务治理下沉到基础设施层,屏蔽了微服务治理问题的复杂度,通过把这些服务治理SDK的能力下层到基础设施,拆解为独立进程,以Sidecar的模式进行部署。使其和业务系统完全解耦,可以使开发人员更加专注于业务本身。
#2 帮助应用轻量化,专注业务:开发者无需关心通信层和服务治理的具体实现,真正像本地调用一样使用微服务,通信相关的一切工作直接交给 Service Mesh,让开发者更关注于业务的开发。
#3 异构系统的统一治理。随着新技术的发展和人员的更替,即使在同一家公司也会出现不同语言、不同框架的应用和服务。为了统一管控这些服务,以往的做法是为每种语言、每种框架都开发一套完整的SDK,不仅维护成本非常高,而且会给公司的中间件团队带来很大的挑战。有了服务网格之后,可以将主体的服务治理功能下沉到基础设施,多语言的支持就会轻松很多。只需提供一个非常轻量级的SDK,甚至在很多情况下都不需要一个单独的SDK,就可以轻松实现多语言、多协议的统一流量管控、监控等需求。
服务网格主要提供了 流量控制、安全和可观察性三个能力,这些能力不需要业务系统配合,只需要通过一些配置就可以获得。
02 Istio概述
Istio官方文档是这样定义的:“它是一个完全开源的服务网格,以透明的方式构建在现有的分布式应用中。它也是一个平台,拥有可以集成任何日志、遥测和策略系统的API接口。Istio多样化的特性使你能够成功且高效地运行分布式微服务架构,并提供保护、连接和监控微服务的统一方法。”
Istio是一个开源的Service Mesh实现产品,基于服务网格的概念提供了丰富的功能:
流量管理:Istio 的流量路由规则可以让您很容易的控制服务之间的流量和 API 调用。Istio 简化了服务级别属性的配置,比如熔断器、超时和重试,并且能轻松的设置重要的任务,如 A/B 测试、金丝雀发布、基于流量百分比切分的概率发布等。它还提供了开箱即用的故障恢复特性,有助于增强应用的健壮性,从而更好地应对被依赖的服务或网络发生故障的情况。
可观测性:Istio 为网格内所有的服务通信生成详细的遥测数据。这种遥测技术提供了服务行为的可观察性,使运维人员能够排查故障、维护和优化应用程序,而不会给服务的开发人员带来任何额外的负担。通过 Istio,运维人员可以全面了解到受监控的服务如何与其他服务以及 Istio 组件进行交互。
安全认证:Istio 安全功能提供强大的身份,强大的策略,透明的 TLS 加密,认证,授权和审计(AAA)工具来保护你的服务和数据。
可拓展性WebAssembly 是一种沙盒技术,可以用于扩展 Istio 代理(Envoy)的能力。
Istio 架构
Istio的架构由两部分组成,分别是数据平面(Data Plane)和控制平面(Control Plane)。
控制平面 – istiod
Istiod 提供服务发现、配置和证书管理。
用于控制和管理数据平面中的Sidecar代理,完成配置分发、服务发现、授权鉴权等功能。在架构中拥有控制平面的优势在于,可以统一地对数据平面进行管理。如果没有它,对网格内的代理进行配置更新操作,就不是一件轻松的事情了。
数据平面
Istio 数据平面使用 Envoy 代理的扩展版本。Envoy 是用 C++ 开发的高性能代理,用于协调服务网格中所有服务的入站和出站流量。
Istiod 将控制流量行为的高级路由规则转换为 Envoy 特定的配置,并在运行时将其传播给 Sidecar。Pilot 提取了特定平台的服务发现机制,并将其综合为一种标准格式,任何符合 Envoy API 的 Sidecar 都可以使用。
您可以使用 Istio 流量管理 API 让 Istiod 重新构造 Envoy 的配置,以便对服务网格中的流量进行更精细的控制
Istio的架构变迁
从2017年5月发布以来,Istio经历了4个重要的版本和由此划分而成的3个发展阶段,并出现了两次重大的架构变动。
0.1版本:发布于2017年5月。Istio的诞生。
1.0版本:发布于2018年7月,对外宣传生产环境可用。从0.1版本到1.0版本,历经了一年多的开发时间。
1.1版本:发布于2019年3月,号称企业级可用的版本。。
1.5版本:发布于2020年3月,进行架构的重构,将多组件整合为单体形态的istiod,开始支持WebAssembly。从1.1版本到1.5版本的一年中,Istio开始遵循季度性发布规律,进入了产品的稳定发展期。
1.6版本:发布于2020年5月,添加了新的自定义资源WorkloadEntry,开始加入对虚拟机的支持。
核心功能
流量控制
Virtual Service 和Destination Rule是Istio的自定义CR,是Istio流量路由功能最关键的两个CR。
Virtual Service:Virtual Service 基于服务网格的服务发现能力,定义了请求是如何路由到服务网格内的服务。每个Virtual Service定义了一组路由规则,Istio将会根据配置文件的顺序对规则进行校验,会讲请求匹配并路由到Virtual Service中配置到目标地址。
Destination Rule:Virtual Service 定义了流量如何路由到给定目标地址,而Destination Rule是用来定义流量在目标地址上的行为。在通过Virtual Service 路由后到流量,将根据Destination Rule中的规则应用在真实的目标地址上。
通常两个配置文件需要搭配使用,一个简单的例子:
默认将所有 HTTP 流量路由到标签为“version:v1”的评论服务的 pod。此外,路径以 “/wpcatalog/” 或 "/consumercatalog/ "开头的 HTTP 请求将被重写为 “/newcatalog” 并发送到标签为“version: v2”的 pod。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-route
spec:
hosts:
- reviews.prod.svc.cluster.local
http: - name: “reviews-v2-routes”
match:
- uri:
prefix: “/wpcatalog” - uri:
prefix: “/consumercatalog”
rewrite:
uri: “/newcatalog”
route: - destination:
host: reviews.prod.svc.cluster.local
subset: v2
- name: “reviews-v1-route”
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v1
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews-destination
spec:
host: reviews.prod.svc.cluster.local
subsets:
- name: v1
labels:
version: v1 - name: v2
labels:
version: v2
其中Virtual Service 定义了路由规则,表明了流量该如何路由到正确的服务版本,而Destination Rule定义了服务的子集,按版本为所有给定服务的实例分组。然后可以在Virtual Service 的路由规则中使用这些服务子集来控制到服务不同实例的流量。
在下面的示例中,目标规则为 my-svc Destination Rule配置了 3 个具有不同负载均衡策略的子集:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: my-destination-rule
spec:
host: my-svc
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: v1
labels:
version: v1 - name: v2
labels:
version: v2
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN - name: v3
labels:
version: v3
每个子集都是基于一个或多个 labels 定义的,在 Kubernetes 中它是附加到像 Pod 这种对象上的键/值对。这些标签应用于 Kubernetes 服务的 Deployment 并作为 metadata 来识别不同的版本。
除了定义子集之外,目标规则对于所有子集都有默认的流量策略,而对于该子集,则有特定于子集的策略覆盖它。定义在 subsets 上的默认策略,为 v1 和 v3 子集设置了一个简单的随机负载均衡器。在 v2 策略中,轮询负载均衡器被指定在相应的子集字段上。
安全
Istio中的安全架构是由多个组件协同完成的。其中,Citadel是负责安全的主要组件,用于密钥和证书的管理;Pilot会将安全策略配置分发给Envoy代理;Envoy执行安全策略,实现访问控制。
Istio提供的安全功能主要分为认证和授权两部分。
认证
对等认证(Peer Authentication):用于从服务到服务的认证。通过mTLS(mTLS)实现的,客户端和服务端彼此都要验证的合法性。Istio中提供了内置的密钥和证书管理机制,可以自动进行密钥和证书的生成、分发和轮换,而无须修改业务代码。
请求认证(Request Authentication):也被称为最终用户认证,用于验证终端用户或客户端。Istio将目前业界流行的JWT(JSON Web Token)作为实现方案。Istio的mTLS提供了一种宽容模式(Permissive Mode)的配置方式,使得服务可以同时支持纯文本和mTLS流量。用户可以先用非加密的流量确保服务间的连通性,再逐渐迁移到mTLS,这种方式极大地降低了迁移和调试的成本。Istio还提供了多种粒度的认证策略,支持网格级别、命名空间级别和工作负载级别的认证,使用户可以灵活地配置各种级别的策略和组合。
授权
Istio的授权策略可以为网格中的服务提供不同级别的访问控制,比如,网格级别、命名空间级别和工作负载级别。授权策略支持ALLOW和DENY动作,假如每个Envoy代理都运行一个授权引擎,当请求到达代理时,授权引擎就会根据当前策略评估请求的上下文,返回授权结果ALLOW或DENY。授权功能如果在没有显示开关状态时配置,则默认处于启动状态。只要将配置好的授权策略应用到对应的工作负载就可以进行访问控制了。
可观测
Istio 生成以下类型的遥测数据,以提供对整个服务网格的可观察性:
指标。Istio 基于 4 个监控的黄金标识(延迟、流量、错误、饱和)生成了一系列服务指标。Istio 还为网格控制平面提供了更详细的指标。除此以外还提供了一组默认的基于这些指标的网格监控仪表板。
分布式追踪。Istio 为每个服务生成分布式追踪 span,运维人员可以理解网格内服务的依赖和调用流程。
访问日志。当流量流入网格中的服务时,Istio 可以生成每个请求的完整记录,包括源和目标的元数据。此信息使运维人员能够将服务行为的审查控制到单个工作负载实例的级别。
03 演示Istio安装
环境要求:docker 、K8s
下载Istio
$ curl -L https://istio.io/downloadIstio | sh -
选择版本与系统类型下载
$ curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.8 TARGET_ARCH=x86_64 sh -
Istio Release
目录结构
samples/: 示例应用程序
bin/istioctl: 目录中的客户端二进制文件。
将istioctl客户端添加到您的环境变量路径:
export PATH=PATH
Istio安装
Istio提供了多种安装配置文件进行Istio的安装
选择demo配置文件安装:
$ istioctl install --set profile=demo -y
验证
成功安装后,Istio所有的组件将会被部署在 istio-system命名空间下:
$ kubectl get po -n istio-system NAME
READY STATUS RESTARTS AGE
istio-egressgateway-6b4774576-fxqjk 1/1 Running 3 44d
istio-ingressgateway-5b6f9b6995-wm97w 1/1 Running 3 44d
istiod-7845cf4755-b45t7 1/1 Running 3 44d
当所有pod运行起来后,Istio就启动成功了。
Istio中的服务部署与注入
为命名空间开启自动注入
创建一个用于测试的命名空间
$ kubectl create namespace bookinfo
为命名空间添加标签,可以为该命名空间开启自动注入,在后续部署在该命名空间下的应用程序将会自动注入Envoy Sidecar代理。
$ kubectl label namespace bookinfo istio-injection=enabled
namespace/default labeled
Sidecar 注入主要是依托k8s的准入控制器Admission Controller来实现的。
通常Sidecar注入由以下步骤完成:
解析Webhook REST请求,将AdmissionReview原始数据反序列化;
解析pod,将AdmissionReview中的AdmissionRequest反序列化;
利用Pod及网格配置渲染Sidecar配置模板;
利用Pod及渲染后的模板创建Json Patch;
构造AdmissionResponse;
构造AdmissionReview,将其发给apiserver;
BookInfo 简介
Bookinfo 应用中的几个微服务是由不同的语言编写的。这些服务对 Istio 并无依赖,但是构成了一个有代表性的服务网格的例子:它由多个服务、多个语言构成,并且 reviews服务具有多个版本。
该应用由四个单独的微服务构成。这个应用模仿在线书店的一个分类,显示一本书的信息。页面上会显示一本书的描述,书籍的细节(ISBN、页数等),以及关于这本书的一些评论。
Bookinfo 应用分为四个单独的微服务:
productpage. 这个微服务会调用 details和 reviews两个微服务,用来生成页面。
details. 这个微服务中包含了书籍的信息。
reviews. 这个微服务中包含了书籍相关的评论。它还会调用 ratings微服务。
ratings. 这个微服务中包含了由书籍评价组成的评级信息。
reviews微服务有 3 个版本:
v1 版本不会调用 ratings服务。
v2 版本会调用 ratings服务,并使用 1 到 5 个黑色星形图标来显示评分信息。
v3 版本会调用 ratings 服务,并使用 1 到 5 个红色星形图标来显示评分信息
金丝雀发布
首先需要给每个服务定义好相应的子集。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: productpage
spec:
host: productpage
subsets:
- name: v1
labels:
version: v1
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1 - name: v2
labels:
version: v2 - name: v3
labels:
version: v3
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: ratings
spec:
host: ratings
subsets:
- name: v1
labels:
version: v1 - name: v2
labels:
version: v2 - name: v2-mysql
labels:
version: v2-mysql - name: v2-mysql-vm
labels:
version: v2-mysql-vm
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: details
spec:
host: details
subsets:
- name: v1
labels:
version: v1 - name: v2
labels:
version: v2
通过创建VirtualService并设置路由规则可以配置流量的流向。这里配置一个将所有流量路由到所有服务的v1 版本。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: productpage
spec:
hosts:
- productpage
http: - route:
- destination:
host: productpage
subset: v1
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http: - route:
- destination:
host: reviews
subset: v1
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http: - route:
- destination:
host: ratings
subset: v1
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: details
spec:
hosts:
- details
http: - route:
- destination:
host: details
subset: v1
通过Istio我们可以设定流向每个版本流量的比例。我们重新修改reviews的 Virtual Service配置,模拟金丝雀发布。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 80 - destination:
host: reviews
subset: v2
weight: 20
配置了20%流量流向v2版本,80%的流量流向v1版本。刷新页面后可以看见黑色星标服务与没有星标的服务交替出现,并且出现的比例大致在1:4左右。通过不断调高v2版本的流量比例就可以实行金丝雀发布。
注:部分资料参考源自云原生社区
「深入理解Istio 云原生服务网格进阶实战」