牛顿有曰:如果说我看得比别人更远些,那是因为我站在巨人的肩膀上。 学习前人的成果,就是先努力站到巨人的肩膀上;掌握前人的成果是前进的必要过程。有些人不学就懂了,直飞“巨人的肩膀”,很牛逼,为了更好体现天才的价值,该往更远处看看了。然而很多人,刚摸到“巨人的脚”,在爬“巨人的大腿”上,甚至有些人巨人在哪呢还没找到。
好了,开始“抱腿”——Service Mesh的大腿。
1. Service Mesh
Service - 服务,各种服务,不过不是指建QQ号,拉微信消息,买域名等等具体的业务服务实例,而是一种抽象,指各种 GRPC/HTTP/FTB/SSH/Telnet 服务等等。
Mesh - 网格,最常见的造型就是横竖间隔组成的方格子,比如围棋盘,治沙干草格,防虫窗纱等等都称为mesh。也有翻译成格栅的,但是丢了"网"这种拓扑的神韵。
两个单词组合起来 Service Mesh - 翻译成"服务网格"。意思就是有一网格,把各种服务种到每个格子里,埋上土,倒上水,通上电,然后把网格放到阳光下,迎上风,能不能长出来新服务不知道,反正服务之间可以愉快的侃大山了。哈哈,是的,你没看错,这就是“服务网格”的通俗解释。莫慌,这是一种比方,继续看为啥这就是Service Mesh。
原 Twitter 工程师威廉 · 摩根(Willian Morgan) ,发起 Linkerd项目的创始人之一(另一位是Oliver Gould),并在创建的 Buoyant 公司担任 CEO。其发起的 Linkerd (第一个服务网络项目)项目催生了“Service Mesh”这个术语。由此“Service Mesh”面世并迅速的得到认可。 在他的文章《 WHAT’S A SERVICE MESH? AND WHY DO I NEED ONE? 》中定义了什么是 Service Mesh,以及为什么云原生应用需要Service Mesh。
定义原文如下:
A service mesh is a dedicated infrastructure layer for making service-to-service communication safe, fast, and reliable. WHAT IS A SERVICE MESH? A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware. (But there are variations to this idea, as we’ll see.)
在这个定义中明确说明了Service Mesh的环境,目的和实现方式三个方面:
- 云原生应用有着复杂的服务拓扑;
- Service Mesh 是一基础设施层,用于处理服务间通讯;保证请求在这些拓扑之间安全,快速,可靠的穿梭;
- Service Mesh 通常有一系列的轻量级的网络代理组成,它们与应用程序部署在一起,但是应用程序不需要知道它们的存在。
第1点,特别指明服务网格诞生的背景和应用环境。第2点,强调服务网格是一种网络模型,提供“服务-服务”这种端对端的通信抽象模型,并假设网络的不可靠和不安全性,然后由服务网格提供安全,快速,可靠的保证。第3点,意味着需要轻量级的网络代理和服务部署在一起,并拦截服务之间的调用,由这些代理做相应的“基础工作”,让服务程序不再关心这些“基础工作”,也无需感知谁在做这些工作,代理的管理协调也由服务网格负责,从而达到第2点的目标。
因此,服务网格并没有提供什么新的功能,只是将“基础工作”从服务剥离并下沉成基础设施而已。也就是开篇比方中的“风雨阳光,水土电”,让服务不再关心如何通风通水通电(构建基础设施)以及不担心断水断电(网络的不可靠性),而只关心业务的功能逻辑实现,然后“拎包入住”的“种”(部署)到网格里,并且专业技术为你提供便利服务。
服务网格在架构设计上也十分简单。实现方式就是在用户空间里,由部署在服务的“旁边”的代理,加上一组协调管理代理的过程组成。 代理称为服务网格的数据平面,管理过程称为其控制平面。
以上对定义的粗略分析,对服务网格有个大致的认识。下面针对这三点做更具体详细的讨论,讨论清楚了,也就明白了“服务网格”到底是个什么东西了。(有一些网文,花里胡哨说一堆,其实分析最本质的定义即可)
2. 服务拓扑
说到“拓扑”二字,想到大学里有一门数学课程叫拓扑学(topology),它是研究几何图形或空间在连续改变形状后还能保持一些性质不变的学科。我曾经上过这课,当时学的云里雾里的,现在全还给老师了。不过在这里不需要系统学习一遍拓扑学,涉及一堆数学理论和符号,大部分看不懂,也和本文没多大关系。
但是有个经典案例你需要知道,那就是祖师爷欧拉在300年前将哥尼斯堡七桥问题完美解决了,并发明了欧拉定理。其思想是把小岛和河岸看成点,把连接小岛和河岸的桥看成线,然后将实际的物理事物关系抽象成了数学几何图形。不关心桥是混凝土还是石拱桥,小岛绿意葱葱,繁华热闹还是人迹罕至,荒无人烟;不关心桥面多宽多长,建在河岸什么位置,小岛多大面积等等。至于画出来的图形漂不漂亮,线直还是蚂蚁线,实心圆点还是空心圆点都不在考虑范围之内。重要的是将不可变更的物理实体,抽象之后搬到一张纸上,就成了数学家的玩物,任由其摆弄了。
通过这个故事,传达一个核心思想,拓扑学只考虑物体间的位置关系而不考虑它们的形状和大小。对于计算机网络而言,这就足够了。至于连通性与紧致性这两个重要拓扑性质也不用关心(有兴趣的可以去看看)。因为在计算机网络中,仅仅利用了拓扑学中不考虑形状和大小而只研究点和线关系的方法。没有再多的拓扑学知识了。
依葫芦画瓢,把网络中的计算机和通信设备抽象为一个点,把通信链路抽象为一条线,由点和线组成的几何图形就是计算机网络的拓扑结构。网络的拓扑结构反映出网中各实体的结构关系。计算机网络常见的拓扑结构包括:星型结构,环形结构,总线型结构,树形结构,网状结构,蜂窝结构,混合拓扑结构等等。
明白了网络拓扑是什么,那么服务拓扑又是什么呢?原理是一样的,表现形式不同而已,换言之侧重点不同,服务的层次要比网络更高,不是精神层次,而是类似七层网络模型中的逻辑层次一样,是更高一层的抽象视角。服务拓扑的节点不再指网络拓扑中的实体计算机和通信设备,而是一个具体的端口,一个上层服务;线路不再是一般而言的通信链路而是服务之间的调用关系。
比如一个小公司,有一个核心的业务,几个旁支业务。以为核心业务为中心,其他旁支业务都去核心业务请求服务。如此形成一种树状的服务拓扑。随着公司规模逐渐变大,业务会随之变多而且业务拆分也更细化,那么服务自然也会越来越多。业务之间的合作伴随着服务之间的相互调用而体现。这时候服务之间的调用关系,形成一个网状服务拓扑。传统的业务服务拓扑并不会太复杂,因为服务量级不会太大。敢这样说的原因是随着微服务的兴起,服务的量级在迅速扩大。服务拓扑在发生着改变。
我们通过拓扑学的经典案例来了解拓扑学的核心思想,并介绍了如何利用拓扑学的原理来研究网络拓扑结构。最后在网络拓扑基础上说明了服务拓扑具体是什么,这样理解起来也更清晰明了。随着软件技术的不断升级换代,在微服务兴起的大背景下,服务拓扑将面临更多的问题。下面介绍一下微服务。
3. 微服务
微服务的诞生历史就不赘述了。直接看看什么是微服务。
微服务有很多种定义,业界尚未统一,所以不一而论。但是它们都包含微服务的共同特征,比如服务根据业务组织,规模通常较小,并拥有清晰的接口;可独立部署;依据自身硬件(部署环境)软件(开发语言)需要独立开发;服务之间组织比较松散等等。
这种微服务架构将传统的ABC的聚合体架构拆分成A,B,C单体的设计,看起来更加遵循“做好一件事”的 Unix 哲学。 对服务的一小部分进行更改只需重新构建并部署相关或者极少数微服务,避免了“大服务”的“牵一发而动全身”的巨大代价;对于资源消耗型的服务业务,可以实现单个微服务单独扩展,避免“吃大锅饭”,实现精准“扶贫”,资源利用的最大化,精准化,进而提高成本优化效益和运维效率。同时微服务更加的满足驱动型业务持续交付的需求,实现快速升级迭代。从管理层面来看,系统的分工更加明确,责任也更加清晰。
如此看来,微服务的思想和现实中工业产业链的分工合作思想是一样的。产业链中的每一环都是可以自主研发,升级,持续交付的,而且组织分散全球化。这样一说好像也没有什么新发明新创造,但是将其思想从一个领域引入到另外一个领域,但是这已是巨大的改变和进步。
好处讲了一堆,以为碧玉无瑕,其实不然。微服务直接带来的副作用就是服务拓扑变化,从简单的调用关系变成一团乱麻(如图所示)。
部署管理的成本在升高(这要是让开发运维人工去维护服务-服务之间的调用关系,没有人愿意干)。故障的定位变得困难。由于服务粒度变小,每个服务有自己的日志,那么定位一个问题需要看多个服务的日志。整个系统的稳定性也会下降。一个整体水桶变成多个服务拼板,稳定性取决于关键路径上最差那一个(木桶效应)。此外,从概率上讲,多服务系统要比单一系统发生故障概率要高。以及如何监控,服务治理,熔断,测试,安全等等直接问题都暴露出来了(为什么会暴露?可以和传统的服务方式对比即可)。
大致了解了什么是微服务,以及微服务的利与弊。虽然好处是推动技术升级的主要动力,但是前提是利大于弊,以及弊端是可以完美解决或者一定程度可以解决的。如何解决这些弊端是下文要阐述的内容。现在的情况是,急需解决两个难题:1. 如何运行这些服务;2.如果让服务-服务之间建立映射(通信)。
如何运行服务?开玩笑吧,这哪门子难题。扔到机器上运行不就ok了。思想没毛病,但是在微服务由五花八门的各种语言实现和其自身的环境依赖的前提下,让人工去一个个丢是不ok的。让你丢个一次两次可以ok,几十几百个服务经常让你丟,估计你就不干了。关键也不满足持续开发、集成和部署的要求。因此,急需一种统一的运行各种微服务的标准技术,这就是下面要谈的话题:容器。第2个难题是要在第一个问题解决的基础上来解决的问题,即服务治理。
4. 容器
首先简单了解一下容器的进化史。
传统的服务部署方式是直接将多个服务部署在物理机器上(如图1所示)。也就是所谓的吃“大锅饭”。每个应用程序的资源分配都是“自私”的,根据自己需要任意使用不关心其他应用程序的“死活”。虽然有OS警察管着,但是每个应用程序只要不超过OS的资源限制,一般不会被“枪毙”掉。但是资源是有限的,必然有些耗资源或者耗CPU的服务把其他服务给挤垮。换个角度讲,这也算充分利用硬件资源了。但是为了避免关键服务不被“流氓服务”坑,这样的“大锅饭”不是最佳方式,所以会选择将关键服务需要“开小灶”——独立部署专有服务器上,然而如此资源又得不到充分的利用而产生服务器资源的浪费。问题根源就是每个服务没有资源边界和隔离。
为解决上述问题,虚拟化技术被引入。虚拟化部署作为一种解决方案,它为每个服务提供了“实体隔间”,一定程度上隔离了资源和运行环境。让服务看起来自己有私有的一间房而充满安全感(安全性)。实现一定程度的伸缩性,降低硬件成本,比如将一台物理机虚拟成一集群。从图2中可以明确看出来,每一个虚拟机里都有一套完整的OS。这就意味着它们要占用底层主机很大的存储(内存和硬盘)和CPU,而且需要启动一个虚拟的OS,这将十分耗时。从实践来看,虚拟机技术的确解决了早期的问题,但是臃肿,耗资源,启动慢的弊端,让技术人员继续寻找新的解决方案。
既然“实体隔间”太耗资源,那能不能“挂个帘子不砌墙”,做成“虚拟隔间”——比如方舱,集装箱。实际证明是可行的,不行技术人员也能让它行。基于Linux的NS,Control Group(隔离CPU/内存),Union File Systems(写时复制),容器引擎等技术,容器化部署鸣笛起航了(如图3所示)。(注:不仅限于Linux)
容器是一个标准的软件单元,它将代码及其所有依赖项打包,从而使应用程序能够快速可靠地从一个计算环境运行到另一个计算环境。 一个容器映像是一个轻量级的、独立的、可执行的软件包,包括运行应用程序所需的一切: 代码、运行时、系统工具、系统库和设置。从而提供了更高效的资源隔离和资源利用。
相比虚拟机其优势在于便携、灵活和易于部署。便携是因为它很轻量级,只打包必要的BIN/LIB(如图3),不像虚拟化还要背着完整的OS。它构建不像VM,它可以基于基础镜像,根据需要定制自己的需求,而十分快速灵活。构建完成后可以方便的移植到各中环境下进行部署,而不用担心环境一致性问题,保证一次构建随意部署。比如 Docker 容器技术的口号就是:“Debug your app, not your environment——Securely build and share any application, anywhere”。
容器虚拟化技术有Docker、coreos、rocket、Pouch等等。其中 Docker 比较热门,由于其太热们导致很多人脑海里形成了“容器=Docker”的概念,其实不是。Docker只是容器技术的一种技术实现。在2015年,由Google,Docker、CoreOS、IBM、微软、红帽等厂商联合发起的OCI(Open Container Initiative)组织,并于2016年4月推出了第一个开放容器标准。
有了容器技术,回到原来的问题。不管微服务依赖什么环境,用什么语言实现的还是什么种类服务,统一打包成容器镜像到任意环境下部署就可以了,对外统一了。容器技术也是促进微服务的语言栈如此丰富的一个主要原因,让开发从此跳脱了谁是最好的语言之争。问题1解决了,那么在此基础之上,我们可以解决第2个难题了。
5. 服务治理
正如上文所述,用容器技术解决了如何运行微服务的问题,现在情况变成了:我们有一堆可运行的容器和一堆机器,如何将容器和机器之间建立映射关系以及如何管理它们。为了提高资源利用率,在大量的微服务部署容器前提下,手工决策容器部署在哪里,处理容器的动态变化以及配置显然不靠谱。因此需要一些自动化措施来调度,管理,监管和故障转移。
服务治理——应运而生了。它的典型代表是K8S(kubernetes),Mesos,Swarm。后者侧重于服务编排,但是k8s并不仅限于服务编排,它提供功能要多于服务编排的需要。下面简单了解一下K8S。
依据K8S官网的定义。K8S提供如下服务:
- 服务发现和负载均衡——使用 DNS 名称或自己的 IP 地址暴露容器服务。如果到一个容器的流量很高,那么 Kubernetes 能够负载平衡和分配网络流量,从而使部署稳定。
- 自动挂载指定的存储系统——比如本地存储、公共云提供商等等。
- 自动推出和回滚——可以以受控的速率将实际状态更改为所需状态。
- 自动装箱;——每个容器需要指定CPU 和内存资源。
- 自修复——重启失败的容器,替换容器,杀死不响应用户定义的健康检查的容器。
- 秘钥和配置管理——存储和管理敏感信息,如密码、 OAuth 令牌和 SSH 密钥;可以部署和更新机密和应用程序配置,而无需重新构建容器映像。
K8S不提供的服务包括:
- 不是传统的PaaS,但是提供了一些 PaaS 产品通用的通用特性,比如部署、缩放、负载平衡、日志记录和监视,并且这些特性是可选的和可插拔的。
- 不限制所支持的应用程序类型——包括无状态、有状态和数据处理工作负载。只要能在容器中运行,就可以在k8s中使用。
- 不提供应用程序级服务——比如中间件(例如,消息总线)、数据处理框架(例如,Spark)、数据库(例如,MySQL)、缓存,也不提供集群存储系统(例如,Ceph)作为内置服务。
- 不指定日志、监视或警报解决方案。
- 不提供也不要求配置语言 / 系统。
- 不提供也不采用任何机器配置、维护、管理或自我修复系统。
- 不仅仅是一个编排系统,Kubernetes 包括一组独立的、可自由组合的控制过程。
更多内容参考k8s官网。
至此,上述的两个难题就给解决掉了。这为服务网格诞生奠定了基础。
6. 微服务,容器,服务治理和服务网格的关系
介绍完微服务,容器,服务治理之后,需要做个总结。在谈到前面三部分内容的时候,读者心里会有一个疑问,这些内容和服务网格有半毛钱的关系?是不是跑题了?准确的讲,没有一点跑题。不是半毛钱关系而是一毛钱(十分)的关系。是因为有了这三样技术才让服务网格成为可能。这就好比DNA,RNA,蛋白质之于细胞。
微服务和容器的结合,抽象统一了运行环境,让大量新的应用程序以各种语言被实现为微服务。大量的微服务这为服务网格提供了最适合的应用环境。Docker 和 Kubernetes 的结合,让无状态、有状态和数据处理等等各种工作服务成为统一的操作对象,由 Kubernetes 为服务提供一致性操作。通过 Kubernetes 使得运行一个服务的部署时成本和运行100个服务的部署成本是没有多大区别。这满足了服务网格的操作需求。把代理打包到 Docker 里,由 Kubernetes 把它们和业务微服务部署在一起,并且部署的事情 Kubernetes 替你处理,如此提供了部署和维护 Sidecar 代理的机制。大大降低了服务网格的运维成本。
如此构成如下图所示的拓扑结构。其中灰色单元表示k8s的pod,包括两个容器,绿色表示实际的微服务(业务服务);蓝色表示 Sidecar 代理。
上文提到“服务网格并没有提供什么新的功能,只是将基础工作从服务剥离并下沉成基础设施而已”;从这张图中可以得知,绿色的微服务的网格之间的通信,由有蓝色的代理全权负责了。也就是说微服务的基础工作不再有开发工程师全权负责,而是转移到服务网格上去了。其中蓝色代理称为服务网格的数据平面,管理这些代理的过程称为控制平面。
因此,微服务,容器,服务治理都是服务网格的必要组成部分。
7. 服务网格要做什么
站在一个开发者的角度,如果实现一个只包含业务功能的服务,这只能是一个demo。因为还有更多的核心工作没有做,比如负载均衡,故障恢复,频控,审计,超时、重试、鉴权,监控,日志,追踪等等。传统开发模式下,这些核心工作一部分要伴随业务开发,一部分独立成公共组件重复来使用,无论如何都需要开发人员来关心。
服务网格打破了这个局限,一定程度上解放了开发人员。它将业务之外的“基础工作”从开发者身上剥离了,并成为一种基础功能下沉了。在服务网格定义中强调:“Service Mesh 是一基础设施层,用于处理服务间通讯;保证请求在这些拓扑之间安全,快速,可靠的穿梭”。
这个“基础设施层”至少要具有:服务发现、负载平衡、故障恢复、日志、监视、追踪、a / b 测试、金丝雀发布、蓝绿部署、频控、访问控制、网关、端到端身份验证等等。
通过k8s来看,它已经满足了其中一部分功能,但是显然没有做到全部。那么剩余的功能就需要一个新的软件来覆盖,这个优秀的代表就是Istio/Linkerd。
以Istio作为例,它具有如下功能:
- Http、 gRPC、 WebSocket 和 TCP 流量的自动负载平衡。
- 丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制。
- 一个可插拔的策略层和配置 API,支持访问控制、速率限制和配额。
- 集群内所有流量的自动指标、日志和跟踪,包括集群的进入和出口。
- 基于强身份验证和授权的集群中的安全服务对服务通信。
总结起来就是流量管理,安全管理和服务观测。
总结
任何事物发展都有前因后果,不是一蹴而就的;同理,很多思想是在已有思想基础之上建立并发展起来的。事物从简单到复杂,是一个逐渐进化,变得更高级,当然也更复杂的过程。了解其整个发展的变迁过程,循序渐进,搞懂来龙去脉,才能真正的明白并领悟到事物身上的所具有的"设计"的背后原因,内涵,而非出自拍脑袋的上帝之手。
本文从服务网格的定义起步,逐渐讨论了服务拓扑,微服务,容器,服务治理和服务网格的功能。描述性的介绍了一下服务网格是个什么东西。其具体的实现技术和具体实现细节,比如docker,k8s,istio,还需进一步的学习。
后话
服务网格作为一种网络模型,伴随着云计算,给 DevOps 团队提供了一种解决方案。如今正如火如荼的发展的。但是和人工智能,量子通信,基因遗传,比特币等等比起来,十分不起眼,因为其影响的领域相比它们要窄的多。再加上它的起步发展不是太早,也只是在圈子内专业人员知道。这篇文章也算一个入门介绍,抛砖引玉吧。
参考文献
- 《The Service Mesh: What Every Software Engineer Needs to Know about the World's Most Over-Hyped Technology》
- 《What's a service mesh? And why do I need one?》
- 《Istio Handbook》
- 《Pattern: Service Mesh》
- 《Microservices-wiki》
- 《What is Kubernetes》
- 《什么是微服务架构?》
- 《What is a Container?》
- 《kubernetes in Action》
- 《What is Istio?》
声明:图片均无版权,来源于网络,如有版权,请联系删除!!!