博客原文地址 (https://elfgzp.cn/2020/06/21/新一代的微服务架构 Service Mesh html
因为最近在工做中在作 Service Mesh
的落地项目,有很是多的感触,因此想写一篇文章来分享这个「新一代的微服务架构 Service Mesh
」。git
笔者会从如下顺序开始分享:github
首先会从 「单体应用架构」 演进到 「微服务架构」 产生的问题开始提及,到本身做为开发人员感触最深的痛点。web
而后简单介绍如下今天的主角 Istio
的服务编排环境 Kubernetes
。docker
最后从 Sidecar
这种设计,说到 Service Mesh
,最后到咱们的主角 Istio
。api
到正式的主角以前的铺垫会比较多,这是为了让大多数开发者都能理解。安全
本文大部份内容都整理自笔者的学习资料加上本身的一些总结和体会,你们最后能够从文末找到他们。服务器
从「单体」到「分布式」演进(也就是微服务化)的缘由我相信你们都很了解了。网络
由于业务量愈来愈大,咱们须要多台机器才能应对大规模的应用,因此须要垂直或者水平拆分业务系统,让其变成一个分布式的架构。架构
从上面的表格咱们能够看到,分布式系统虽然有一些优点,但也存在一些问题。
做为业务开发人员最直观的感觉:
总结来讲,微服务架构有这些痛点和须要解决的问题:
图片引用自 《左耳听风 - 分布式系统技术栈》
针对这么多的须要去解决和处理的问题。
引出了咱们今天的主角 Istio
。
在介绍咱们今天的主角 Istio
以前,先简单介绍一下它的服务编排环境 Kubernetes
。经过 Docker
以及其衍生出来的 Kubernetes
之类的软件或解决方案,大大地下降了作上面不少事情的门槛。
Docker
相信你们都很是了解了,因此这里我就从 Docker
过分讲到 k8s
。
Docker
容器这个听起来玄而又玄的概念,其实是在建立容器进程时,指定了这个进程所须要启用的一组 Namespace
参数。这样,容器就只能“看”到当前 Namespace
所限定的资源、文件、设备、状态,或者配置。而对于宿主机以及其余不相关的程序,它就彻底看不到了。
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
咱们知道,在 Linux
系统中建立线程的系统调用是 clone()
,就像这样。而当咱们用 clone()
系统调用建立一个新进程时,就能够在参数中指定 CLONE_NEWPID
参数。这时,新建立的这个进程将会“看到”一个全新的进程空间,在这个进程空间里,它的 PID
是 1。之因此说“看到”,是由于这只是一个“障眼法”,在宿主机真实的进程空间里,这个进程的 PID
仍是真实的数值,好比 100。
因此说,容器,实际上是一种特殊的进程而已。
感兴趣的同窗能够阅读 《本身动手写 Docker》 和尝试一下书中的代码。
我花了不少精力去学习 Linux
容器的原理、理解了 Docker
容器的本质,终于, Namespace
作隔离, Cgroups
作限制, rootfs
作文件系统” 这样的“三句箴言”能够朗朗上口了。
为何 Kubernetes
又忽然搞出一个 Pod
来呢?
这里提一个概念: Pod
, 是 Kubernetes
项目中最小的 API
对象。若是换一个更专业的说法,咱们能够这样描述: Pod
是 Kubernetes
项目的原子调度单位。
这里经过一个实际的例子来讲明:
咱们经过 pstree
查看操做系统中运行的进程,进程并非“孤苦伶仃”地独自运行的,而是以进程组的方式,“有原则地”组织在一块儿。
好比,这里有一个叫做 rsyslogd
的程序,它负责的是 Linux
操做系统里的日志处理。能够看到, rsyslogd
的主程序 main
, 和它要用到的内核日志模块 imklog
等,同属于 1632
进程组。这些进程相互协做,共同完成 rsyslogd
程序的职责。
若是说 「Docker 容器」的其实就是一个「特殊的进程」。
那么「K8s」就能够理解成操做系统。
Kubernetes
所作的,其实就是将 “进程组” 的概念映射到了容器技术中,并使其成为了这个云计算 “操做系统” 里的 “原子调度单位”。
不过,相信此时你可能会有第二个疑问:
对于初学者来讲,通常都是先学会了用 Docker
这种单容器的工具,才会开始接触 Pod
。而若是 Pod 的设计只是出于调度上的考虑,那么 Kubernetes
项目彷佛彻底没有必要非得把 Pod
做为“原子调度单位”吧?
首先,关于 Pod
最重要的一个事实是:它只是一个逻辑概念。
具体的说: Pod
里的全部容器,共享的是同一个 Network Namespace
,而且能够声明共享同一个 Volume
。
那这么来看的话,一个有 A
和 B
两个容器的 Pod
,不就是等同于一个容器(容器 A
)共享另一个容器(容器 B
)的网络和 Volume
?这好像经过 docker run --net --volumes-from
这样的命令就能实现,就像这样。
可是,你有没有考虑过,若是真这样作的话,容器 B
就必须比容器 A
先启动,这样一个 Pod
里的多个容器就不是对等关系,而是拓扑关系了。
因此,在 Kubernetes
项目里, Pod
的实现须要使用一个中间容器,在这个 Pod
中,中间容器永远都是第一个被建立的容器,而其余用户定义的容器,则经过 Join Network Namespace
的方式,与 中间容器关联在一块儿。
如上图所示,这个 Pod
里有两个用户容器 A
和 B
,还有一个中间容器容器。很容易理解,在 Kubernetes
项目里,中间容器必定要占用极少的资源,因此它使用的是一个很是特殊的镜像,叫做: k8s.gcr.io/pause
。这个镜像是一个用汇编语言编写的、永远处于“暂停”状态的容器,解压后的大小也只有 100~200 KB
左右。
这里就再也不深刻说明了,感兴趣的能够点击图片连接,或者在文章末尾我列出的参考资料。
其中 Pod
的一个重要的特性,它的全部容器都共享同一个 Network Namespace。这就使得不少与 Pod
网络相关的配置和管理,也均可以交给 Sidecar
完成,而彻底无须干涉用户容器。
这里最典型的例子莫过于 Istio
这个微服务治理项目了。
接下来就从 Sidecar
到 Service Mesh
来一步一步介绍 Istio 的设计思想。这里提到的 Sidecar
究竟是什么呢, Sidecar
在国内翻译为边车模式,这个翻译真的很形象。
所谓的边车模式,对应于咱们生活中熟知的边三轮摩托车。
图片引用自 《左耳听风 - 管理设计篇“边车模式”》
咱们能够经过给一个摩托车加上一个边车的方式来扩展示有的服务和功能。这样能够很容易地作到 "控制 " 和 "逻辑" 的分离。
也就是说,咱们不须要在服务中实现控制面上的东西,如监视、日志记录、限流、熔断、服务注册、协议适配转换等这些属于控制面上的东西,而只须要专一地作好和业务逻辑相关的代码,而后,由“边车”来实现这些与业务逻辑没有关系的控制功能。
图片引用自 《左耳听风 - 管理设计篇“边车模式”》
那最终这个 Sidecar
的效果就会像上图所示。
那么在 Istio
中, [Envoy](https://github.com/envoyproxy/envoy)
就是默认的 Sidecar
。它与服务容器在同一个 Pod
中,与服务容器共享同一个 Network Namespace
,接管全部通过服务容器的流量。
而后, Sidecar
集群就成了 Service Mesh
。图中的绿色模块是真实的业务应用服务,蓝色模块则是 Sidecar
, 其组成了一个网格。而咱们的应用服务彻底独立自包含,只须要和本机的 Sidecar
依赖,剩下的事全交给了 Sidecar
。
图片引用自 《左耳听风 - 管理设计篇之“服务网格”》
Service Mesh
这个服务网络专一于处理服务和服务间的通信。其主要负责构造一个稳定可靠的服务通信的基础设施,并让整个架构更为的先进和 Cloud Native
。在工程中, Service Mesh
基原本说是一组轻量级的服务代理和应用逻辑的服务在一块儿,而且对于应用服务是透明的。
说白了,就是下面几个特色。
Service Mesh
是一个基础设施。Service Mesh
是一个轻量的服务通信的网络代理。Service Mesh
对于应用服务来讲是透明无侵入的。Service Mesh
用于解耦和分离分布式系统架构中控制层面上的东西。咱们今天的主角 Istio
,它的伟大之处不仅是在设计自己,而是在于它是一个兼容并包的生态。它为整个行业提供了一种全新的开发及运维的方式。
微服务架构在网络链路上还有不少待解决的点,如链路跟踪、分布式日志、监控报警、压测演练、故障注入等。若让 Istio
官方来实现全部的功能,不只耗时,还会让整个系统变得很是臃肿。
接下来就用 Istio
的官方 Demo
来说一个实际的应用场景。
这部分会用 Istio 官方的 Demo 来演示,因此本文的大部份内容均可以在官方文档中找到。
若是有感兴趣的同窗能够跟着这个 Demo
来实践,可是可能须要一个 K8s
集群,这里推荐使用 Google Cloud Platform 的免费试用服务 GCP Free Tier - Free Extended Trials and Always Free。
固然若是想本身折腾搭建 K8s
集群的同窗能够参考笔者的这篇文章 「K8s 学习日记」Kubeadm 部署 kubernetes 集群。
可是笔者仍是建议使用谷歌的服务,体验云原生的方式。
Bookinfo
应用分为四个单独的微服务:
productpage
. 这个微服务会调用 details
和 reviews
两个微服务,用来生成页面。details
. 这个微服务中包含了书籍的信息。reviews
. 这个微服务中包含了书籍相关的评论。它还会调用 ratings
微服务。ratings
. 这个微服务中包含了由书籍评价组成的评级信息。reviews
微服务有 3 个版本:
ratings
服务。ratings
服务,并使用 1 到 5 个黑色星形图标来显示评分信息。ratings
服务,并使用 1 到 5 个红色星形图标来显示评分信息。下图展现了这个应用的端到端架构。
在实际的应用场景中,咱们当前发布了两个 Reviews
服务的 feature
版本 v2
和 v3
版本。可是若是须要对这些服务进行测试。
为了开发人员在测试本身开发的 Review
服务不受影响,咱们可能须要部署多个完整的 Bookinfo 应用
即 Product page
、 Ratings
、 Details
的服务都须要部署,以下图所示 。
官方的 BookInfo
中的微服务数量仍是比较少的,在实际的场景中,一个完整的系统可能会有成百上千个微服务共同支撑和运行,若是为了开发测试方便就须要庞大的服务器资源提供给微服务进行部署,这也是目前笔者公司的一个痛点。
在官方的 demo
中,有这样一个例子。
未来自名为 Jason
的用户的全部流量路由到服务 reviews:v2
。将请求头中 end-user
值为 jason
的全部请求指向 reviews:v2
。
正常来讲,这样的功能应该须要在具体语言的 Web
框架层进行实现,可是因为 Istio
的 Sidecar
接管了全部的流量,这个功能就在 Istio
中已经集成了。
对于开发人员来时也就是简单的一个配置和一行命令:
$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml $ kubectl get virtualservice reviews -o yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: reviews ... spec: hosts: - reviews http: - match: - headers: end-user: exact: jason route: - destination: host: reviews subset: v2 - route: - destination: host: reviews subset: v1
当 Istio
的流量控制放到实际的应用场景中时,测试环境就只须要一套完整的服务,和一些须要测试的不一样版本的服务了。
固然这只是其中一个应用场景,流量控制还能够用于 A/B
测试,灰度发布等。而且这只是 Istio
的其中一个功能。
笔者也不一一去介绍 Istio
的其余功能了,如:服务安全、链路追踪、网络拓扑、服务注册等等服务治理相关的功能,感兴趣的同窗能够阅读官方文档。
除了官方给出的 demo
, 感兴趣的同窗还能够在这个网站上找到更多的例子,https://istiobyexample.dev/ 。
以上就是笔者想分享的所有内容,在这个云计算时代,笔者相信 Service Mesh
将会成为微服务架构中的一个佼佼者,帮助咱们更好治理微服务架构。
本文由博客一文多发平台 OpenWrite 发布!